为啥这么一道弱题难了我好久。。。
考虑一维的情况,维护前缀和,其中余数用一个桶来维护,前缀和相等的其差的余数一定相等,于是在桶里搜就好。
二维把每一个竖列的线段区间压成一维即可。
一维转二维啊
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=405;
const int maxk=1000005;
int n,m,K,cnt;
long long ans;
int s[maxn][maxn],dp[maxn][maxn],sum[maxn][maxn];
int bucket[maxk];
int vst[maxn];
int main()
{
scanf("%d%d%d",&n,&m,&K);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&s[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
dp[i][j]=(dp[i][j-1]+s[i][j])%K;
for(int j=1;j<=m;j++)
for(int i=1;i<=n;i++)
sum[i][j]=(sum[i-1][j]+dp[i][j])%K;
for(int k=1;k<=n;k++)
for(int i=k;i<=n;i++)
{
for(int j=1;j<=cnt;j++)
bucket[vst[j]]=0;
cnt=0;
bucket[0]=1;
for(int j=1;j<=m;j++)
{
int now=((sum[i][j]-sum[k-1][j])%K+K)%K;
vst[++cnt]=now;
ans+=bucket[now];
bucket[now]++;
}
}
printf("%lld",ans);
return 0;
}