入陣曲
10.24
思路:
明顯的n3複雜度,考慮n2卡住上下界,組合數計數優化,由於模數比較小,我們維護了每一列的前綴之後,就可以O(1)計算固定上下界的前綴矩形的值了。記錄每個前綴矩形modK的餘數,記錄每種餘數有多少個,同種餘數的前綴矩形相減就是合法。清空不要用memset會T。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#define LL long long
#define N 410
using namespace std;
int n, m, k, idc=0;
int mp[N][N], res[N];
int cnt[1000010];
LL sum[N][N];
LL ans=0;
inline int read(){
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9'){ x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
int main() {
freopen ("rally.in", "r", stdin);
freopen ("rally.out", "w", stdout);
scanf("%d%d%d", &n, &m, &k);
for(register int i=1; i<=n; i++){
for(register int j=1; j<=m; j++){
mp[i][j] = read();
sum[i][j] = sum[i-1][j] + mp[i][j];
}
}
for(register int i=0; i<n; i++){
for(register int j=i+1; j<=n; j++){
LL cc = 0;
for(register int p=1; p<=m; p++){
cc = ( (cc + sum[j][p] - sum[i][p]) % k + k ) % k;
cnt[cc]++; res[++idc] = cc;
}
cnt[0]++;
for(register int x=1; x<=idc; x++){
int d = res[x];
ans += cnt[d] * (cnt[d] - 1) / 2;
cnt[d] = 0;
}
cnt[0] = 0;
idc = 0;
}
}
cout << ans << endl;
return 0;
}