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]);
}

posted @ 2022-09-08 16:10  RiverSheep  阅读(19)  评论(0)    收藏  举报