题解 CF296B 【Yaroslav and Two Strings】

eee_hoho

2020-11-11 20:25:09

Solution

考虑直接对不可比的串进行dp,设$f_i$表示前$i$个字符不可比的串的个数,$g1_i$表示前$i$个字符可比的字符串且所有$s\leq t$的个数,$g2_i$表示前$i$个字符可比的字符串且所有$s\geq t$的个数,$g3_i$表示前$i$个字符可比的字符串且$s=t$的个数。 于是考虑转移方程: 1. $s_i\neq ?,w_i\neq?$ $$\begin{cases}f_i=f_{i-1}+g1_{i-1}[s_i>w_i]+g2_{i-1}[s_i<w_i]-g3_{i-1}[s_i\ne w_i]\\g1_i=g1_{i-1}[s_i\le w_i]\\g2_i=g2_{i-1}[s_i\ge w_i]\\g3_i=g3_{i-1}[s_i=w_i]\end{cases}$$ 就是之前的方案乘和这一位相反的方案,但还要减去之前都相等的方案。 2. $s_i=?,w_i\neq?$ 有一个是问号的做法是类似的,所以我只拿一个来说。 $$\begin{cases}f_i=10f_{i-1}+(9-(w_i-'0'))g1_{i-1}+(w_i-'0')g2_{i-1}-9g3_{i-1}\\g1_i=(w_i-'0'+1)g1_{i-1}\\g2_i=(9-(w_i-'0')+1)g2_{i-1}\\g3_i=g3_{i-1}\end{cases}$$ 直接考虑问号会取到哪些值,然后用和上面一样的容斥处理方案。 3. $s_i=?,w_i=?$ $$\begin{cases}f_i=100f_{i-1}+45g1_{i-1}+45g2_{i-1}-90g3_{i-1}\\g1_i=55g1_{i-1}\\g2_i=55g2_{i-1}\\g3_i=10g3_{i-1}\end{cases}$$ 多考虑一个问号,就是多用一个求和公式算算就可以了。 最后注意下$i=1$的时候不会构成不可比的串,所以$f_1=0$ **Code** ``` cpp #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> const int N = 1e5; const int p = 1e9 + 7; using namespace std; int n,g1[N + 5],g2[N + 5],f[N + 5],g3[N + 5]; char s[N + 5],w[N + 5]; int main() { scanf("%d",&n); scanf("%s",s + 1); scanf("%s",w + 1); g1[0] = g2[0] = g3[0] = 1; for (int i = 1;i <= n;i++) { if (s[i] != '?' && w[i] != '?') { if (s[i] <= w[i]) g1[i] = g1[i - 1]; if (s[i] >= w[i]) g2[i] = g2[i - 1]; if (s[i] == w[i]) g3[i] = g3[i - 1]; f[i] = f[i - 1]; if (s[i] < w[i]) f[i] += g2[i - 1],f[i] %= p; if (s[i] > w[i]) f[i] += g1[i - 1],f[i] %= p; if (s[i] != w[i]) f[i] -= g3[i - 1],f[i] %= p; } if (s[i] == '?' && w[i] != '?') { f[i] = 10ll * f[i - 1] % p; g1[i] = 1ll * g1[i - 1] * (w[i] - '0' + 1) % p; g2[i] = 1ll * g2[i - 1] * (9 - (w[i] - '0') + 1) % p; g3[i] = g3[i - 1]; f[i] += 1ll * g1[i - 1] * (9 - (w[i] - '0')) % p; f[i] %= p; f[i] += 1ll * g2[i - 1] * (w[i] - '0') % p; f[i] %= p; f[i] -= 9ll * g3[i - 1] % p; f[i] %= p; } if (s[i] != '?' && w[i] == '?') { f[i] = 10ll * f[i - 1] % p; g1[i] = 1ll * g1[i - 1] * (9 - (s[i] - '0') + 1) % p; g2[i] = 1ll * g2[i - 1] * (s[i] - '0' + 1) % p; g3[i] = g3[i - 1]; f[i] += 1ll * g1[i - 1] * (s[i] - '0') % p; f[i] %= p; f[i] += 1ll * g2[i - 1] * (9 - (s[i] - '0')) % p; f[i] %= p; f[i] -= 9ll * g3[i - 1] % p; f[i] %= p; } if (s[i] == '?' && w[i] == '?') { f[i] = 100ll * f[i - 1] % p; g1[i] = 55ll * g1[i - 1] % p; g2[i] = 55ll * g2[i - 1] % p; g3[i] = 10ll * g3[i - 1] % p; f[i] += (45ll * g1[i - 1] % p + 45ll * g2[i - 1] % p) % p; f[i] %= p; f[i] -= 90ll * g3[i - 1] % p; f[i] %= p; } f[1] = 0; } cout<<(f[n] + p) % p<<endl; return 0; } ```