如题,已打注释,是组合写法
#include<bits/stdc++.h>
using namespace std;
#define long long int
int mod=998244353;
int T,id,ansc,ansf;
int n,m,c,f;
char a[1010][1010];
//zx、hx数组即记录点(i,j)下方、右方所有可使用的点的数目(含(i,j))
int zx[1010][1010],hx[1010][1010];
signed main() {
cin>>T>>id;
while(T--) {
cin>>n>>m>>c>>f;
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
cin>>a[i][j];
}
}
//求点(i,j)右方与下方点的数量(含点(i,j) )
for(int i=n; i>=1; i--) {
for(int j=m; j>=1; j--) {
if(a[i][j]=='0') {
zx[i][j]=zx[i+1][j]+1;
hx[i][j]=hx[i][j+1]+1;
}
}
}
for(int j=1; j<=m; j++) {
int s=0;
for(int i=1; i<=n; i++) {
//如果不能种花,那么后面的所求的答案与前面的s(后文有关于s的解释)无关
if(a[i][j]=='1') {
s=0;
continue;
}
//如果是组成“C”的第一个位置(左上角处),则不计算,否则(前面有s-(hx[i-1][j]-1)种情况),共计(hx[i][j]-1)*(s-hx[i-1][j]+1)可构成“C”
if(s != hx[i-1][j]-1 && s) {
ansc = ( ansc + ( hx[i][j] - 1 ) * ( s - hx [i - 1][ j ] + 1 ) % mod ) % mod;
if(zx[i][j]>1) { //如果能构成“F”,则应当有(hx[i][j]-1)*(s-hx[i-1][j]+1)*(zx[i][j]-1)种情况可构成“F”
ansf = ( ( ansf + ( hx[i][j] - 1 ) * ( s - hx[i - 1][ j ] + 1) % mod ) % mod * ( zx[i][j] - 1 ) )%mod;
}
}
//增加s(即在(i,j)之前所有可能与答案有贡献的情况数的总和(含(i,j)) )
s=(s+hx[i][j]-1)%mod;
}
}
cout<<ansc*c<<' '<<ansf*f<<endl;
//初始化
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
hx[i][j] = zx[i][j] = 0;
}
}
ansc = ansf = 0;
}
return 0;
}