第八届蓝桥杯B-K倍区间(前缀和)
给定一个长度为 N 的数列,A1,A2,…AN,如果其中一段连续的子序列 Ai,Ai+1,…Aj 之和是 K 的倍数,我们就称这个区间 [i,j] 是 K 倍区间。
你能求出数列中总共有多少个 K 倍区间吗?
输入格式
第一行包含两个整数 N 和 K。
以下 N 行每行包含一个整数 Ai。
输出格式
输出一个整数,代表 K 倍区间的数目。
数据范围
1≤N,K≤100000,
1≤Ai≤100000
输入样例:
5 2
1
2
3
4
5
输出样例:
6
题目要求统计区间和为k的倍数个数
即(sum[R]-sum[L-1])%k==0的<L,R>对数量
也就是\(sum[R]\equiv sum[L-1](mod \quad k)\)
然后对每一个sum[i]取模后,我们都可从中任选两个组成一个满足条件的答案,就都有通向公式sn=n(n-1)/2;
特殊的sum[i]的值为0,单个就可以满足条件,所以加上sum[i]的个数,或者用sn=n(n+1)/2;
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=1e5+9;
#define line '\n'
inline int read(){int x=0,op=1;char c=getchar();while(!isdigit(c)){if(c=='-')op=-1;c=getchar();}while(isdigit(c))x=x*10+c-48,c=getchar();return x*op;}
unordered_map<int,int> mp;
int sum[N];
int main()
{
int n=read(),mod=read(),a;
LL ans=0;
for(int i=1;i<=n;++i){
a=read();
sum[i]=(sum[i-1]+a)%mod;
mp[sum[i]]++;
}
for(auto it:mp){
if(it.first==0)ans+=it.second;
ans+=1LL*it.second*(it.second-1)/2;
}
cout<<ans<<line;
return 0;
}

浙公网安备 33010602011771号