经过参考了各位大哥的代码和题解,我终于大概是了解了这题的思路
题意:
给定一个字符串,求字符串内任意连续子串组成的数字可以被
p
p
p整除的个数
思路:
首先我们从字符串的地位进行考虑
当
p
=
2
o
r
p
=
5
p = 2 or p=5
p=2orp=5时,此时我们考虑有最后一位数字可以被整除的必定对答案有贡献所以我们把这种情况单独提出来
其次我们考虑这样一个公式: 如果
s
[
i
−
−
j
]
=
(
s
[
i
]
−
s
[
j
]
)
1
0
j
−
i
+
1
s[i--j]=\frac{(s[i]-s[j])}{10^{j-i+1}}
s[i−−j]=10j−i+1(s[i]−s[j])
所以这个时候只要
s
[
i
]
%
p
s[i]\%p
s[i]%p和
s
[
j
]
%
p
s[j]\%p
s[j]%p模数相同则对答案有贡献
这个时候我们还需要对
q
[
r
e
s
]
q[res]
q[res]++
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10,M = 1e4 + 10;
char s[N];
int q[M];
ll ans;
int main()
{
int p,n;
cin >> n >> p;
cin >> s+1;
if(p == 2 || p == 5)
{
for(int i = n;i >= 1;i--)
{
if((s[i] - '0') % p == 0)ans += i;
}
}
else
{
q[0] = 1;int po = 1,res = 0;
for(int i = n;i >= 1;i--)
{
res = (res + (s[i] - '0') * po) % p;
po = po * 10 % p;
ans += q[res];//处理到i位时,连续余数和为now的个数是cnt[now],当前余数和now与之前余数和now,作差为0,那么之间的余数和为0的数能找到cnt[now]个,这就是能被p整除的数量。
q[res]++;
}
}
cout << ans;
return 0;
}