CF1778D Flexible String Revisit 题解
题意
给出两个长度均为
每次随机将
问:第一次
思路
首先我们得目的是将两串不匹配的位置使得它能够匹配。
我们定义状态
这个时候我们要从状态
-
修改的位置恰好能匹配上,期望是
\frac{i}{n} 。 -
修改的位置不能匹配上,那这个时候不匹配的个数会从
i 变成i+1 ,期望是\frac{n-i}{n} ,那这个时候还要采用f_{i+1} 来转移回i ,再从i 转移到i-1 。
是能够证明只有这两种情况的,因为上下两个串要不然就是匹配,要不然就是不匹配,那修改要不然会改错,要不然就是改对了。
表现成状态转移方程是这样的:
化简过后会变成:
这样就能线性递推求解了,最后的答案
其中
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
char a[N],b[N];
int n,dp[N],mod=998244353;
int qmi(int a,int b){
int res=1;
while(b){
if(b&1){
res=(res*a)%mod;
}
a=(a*a)%mod;
b>>=1;
}
return res%mod;
}
int inv(int x){
return qmi(x,mod-2);
}
signed main(){
int T;
cin>>T;
while(T--){
cin>>n;
cin>>(a+1)>>(b+1);
int nums=0;
for(int i=1;i<=n;i++){
// cout<<a[i]<<" "<<b[i]<<endl;
if(a[i]!=b[i]) nums++;
}
for(int i=n;i>=1;i--){
dp[i]=((n-i)*dp[i+1]%mod+n)*inv(i)%mod;
}
int res=0;
for(int i=1;i<=nums;i++){
res=(res+dp[i])%mod;
}
cout<<res<<endl;
}
}