---
# System prepended metadata

title: Codeforces 1778D Flexible String Revisit
tags: [math, dp, probabilities]

---

# Codeforces 1778D Flexible String Revisit
## 給兩個長度n之字串a和b，且其都由0或1組成，定義操作為隨機挑a中一個字元，如果為1則將其變0，為0則將其變1，問操作幾步使a變為b之期望操作步數(變為b後停止操作)，$n \le 10^6$。
> https://codeforces.com/contest/1778/problem/D

定義dp(i)為起始狀態a與b之字元相等個數有i個，期望操作幾步使得a等於b，然後我們很容易得到：
\begin{array}{ll}
& dp(i) = 1 + \frac{i}{n}dp(i-1) + \frac{n-i}{n}dp(i+1)  \\
& dp(n) = 0 \\
& dp(0) = 1 + dp(1)
\end{array}
然後然後我就不會了==，感謝這位大老的想法又讓可憐菜雞學到一招遞推化簡技巧QQ
>https://codeforces.com/blog/entry/111780?#comment-999204
>
觀察上面第三式發現dp第0項只與dp第一項有關，考慮dp(1):

\begin{array}{ll}
& dp(1) = 1 + \frac{1}{n}dp(0) + \frac{n-1}{n}dp(2)
\end{array}

可以發現上式中dp(0)可直接拆成dp(1)與常數再化簡，則式子變為:
\begin{array}{ll}
& dp(1) = \alpha + \beta dp(2)
\end{array}

照這邏輯則dp(i)僅會跟dp(i+1)和兩個常數f(i),g(i)有關，可以得到:
\begin{array}{ll}
& dp(i) = f(i) + g(i) dp(i+1)
\end{array}
將最一開始之遞迴式之dp(i-1)代換掉比較係數可得:
\begin{array}{ll}
f(i) = \frac{n + if(i-1)}{n - ig(i-1)},\
g(i) = \frac{n - i}{n - ig(i-1)}
\end{array}
然後 就沒有然後了==
```cpp=
#include <bits/stdc++.h>
#pragma GCC optimize(3)
#define ll long long
#define pii pair<int, int>
#define pll pair<long long, long long>
#define F first
#define S second
#define endl '\n'
using namespace std;
const int inf = 0x3f3f3f3f;
const int mod = 998244353;


ll qmul(ll x, ll y){
    ll cur = x, ans = 1;
    while(y > 0){
        if(y & 1) ans = (ans * cur) % mod;
        cur = (cur * cur) % mod;
        y >>= 1;
    }
    return ans;
}


void solve(){
    int n; cin >> n;
    string a, b; cin >> a >> b;
    int cnt = 0;
    for(int i=0; i<n; i++) if(a[i] == b[i]) cnt++;

    ll f[n+1], g[n+1], dp[n+1];
    f[0] = g[0] = 1;
    for(int i=1; i<=n-1; i++){
        ll inv = (n - g[i-1] * i % mod) % mod;
        if(inv < 0) inv += mod;
        inv = qmul(inv, mod - 2);
        f[i] = (n + f[i-1] * i) % mod * inv % mod;
        g[i] = (n - i) * inv % mod;
    }

    dp[n] = 0;
    for(int i=n-1; i>=cnt; i--){
        dp[i] = f[i] + g[i] * dp[i+1];
        dp[i] %= mod;
    }

    cout << dp[cnt] << endl;

} 


int main(){
    ios::sync_with_stdio(0); cin.tie(0);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    
    int t =1;
    cin >> t;
    while(t--)
    solve();
    return 0;
}
```

###### tags: `dp` `probabilities` `math`