G-小圆前辈的数组_长沙学院2021校赛(重现赛) (nowcoder.com)
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
long long s[N];
vector<long long> ve[N];
int main(){
long long n,k,z;
scanf("%lld %lld %lld",&n,&k,&z);
for(long long i=1;i<=n;i++){
scanf("%lld",&s[i]);
s[i]=s[i]+s[i-1];//前缀和统计和数
ve[s[i]%k].push_back(s[i]); //将所有和%k相同的下标存到一起
}
//因为a[i]%k=a[j]%k则(a[i]-a[j])%k=0
long long res=0;
for(long long i=1;i<=n;i++){
if(s[i]<z) continue;//如果和小于z则自动跳过
if(s[i]%k==0) res++;//如果自身%k等于0那么自身就可以成为一种情况
long long num=s[i]-z;//num指的是和目前统计的差值为z的前缀和可能性
int ver=upper_bound(ve[s[i]%k].begin(),ve[s[i]%k].end(),num)-ve[s[i]%k].begin()+1-1;//此为从这个下标之前的都是和s[i]%k相同的且差值大于z的个数
res=res+ver;
//ver处+1-1是为了更好理解,+1是因为ve的下标是从0开始,而-1是因为我们找的是差值大于等于z的,二分找到的是第一个大于他的值,所以要-1;
}
printf("%lld\n",res);
return 0 - 0;
}