1. 程式人生 > 實用技巧 >CF296B Yaroslav and Two Strings(DP)

CF296B Yaroslav and Two Strings(DP)

題意翻譯

如果兩個只包含數字且長度為nn的字串ss和ww存在兩個數字1\leq i,j\leq n1i,jn,使得s_i<w_i,s_j>w_jsi<wi,sj>wj,則稱ss和ww是不可比的。現在給定兩個包含數字和問號且長度為nn的字串,問有多少種方案使得將所有問號替換成0到9的數字後兩個字串是不可比的?

題解:

/*
 *CF296B
 *線性DP
 *dp(i,k)表示遍歷到第i位兩個字串的狀態
 *k=0:前面沒有大於或小於
 *k=1:前面只有大於
 *k=2:前面只有小於
 *k=3:前面既有小於又有大於
 */
#include<bits/stdc++.h>
using
namespace std; const int maxn=2e5+100; const int mod=1e9+7; typedef long long ll; ll dp[maxn][4]; int n; string s,t; int main () { scanf("%d",&n); cin>>s>>t; dp[0][0]=1; for (int i=1;i<=n;i++) { if (s[i-1]!='?'&&t[i-1]!='?') { if (s[i-1]==t[i-1
]) { dp[i][0]=dp[i-1][0]; dp[i][1]=dp[i-1][1]; dp[i][2]=dp[i-1][2]; dp[i][3]=dp[i-1][3]; } else if (s[i-1]<t[i-1]) { dp[i][0]=0; dp[i][1]=0; dp[i][2]=dp[i-1][2]+dp[i-1
][0];dp[i][2]%=mod; dp[i][3]=dp[i-1][3]+dp[i-1][1];dp[i][3]%=mod; } else if (s[i-1]>t[i-1]) { dp[i][0]=0; dp[i][1]=dp[i-1][0]+dp[i-1][1];dp[i][1]%=mod; dp[i][2]=0; dp[i][3]=dp[i-1][2]+dp[i-1][3];dp[i][3]%=mod; } } else if (s[i-1]=='?'&&t[i-1]!='?') { int t1='9'-t[i-1]; int t2=t[i-1]-'0'; dp[i][0]=dp[i-1][0]; dp[i][1]=dp[i-1][1]*(t1+1)%mod+dp[i-1][0]*t1%mod;dp[i][1]%=mod; dp[i][2]=dp[i-1][2]*(t2+1)%mod+dp[i-1][0]*t2%mod;dp[i][2]%=mod; dp[i][3]=dp[i-1][1]*t2%mod+dp[i-1][2]*t1%mod+dp[i-1][3]*10%mod;dp[i][3]%=mod; } else if (s[i-1]!='?'&&t[i-1]=='?') { int t2='9'-s[i-1]; int t1=s[i-1]-'0'; dp[i][0]=dp[i-1][0]; dp[i][1]=dp[i-1][1]*(t1+1)%mod+dp[i-1][0]*t1%mod;dp[i][1]%=mod; dp[i][2]=dp[i-1][2]*(t2+1)%mod+dp[i-1][0]*t2%mod;dp[i][2]%=mod; dp[i][3]=dp[i-1][1]*t2%mod+dp[i-1][2]*t1%mod+dp[i-1][3]*10%mod;dp[i][3]%=mod; } else { int t1=45; int t2=45; int t3=10; dp[i][0]=dp[i-1][0]*t3; dp[i][1]=dp[i-1][1]*(t1+t3)%mod+dp[i-1][0]*t1%mod;dp[i][1]%=mod; dp[i][2]=dp[i-1][2]*(t2+t3)%mod+dp[i-1][0]*t2%mod;dp[i][2]%=mod; dp[i][3]=dp[i-1][1]*t2%mod+dp[i-1][2]*t1%mod+dp[i-1][3]*(t1+t2+t3)%mod;dp[i][3]%=mod; } } printf("%lld\n",dp[n][3]); }