CF296B Yaroslav and Two Strings
\(\text{Solution}\)
一道简单的\(DP\),没有需要转弯的地方,思路较为顺畅。
考虑每一位的填法是独立的,设\(f_{i,0/1/2/3}\)表示填到第\(i\)位,当前的状态为\(s < w\)或\(s > w\)或\(s = w\)或\(s\)和\(w\)不可比。易得转移
\[f[i][0] = f[i - 1][0] * (a[i][0] + a[i][2]) + f[i - 1][2] * a[i][0]
\]
\[......
\]
\[f[i][3] = f[i - 1][0] * a[i][1] + f[i - 1][1] * a[i][0] + f[i - 1][3] * (a[i][0] + a[i][1] + a[i][2])
\]
其中\(a_{i,0/1/2}\)为第\(i\)位的状态位\(0/1/2\)时的方案数,其余转移类似。
\(\text{Code}\)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#define LL long long
#define RE register
#define IN inline
using namespace std;
const int N = 1e5 + 5,P = 1e9 + 7;
int n; LL a[N][3],f[N][4];
char s1[N],s2[N];
int main()
{
scanf("%d%s%s",&n,s1 + 1,s2 + 1);
for (int i = 1; i <= n; i++)
{
LL x = s1[i] - '0',y = s2[i] - '0';
if (s1[i] != '?' && s2[i] != '?') a[i][(x == y ? 2 : (x < y ? 0 : 1))] = 1;
if (s1[i] != '?' && s2[i] == '?') a[i][2] = 1,a[i][0] = 9 - x,a[i][1] = x;
if (s1[i] == '?' && s2[i] != '?') a[i][2] = 1,a[i][0] = y,a[i][1] = 9 - y;
if (s1[i] == '?' && s2[i] == '?') a[i][2] = 10,a[i][0] = a[i][1] = 45;
}
f[0][2] = 1;
for (int i = 1; i <= n; i++)
{
f[i][0] = (f[i - 1][0] * (a[i][0] + a[i][2]) % P + f[i - 1][2] * a[i][0] % P) % P;
f[i][1] = (f[i - 1][1] * (a[i][1] + a[i][2]) % P + f[i - 1][2] * a[i][1] % P) % P;
f[i][2] = f[i - 1][2] * a[i][2] % P;
f[i][3] = (f[i - 1][0] * a[i][1] % P + f[i - 1][1] * a[i][0] % P + f[i - 1][3] * (a[i][0] + a[i][1] + a[i][2]) % P) % P;
}
printf("%lld\n",f[n][3]);
}

浙公网安备 33010602011771号