题目链接:https://www.luogu.com.cn/problem/P8649
思路:
看到区间和,第一反应肯定是前缀和,我们求出前缀和后对前缀和数组每一个值模k,然后对一个数组的值查看前面有几个相同的,举个例子:
样例中前缀和数组a取模后为:1 1 0 0 1
下标依次为1 2 3 4 5
当题目所求子序列以a5结尾时,已知a5=1且a5前面与a5相同的值有2个,则以a5结尾可以获得2个满足题目要求的区间
如果以a3结尾则是一个,因为实际上有一个a0=0。
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll N = 3e5 + 5;
const ll mod = 1e9 + 7;
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
void solve() {
int n; cin >> n;
ll k; cin >> k;
vector<ll>a(n + 1);
vector<ll>pre(n + 1);
vector<ll>cnt(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
pre[i] = pre[i - 1] + a[i];
}
ll ans = 0;
cnt[0] = 1;
for (int i = 1; i <= n; i++) {
ans += cnt[pre[i] % k];
cnt[pre[i] % k]++;
}
cout << ans << '\n';
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
std::cout.tie(0);
int t1 = 1;
//cin >> t1;
while (t1--)
solve();
return 0;
}