14121: 【原4121】入阵曲
题目
题目描述
author: Ca. 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/4121
Description
小F画出了一个n×m的矩阵,每个格子里都有一个不超过k的正整数。小F想问问你,这个矩阵里有多少个不同的子矩形中的数字之和是k的倍数? 如果把一个子矩形用它的左上角和右下角描述为(x1, y1, x2, y2),其中x1≤x2, y1≤y2; 那么,我们认为两个子矩形是不同的,当且仅当他们以(x1, y1, x2, y2)表示时不同;也就是说,只要两个矩形以(x1, y1, x2, y2)表示时相同,就认为这两个矩形是同一个矩形,你应该在你的答案里只算一次。
Input Format
输入第一行,包含三个正整数 n, m, k。 输入接下来n行,每行包含m个正整数,第i行第j列表示矩阵中第i行第j列中所填的正整数 a[i,j]。
Output Format
输入一行一个非负整数,表示你的答案。
Sample Input
2 3 2
1 2 1
2 1 2
Sample Output
6
Data Range
100%的数据,n,m≤400,k≤10^6。
zqy2018's solution
#include <bits/stdc++.h>
#define INF 2000000000
#define modadd(x, y) (x + y >= k ? x + y - k: x + y)
using namespace std;
typedef long long ll;
int read(){
int f = 1, x = 0;
char c = getchar();
while(c < '0' || c > '9'){if(c == '-') f = -f; c = getchar();}
while(c >= '0' && c <= '9')x = x * 10 + c - '0', c = getchar();
return f * x;
}
int n, m, k;
int a[405][405], sum[405][405] = {0};
int cnt[1000005] = {0};
int lis[405], tot;
void init(){
n = read(), m = read(), k = read();
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j){
a[i][j] = read();
sum[i][j] = sum[i][j - 1] + a[i][j];
}
}
void solve(){
ll ans = 0;
for (int i = 1; i <= m; ++i){
for (int j = i; j <= m; ++j){
cnt[0] = 1;
tot = 1, lis[1] = 0;
int sm = 0;
for (int t = 1; t <= n; ++t){
sm = modadd(sm, (sum[t][j] - sum[t][i - 1]) % k);
ans += cnt[sm];
++cnt[sm];
lis[++tot] = sm;
}
for (int i = 1; i <= tot; ++i)
cnt[lis[i]] = 0;
}
}
printf("%lld\n", ans);
}
int main(){
init();
solve();
return 0;
}