入阵曲 (组合数 余数统计)

来源:互联网 发布:淘宝华佗大药房怎么样 编辑:程序博客网 时间:2024/05/24 06:39

入阵曲

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 410using 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;}
原创粉丝点击