rt
hi,j 是点 (i,j) 向右的最长非0块长
li,j 是点 (i,j) 向下的最长非0快长
变量 C,F 存对应答案
#include <bits/stdc++.h>
#define ull unsigned long long
#define ll long long
using namespace std;
const ll N=1010;
const ll MOD=998244353;
ll rd(int x);
int T,id;
int n,m,c,f;
ll C,F;
int a[N][N];
ll h[N][N],l[N][N];
void debug()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
printf("%d ",h[i][j]);
}
puts("");
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
printf("%d ",l[i][j]);
}
puts("");
}
}
void init()
{
// memset(a,0,sizeof(a));
// memset(h,0,sizeof(h));
// memset(l,0,sizeof(l));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
a[i][j]=0;
h[i][j]=0;
l[i][j]=0;
}
}
C=0,F=0;
}
int main()
{
#ifdef local
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#endif
T=rd(0),id=rd(0);
while(T--)
{
init();
n=rd(0),m=rd(0),c=rd(0),f=rd(0);
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=rd(1);
for(int i=1;i<=n;i++)
{
for(int j=m;j>=1;j--)
{
if(!a[i][j]&&h[i][j+1]) h[i][j]=h[i][j+1]+1;
else h[i][j]=(a[i][j])?0:1;
}
}
for(int j=1;j<=m;j++)
{
for(int i=n;i>=1;i--)
{
if(!a[i][j]&&l[i+1][j]) l[i][j]=l[i+1][j]+1;
else l[i][j]=(a[i][j])?0:1;
}
}
// debug();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]||h[i][j]<2) continue;
if(c&&l[i][j]>=3)
{
for(int k=i+2;k<=i+l[i][j]-1;k++)
{
C=(C+(ll)(h[i][j]-1)*(h[k][j]-1)%MOD+MOD)%MOD;
}
}
if(f&&l[i][j]>=4)
{
for(int k=i+2;k<i+l[i][j]-1;k++)
{
F=(F+(
(h[i][j]-1)*(l[k][j]-1)*(h[k][j]-1))%MOD+MOD)%MOD;
}
}
}
}
printf("%lld %lld\n",c*C,f*F);
}
#ifdef local
fclose(stdin);
fclose(stdout);
#endif
return 0;
}
ll rd(int z)
{
ll x=0,f=1,cnt=0;
char c=getchar();
while(!isdigit(c))
{
if(c=='-') f=-1;
c=getchar();
}
while(isdigit(c))
{
x=(x<<1)+(x<<3)+(c^48);
cnt++;
if(cnt==z) return x*f;
c=getchar();
}
return x*f;
}