阿生上学的路上从左到右有N棵树编号(1~N),其中第i个颗树有和谐值Ai。
阿生认为,如果一段连续的树,它们的和谐值之和可以被M整除,那么这个区间整体看起来就是和谐的。
现在阿生想请你帮忙计算一下,满足和谐条件的区间的数量。
输入格式:
第一行,有2个整数N和M,表示树的数量以及计算和谐值的参数。
( 1 <= N <= 100,000, 1 <= M <= 100 )
第二行,有N个整数Ai, 分别表示第i个颗树的和谐值。
( 0 <= Ai <= 1,000,000,000 )
输出格式:
共1行,每行1个整数,表示满足整体是和谐的区间的数量。
输入样例:
在这里给出一组输入。例如:
5 2
1 2 3 4 5
输出样例:
在这里给出相应的输出。例如:
6
思路:显然是问你哪些区间和是M的整数倍,自然我们可以想到去暴力枚举区间左右端点,然后去解决这个问题,但是会超时!
我们记这个区间为[l, r], 显然我们经过前缀和处理了之后, 区间和变成了s[r] - s[l - 1],想要这个数是M的整数倍,那么是否意味着s[r] = k1 * M + k, s[l - 1] = k2 * M + k, 可以自己思考一下。
随后可以显然得到s[r] 与 s[l - 1] % M 必须相同才行。
所以当我们从左到右扫描的时候,选择该点作为右端点,那么区间数就等于之前统计的 s[左]出现的次数。
同时需要注意, l - 1可能取到0, 记得把0的这个左端点加上。
code:
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
#define endl '\n'
#define rep(i,a,n) for (int i = a; i < n; i ++ )
#define repn(i,a,n) for (int i = a; i <= n; i ++ )
#define pb push_back
#define IOS ios::sync_with_stdio(false); cin.tie(0);cout.tie(0);
typedef long long ll;
typedef pair<int,int> PII;
ll gcd(ll a,ll b) { return b ? gcd(b,a % b) : a; }
int n, k;
const int N = 1e6 + 10;
int a[N], cnt[N];
int main(){
IOS;
cin >> n >> k;
repn(i, 1, n){
cin >> a[i];
a[i] %= k;
a[i] = (a[i] + a[i - 1]) % k;
}
ll ans = 0;
for (int i = 1; i <= n; i ++ )
ans += cnt[a[i]] ++;
ans += cnt[0];
cout << ans << endl;
return 0;
}