题意:对于k进制数x,定义d(x)为x个数位的和的k进制表示.若结果超过一位,则继续执行.
7进制下 d(3504)=d(3+5+0+4)=d(15)=d(1+5)=d(6)=6
若d(x)=b,则称x为幸运的.
2<=k<=1e9, 0<=b<k , 1<=n<=1e5.
给出k进制下的n个数位[a[1],a[2]...a[n]],以及b,问其中有多少个子串是幸运的?
因为每个x的最终价值都是1<=val<k的.那么知道[i,j-1]的价值x,可以容易知道[i+1,j]的价值y.
val=x+a[j] val最大为2*k-2 若val>=k 则进位,十位为1,个位为val-k.最后结果:1+val-k<=k-1.
直接枚举计算O(n^2) TLE.
(a[L]+a[L+1]+..a[R]) 每次若有两个数相加超过k,则会用一个1和余k部分来代替.
那么d[L,R]等价于(a[L]+a[L+1]+.a[R]) %(k-1) 的值.(若最后余数为0,则结果为k-1)
现在求出前缀p[i]%(k-1)的值.
枚举右端点r,要想知道有多少个左端点L,满足d[L,R]==b.
那么 d[L-1]+b = d[r] (mod k-1) .两边同时减去b.
d[L-1] = d[r]-b (modk-1)
7进制下 d(3504)=d(3+5+0+4)=d(15)=d(1+5)=d(6)=6
若d(x)=b,则称x为幸运的.
2<=k<=1e9, 0<=b<k , 1<=n<=1e5.
给出k进制下的n个数位[a[1],a[2]...a[n]],以及b,问其中有多少个子串是幸运的?
因为每个x的最终价值都是1<=val<k的.那么知道[i,j-1]的价值x,可以容易知道[i+1,j]的价值y.
val=x+a[j] val最大为2*k-2 若val>=k 则进位,十位为1,个位为val-k.最后结果:1+val-k<=k-1.
直接枚举计算O(n^2) TLE.
(a[L]+a[L+1]+..a[R]) 每次若有两个数相加超过k,则会用一个1和余k部分来代替.
那么d[L,R]等价于(a[L]+a[L+1]+.a[R]) %(k-1) 的值.(若最后余数为0,则结果为k-1)
现在求出前缀p[i]%(k-1)的值.
枚举右端点r,要想知道有多少个左端点L,满足d[L,R]==b.
那么 d[L-1]+b = d[r] (mod k-1) .两边同时减去b.
d[L-1] = d[r]-b (modk-1)
注意当b==0的时候 只能取a[i]==0的区间.
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e5+5; ll k,b,n,a[N],pre[N]; map<ll,ll> cnt; int main() { ios::sync_with_stdio(false); cin.tie(0); cin>>k>>b>>n; ll res=0,z=0,t=0; for(int i=1;i<=n;i++) { cin>>a[i]; pre[i]=(pre[i-1]+a[i])%(k-1); if(a[i]==0) t++,z+=t; else t=0; } if(b==0) { cout<<z<<'\n'; return 0; } cnt[0]++; for(int i=1;i<=n;i++) { ll val=(pre[i]-b+k-1)%(k-1); res+=cnt[val]; cnt[pre[i]]++; } if(b==k-1) res-=z; cout<<res<<'\n'; return 0; }