卧薪尝胆,厚积薄发。
入阵曲
Date: Sun Oct 28 08:39:19 CST 2018 In Category: NoCategory

Description:

给一个矩阵,问有多少子矩阵和是 $k$ 的倍数。
$1\leqslant n,m\leqslant 400,1\leqslant k\leqslant 10^6$

Solution:

先枚举一下矩形的上下边界,然后扫过一行把所有前缀和放到一个桶里,顺便统计一下答案即可。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
inline int rd()
{
register int res = 0,f = 1;
register char c = getchar();
while(!isdigit(c))
{
if(c == '-')f = -1;
c = getchar();
}
while(isdigit(c))
{
res = (res << 1) + (res << 3) + c - '0';
c = getchar();
}
return res * f;
}
int n,m,k;
#define MAXN 410
#define MAXK 1000010
int a[MAXN][MAXN];
int s[MAXN][MAXN];
int sum(int r1,int c1,int r2,int c2)
{
return (s[r2][c2] - s[r1 - 1][c2] - s[r2][c1 - 1] + s[r1 - 1][c1 - 1] + 2 * k) % k;
}
int bask[MAXK];
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j)
a[i][j] = rd();
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j)
s[i][j] = ((s[i - 1][j] + s[i][j - 1]) % k - s[i - 1][j - 1] + k + a[i][j]) % k;
long long ans = 0;
for(int i = 1;i <= n;++i)
{
for(int j = i;j <= n;++j)
{
++bask[0];
for(int k = 1;k <= m;++k)
{
ans += bask[sum(i,1,j,k)];
++bask[sum(i,1,j,k)];
}
--bask[0];
for(int k = 1;k <= m;++k)
{
--bask[sum(i,1,j,k)];
}
}
}
cout << ans << endl;
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡