题目
思路:
先
将
每
个
人
拥
有
的
桃
子
数
量
减
1
,
再
将
其
求
出
前
缀
和
(
求
的
同
时
直
接
m
o
d
k
)
先将每个人拥有的桃子数量减1,再将其求出前缀和(求的同时直接mod k)
先将每个人拥有的桃子数量减1,再将其求出前缀和(求的同时直接modk)
这
样
就
可
以
将
连
续
x
个
人
的
桃
子
数
之
和
m
o
d
k
等
于
人
数
转
换
为
求
前
缀
和
数
组
相
同
数
字
时
的
组
合
情
况
,
(
1.
注
意
:
此
时
的
长
度
不
能
超
过
k
,
由
题
意
可
得
,
桃
子
和
m
o
d
的
值
一
定
小
于
k
这样就可以将连续x个人的桃子数之和mod k等于人数转换为求前缀和数组相同数字时的组合情况,(1.注意:此时的长度不能超过k,由题意可得,桃子和mod的值一定小于k
这样就可以将连续x个人的桃子数之和modk等于人数转换为求前缀和数组相同数字时的组合情况,(1.注意:此时的长度不能超过k,由题意可得,桃子和mod的值一定小于k
此时还要注意两个细节:
1.mp[0]初始值为1,如果在k以前有sum的位置为0那么一定成立;
2.当遍历过程中超过k值时要减去mp之前标记的价值,原因同上(1.注意处)
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
ll sum[N],ans;
map<ll,ll>mp;
signed main(){
std::ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
int n,k,x;cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>x;
sum[i]=(sum[i-1]+(--x)+k)%k;
}
mp[0]++;
for(int i=1;i<=n;i++){
if(i>=k)mp[sum[i-k]]--;
if(mp.count(sum[i]))ans+=mp[sum[i]];//mp.count()比mp[]快一点
mp[sum[i]]++;
}
cout<<ans<<endl;
return 0;
}