#蓝桥杯2017年第八届真题-k倍区间**
题目:
思路:
区间和可以看作是前缀和的差
a
r
r
[
l
,
r
]
=
S
[
r
]
−
S
[
r
−
l
−
1
]
arr[l,r]=S[r]-S[r-l-1]
arr[l,r]=S[r]−S[r−l−1]
那么问题就转换成的有多少对前缀和的差能够整除k
S
[
r
]
−
S
[
r
−
l
−
1
]
≡
0
(
m
o
d
k
)
S[r]-S[r-l-1]≡0(mod k)
S[r]−S[r−l−1]≡0(modk)
S [ r ] ( m o d ) k − S [ r − l − 1 ] ( m o d ) k ≡ 0 S[r](mod)k-S[r-l-1](mod)k≡0 S[r](mod)k−S[r−l−1](mod)k≡0
S [ r ] ( m o d ) k ≡ S [ r − l − 1 ] ( m o d ) k S[r](mod)k≡S[r-l-1](mod)k S[r](mod)k≡S[r−l−1](mod)k
所以题目就拆分成为找多少对前缀和的值对 k k k取余是一样的 ,最后再加上单独取余 k k k为 0 0 0的个数,因为我们前面求的是两两一组相减的 k k k倍区间,单独的 k k k倍区间没有算进去
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define MAX 500100
int main()
{
ll sum[MAX];//前缀和对k取余的值
ll hashmap[MAX];//余数的值出现的次数
ll n,k;
cin>>n>>k;
for(int i=1;i<=n;i++) {
int a;
cin>>a;
sum[i]=(sum[i-1]+a)%k;
}
ll cont=0;
for(int i=1;i<=n;i++){
cont+=hashmap[sum[i]];//判断在这之前有多少对(mod)k值一样的前缀
hashmap[sum[i]]++;
}
cont+=hashmap[0];//最后加上单独k倍的次数
cout<<cont<<endl;
return 0;
}