Codeforces Round #848 (Div. 2)D. Flexible String Revisit-dp、初等数学
题目:https://codeforces.com/problemset/problem/1778/D
场内打的,首先很容易想到答案来自于a、b不同的位置有几个,设\(f_k\)表示当前有k个不同的位置要复原到完全一样需要多少操作,则\(f_k=\frac{k}{n} f_{k-1}+\frac{n-k}{n}f_{k+1}+1\),边界\(f_0=0\),以及特殊的\(f_n=1+f_{n-1}\)
赛时我还企图去做一个递推发现有点行不通,毕竟只是div2的D题应该也用不上什么数学技巧,所以其实盯着边界,考虑设\(f_k=f_{k-1}+x_k\),则\(x_n=1\),然后\(f_k=\frac{k}{n}f_{k-1}+1+\frac{n-k}{n}(f_k+x_{k+1})\),就得到\(x_k=\frac{n}{k}(1+\frac{n-k}{n} x_{k+1})\),然后这样就可以递推出\(x_1\),然后得到\(f_1\),进一步就可以递推了
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define endl '\n'
typedef long long ll;
using namespace std;
const int MOD=998244353;
const int N=1e6+5;
ll ksm(ll a,ll b){
ll ret=1;a%=MOD;
for(;b;b>>=1,a=a*a%MOD)if(b&1)ret=ret*a%MOD;
return ret;
}
ll inv(ll x){return ksm(x,MOD-2);}
int n;
string a,b;
ll f[N],x[N];
int main(){
int T;cin>>T;
while(T--){
cin>>n>>a>>b;
int cnt=0;
rep(i,0,n-1)if(a[i]!=b[i])cnt++;
x[n]=1;
for(int i=n-1;i>=1;i--)x[i]=(1ll*(n-i)*inv(i)%MOD*x[i+1]%MOD+1ll*n*inv(i)%MOD)%MOD;
f[0]=0;f[1]=x[1];
rep(i,1,n-1)f[i+1]=(1ll*n*f[i]%MOD+(MOD-1ll*i*f[i-1]%MOD)%MOD+MOD-n)%MOD*inv(n-i)%MOD;
cout<<f[cnt]<<endl;
}
return 0;
}