P8649 题解
Update 2024/12/4:修改了部分表述不太清楚的点。
Update 2025/7/12:考虑到大多数做本题的都是初学者,优化了表述。
题意
题目传送门
题目大意:
给定长度为
思路
首先,我们看到题目中出现了连续子序列的和,这启发我们想到前缀和,因为使用它一般可以很方便地求出一段序列的某个连续子序列的和。
因此,我们先把
但是仅仅知道了区间和也没有用,题目中还要求区间和是
不妨把区间表示出来,假设现在的区间是
由同余式的性质,上式即
也就是说,这两个前缀和对
统计了有什么用呢?假设我们现在到了第
如果我们知道了这样的
当然需要注意的是,我们现在的
代码
#include<bits/stdc++.h>
#define int long long //一定要开long long
using namespace std;
int n,k,s[100005],ans=0,b[100005];//s前缀和数组,b用于存储前缀和的模数
signed main(){
cin>>n>>k;
for(int i=1,t;i<=n;i++)
cin>>t,s[i]=s[i-1]+t; //输入并计算前缀和
for(int i=0;i<=n;i++)//注意!必须从0开始,因为0的位置也能和后面的下标构成满足条件的子序列
ans+=b[s[i]%k]++;//统计答案的同时也要加上当前余数,方便为以后的i服务
cout<<ans;
return 0;
}