Problem
∑ k 不 含 m 子 串 e k / n \sum_{k不含m子串}e^{k/n} k不含m子串∑ek/n
n , m ≤ 1 0 9 n,m\le 10^9 n,m≤109
Solution
经典数位DP。
f i , j , 0 / 1 , 0 / 1 f_{i,j,0/1,0/1} fi,j,0/1,0/1 表示构造到第 i i i位,匹配到第 j j j位,是否达上届,是否是前导 0 0 0.
C++里 e x p ( k ) = e k exp(k)=e^k exp(k)=ek,且精度很高。
转移注意一个显然的性质是 e x + y = e x p ( x ) ∗ e x p ( y ) e^{x+y}=exp(x)*exp(y) ex+y=exp(x)∗exp(y).
最后注意当 m = 0 m=0 m=0时的前导 0 0 0
Code
#include <bits/stdc++.h>
#define F(i, a, b) for (int i = a; i <= b; i ++)
typedef double db;
using namespace std;
char s[12], t[12];
int n, m, a[12], b[12], sum, ten[12], nx[12];
db f[12][12][2][2], ans;
int main() {
freopen("calc.in", "r", stdin);
freopen("calc.out", "w", stdout);
scanf("%s%s", s + 1, t + 1);
n = strlen(s + 1), m = strlen(t + 1), ten[0] = 1;
F(i, 1, n) a[i] = s[i] - '0', sum = sum * 10 + a[i], ten[i] = ten[i - 1] * 10;
F(i, 1, m) b[i] = t[i] - '0';
int j = 0;
F(i, 2, m) {
while (j && b[j + 1] != b[i]) j = nx[j];
if (b[j + 1] == b[i]) j ++;
nx[i] = j;
}
f[1][0][0][1] = 1;
F(x, 1, a[1]) {
if (m == 1 && x == b[m]) continue;
f[1][x == b[1]][x == a[1]][0] += exp((db)x * ten[n - 1] / sum);;
}
F(i, 1, n - 1) F(j, 0, m - 1)
F(p, 0, 1) F(q, 0, 1) if (f[i][j][p][q])
F(x, 0, ((p == 1) ? (a[i + 1]) : (9))) {
if (q == 1 && x == 0 && b[1] == 0)
f[i + 1][0][0][1] += f[i][j][p][q];
if (j == m - 1 && x == b[m])
continue;
if (q == 1) {
f[i + 1][x == b[1]][0][x == 0] += f[i][j][p][q] * exp((db) x * ten[n - i - 1] / sum);
}
else {
int y = j;
while (y && b[y + 1] != x) y = nx[y];
if (b[y + 1] == x) y ++;
f[i + 1][y][(p == 1) & (a[i + 1] == x)][0] += f[i][j][p][q] * exp((db) x * ten[n - i - 1] / sum);
}
}
F(j, 0, m - 1)
ans = (ans + f[n][j][0][0] + f[n][j][0][1] + f[n][j][1][0] + f[n][j][1][1]);
printf("%.3lf\n", ans - 1);
}