​传送门​


并不是很容易想到,想到就不难…

由于是求所有满足条件的子串

那么满足条件的子串肯定有着某种特性

发现在每次把数位和加起来再转化为 k k k进制数的过程中

数位和的变化是每 k k k转化为 1 1 1

也就是丢失的是 k − 1 k-1 k−1的整数倍

换句话说每次迭代的过程中,模 k − 1 k-1 k−1的余数是不会改变的

那么我们记录一个数字前缀和 p r e [ i ] pre[i] pre[i]

当 b ! = 0 & & b ! = k − 1 b!=0\&\&b!=k-1 b!=0&&b!=k−1时,答案模 k − 1 k-1 k−1后数位和为 b b b的子串个数

当 b = = 0 b==0 b==0时,只有当子串都为 0 0 0时的子串才满足

当 b = = k − 1 b==k-1 b==k−1,转化为 b = 0 b=0 b=0求解,因为在模 k − 1 k-1 k−1的意义下所有 k − 1 k-1 k−1变成了 0 0 0

但是需要减去子串都为 0 0 0的数量

需要清楚的分类

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 2e5+10;
int k,b,n,a[maxn],res;
map<int,int>mp;
signed main()
{
cin >> k >> b >> n;
int ans = 0, pre = 1;
for(int i=1;i<=n;i++)
{
cin >> a[i];
if( a[i] ) pre = i+1;
else ans += i-pre+1;
}
if( b==0 ){ printf("%lld",ans); return 0; }
if( b==k-1 ) ans = -ans, b = 0;
else ans = 0;
mp[0] = 1;
for(int i=1;i<=n;i++)
{
res = ( res+a[i] )%(k-1);
ans += mp[(res-b+k-1)%(k-1) ];
mp[res]++;
}
cout << ans;
}