- 序列划分(division)
求条,(求条要付硬币的别来)
- @ 2026-9-2 17:05:01
#include <bits/stdc++.h>
using namespace std;
#define N 1000005
#define P (int)(1e9 + 7)
char s[N];
int n, d, d2 = 1, pre[N], pw[N], inv[N], val[N], f[N][2], sum1[N], sum2[N], cnt2, cnt5;
int exgcd(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1; y = 0;
return a;
}
int d = exgcd(b, a % b, x, y);
int t = x;
x = y;
y = t - (a / b) * y;
return d;
}
int main() {
scanf("%s%d", s + 1, &d);
n = strlen(s + 1);
// init cnt2 and cnt5
for (; !(d & 1); ++cnt2, d >>= 1, d2 <<= 1);
for (; !(d % 5); ++cnt5, d /= 5, d2 *= 5);
// init hash
pw[0] = 1;
for (int i = 0, y; i <= n; i++) {
if (i) pw[i] = pw[i - 1] * 10 % d,
pre[i] = (pre[i - 1] * 10 + s[i] - '0') % d;
exgcd(pw[i], d, inv[i], y);
inv[i] = (inv[i] % d + d) % d;
val[i] = 1LL * pre[i] * inv[i] % d;
}
// dp
f[0][1] = 1;
int all = 1, k = max({1, cnt2, cnt5});
for (int i = 1; i <= n; i++) {
// upd
if (i >= k) {
int j = i - k;
sum1[val[j]] = (0LL + sum1[val[j]] + f[j][0] + f[j][1]) % P;
sum2[val[j]] = (sum2[val[j]] + f[j][1]) % P;
}
// calc
int res1 = 0, res2 = 0;
if (i >= k) {
int num = 0;
for (int j = i - k + 1; j <= i; j++)
num = (num * 10 + s[j] - '0') % d;
if (!num)
res1 = sum1[val[i]], res2 = sum2[val[i]];
} int st = max(0, i - k + 1);
int cur = 0, pw10 = 1;
for (int j = i - 1; j >= st; --j) {
cur = (cur + 1LL * (s[j + 1] - '0') * pw10 % d) % d;
pw10 = pw10 * 10 % d;
if (!cur) res1 = (0LL + res1 + f[j][0] + f[j][1]) % P,
res2 = (res2 + f[j][1]) % P;
}
f[i][0] = (all - res2 + P) % P;
f[i][1] = res1;
all = (all + f[i][1]) % P;
} printf("%d\n", (f[n][0] + f[n][1]) % P);
return 0;
}
样例一输出 ,没救了
1 条评论
-
sxyTicoh I LV 6 @ 2026-10-6 21:19:41已A,此贴结。
- 1
信息
- ID
- 2719
- 时间
- ms
- 内存
- MiB
- 难度
- 8
- 标签
- (无)
- 递交数
- 109
- 已通过
- 9
- 上传者