1778D Flexible String Revisit

1778D Flexible String Revisit

题目大意:

给你两个长度均为n二进制数列:S,T 每次可以把S中的一位取反,问你ST的期望方案数。

做法:

dp

我们考虑dpi表示i个不一样的位置i1个不一样的位置的期望方案数

每次有in的概率翻转一个未匹配字符,nin的概率翻转一个已匹配字符。翻转到已匹配字符需要 fi+1期望次数才能回到当前状态,然后又需要fi期望次数才能翻转一个未匹配字符。于是有方程:
fi=1+nin(fi+1+fi)

化简一下:
fi=n+(ni)fi+1i

注意

当所有字符未匹配时随意翻一个都是未匹配字符,所以fn=1
设初始状态有k个字符需要匹配,那么ans=i=1x

code

#include<bits/stdc++.h>
using namespace std;
const long long mod = 998244353;
const int N = 1e6 + 5;
int n;
char s[N] , t[N];
long long fac[N + 5] , inv[N + 5] , ans , f[N] , p;
long long ksm (long long x , long long y) {
    if(!y) 
        return 1;
    long long z = ksm (x , y / 2);
    z = z * z % mod;
    if (y & 1) 
        z = z * x % mod;
    return z;
}
void pre () {
    fac[0] = 1;
    for (int i = 1 ; i <= N ; i ++) {
        fac[i] = fac[i - 1] * i % mod;
    }
    inv[N] = ksm(fac[N] , mod - 2);
    for (int i = N - 1 ; i >= 0 ; i --) {
        inv[i] = inv[i + 1] * (i + 1) % mod;
    }
}
int main () {
    int T , dif;
    pre ();
    scanf ("%d" , &T);
    while(T --) {
        scanf ("%d" , &n);
        scanf("%s%s",s+1,t+1);
        dif = 0;
        for (int i = 1 ; i <= n ; i++) {
            if (s[i] != t[i]) {
                dif ++;
            }
        }
        inv[n] = ksm(n , mod - 2);
        f[n] = 1;
        for (int i = n - 1 ; i >= 1 ; i--) {
            f[i] = (n + (n - i) * f[i + 1] % mod) * ksm (i , mod - 2) % mod;
        }
        ans = 0;
        for (int i = 1 ; i <= dif ; i++) {
            ans = (ans + f[i]) % mod;
        }
        printf("%lld\n" , ans);
    }
    return 0;
}
posted @   2020fengziyang  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示