思路
这道题的数据很大,不能暴力枚举。题目中有坑:这是一个环!怎么办呢?我们可以断环为链:把整个数组复制一遍。
所以怎么计算答案呢?用 s[i] 表示前 i-1 个数的和除以 m 的余数。然后我们要找两个数 a,b ,满足 s[a] = s[b] 且 a < b 且 a + n - 1 >= b 。
但是两重循环也会超时呀!没关系,我们可以再开一个数组来维护答案。c[s[i]] 表示 max(1,i-n+1) 至 i-1 中 s[i] 出现了多少次。只是要注意:要扔掉前面太靠前的元素,然后注意在复制一遍的数组 (n+1~n*2) 里不要把 s[i] 加进去,不然计算重复了。
代码
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int n, m;
int a[400010];
int s[400010]; // 前缀和
int c[1000010]; // 统计
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
a[i] %= m;
a[i + n] = a[i]; // 复制
}
for (int i = 2; i <= 2 * n; i++)
s[i] = (s[i - 1] + a[i - 1]) % m;
long long ans = 0;
for (int i = 1; i <= n; i++)
{
ans += c[s[i]];
c[s[i]]++; // 加
}
for (int i = n + 1; i < 2 * n; i++)
{
c[s[i - n]]--; // 扔
ans += c[s[i]];
}
cout << ans << endl;
return 0;
}