D. Flexible String Revisit(期望) Codeforces Round #848 (Div. 2)

题意:

给你两个二进制串a,b。你可以将a中的任意一位进行反转(0->1, 1->0)。问将a变成b操作次数的期望值是多少。

思路:

自己是看了幻想家协会会长: 讲解视频才会做的这道题,讲的很透彻。

首先我们先求出a和b其实有多少个位置不同用cnt来记录。如果cnt=0直接输出0就是了。
那么我们每一次操作无非就两种结果cnt+1, cnt-1。那么就此我们可以列出一个关于期望的式子f(x),他的意思就是有x个位置不同变成相同的期望值。
f ( x ) = 1 + x n f ( x − 1 ) + n − x n f ( n + 1 ) f(x) = 1+\frac{x}{n}f(x-1)+\frac{n-x}{n}f(n+1) f(x)=1+nxf(x1)+nnxf(n+1)
式子的讲解:首先你一定会操作一次,操作过后的效果无非就两种,第一你把相同的改成不同也就是 n − x n f ( n + 1 ) \frac{n-x}{n}f(n+1) nnxf(n+1)从相同中的去选,第二你把不同的改成相同的 x n f ( x − 1 ) \frac{x}{n}f(x-1) nxf(x1)从不同中的去选。

那么我们就此往下递推:
f ( n ) = f ( n − 1 ) + 1 < 1 > . f ( n − 1 ) = 1 + n − 1 n f ( n − 2 ) + 1 n f ( n ) < 2 > f(n) = f(n-1)+1 <1>\\ . \\ f(n-1) = 1+\frac{n-1}{n}f(n-2)+\frac{1}{n}f(n)<2>\\ f(n)=f(n1)+1<1>.f(n1)=1+nn1f(n2)+n1f(n)<2>
将1式带入2式,我们就可以得出:
f ( n − 1 ) = A ∗ f ( n − 2 ) + B . . f ( k ) = A k ∗ f ( k − 1 ) + B k f(n-1) = A*f(n-2)+B \\ .\\ .\\ f(k) = A_k*f(k-1)+B_k f(n1)=Af(n2)+B..f(k)=Akf(k1)+Bk
由此我们已知退出f(1),f(0)是等与0的那么 f ( 1 ) = B 1 f(1) = B_1 f(1)=B1,我们按照上式已知往下推我们就可以推出 B 1 B _1 B1
然后再有f(1)推出f(cnt),求出答案;

代码:

#include<bits/stdc++.h>

#define IOS ios::sync_with_stdio(false);cin.tie(nullptr)
#define int long long
#define endl "\n"

using namespace std;

const int N = 2e6 + 10, mod = 998244353;

int ksm(int a, int b)
{
	int ans = 1;
	while(b) 
	{
		if(b & 1) ans =  ans*a %mod;
		a = a * a % mod;
		b >>= 1;
	}
	return ans;
}

int n, m, k, _;
char s1[N], s2[N];
int arr[N], brr[N];

void solve()
{
	cin >> n >> s1+1 >> s2+1;
	int cnt = 0;
	for(int i = 1; i <= n; i ++)
		if(s1[i] != s2[i]) cnt++;

	if(cnt == 0)
	{
		cout << 0 << endl;
		return;
	} 

	arr[n] = brr[n] = 1;

	for(int i = n-1; i >= 1; i --)
	{
		int t = ksm((n - (n-i) * arr[i+1]) % mod + mod, mod-2);
		arr[i] = i * t % mod;
		brr[i] = (n+ (n-i) * brr[i+1]) % mod * t % mod;
		//cout << t << " " << arr[i] << " " << brr[i] << endl;
	}
	int ans = brr[1];
	for(int i = 2; i <= cnt; i ++) ans = (ans * arr[i] + brr[i]) % mod;

	cout << ans << endl;

}

signed main()
{
	IOS;
	cin >> _;
	while(_--)
		solve();
	return 0;
}

补充

这里对于arr[i], brr[i]的推导代码进行讲述一下,自己最开始也很疑惑。
∵ f ( k ) = A k ∗ f ( k − 1 ) + B k ; . f ( n − i ) = 1 + i n ∗ f ( n − i − 1 ) + n − i n ∗ f ( n ) ; . f ( n − i ) = 1 + i n ∗ f ( n − i − 1 ) + n − i n ∗ ( A i ∗ f ( i − 1 ) + B i ) ; . f ( n − i ) = 1 + i n ∗ f ( n − i − 1 ) + n − i n ∗ A i ∗ f ( i − 1 ) + n − i n ∗ B i ; . ( 1 − n − i n ∗ A i ) f ( n − i ) = i n ∗ f ( n − i − 1 ) + n − i n ∗ B i + 1 ; . n − ( n − i ) ∗ A i n ∗ f ( n − i ) = i n ∗ f ( n − i − 1 ) + ( n − i ) B i + n n ; . f ( n − i ) = n n − ( n − i ) ∗ A i ∗ ( i n ∗ f ( n − i − 1 ) + ( n − i ) B i + n n ) ; . f ( n − i ) = 1 n − ( n − i ) ∗ A i ∗ ( i ∗ f ( n − i − 1 ) + ( n − i ) B i + n ) ; \because f(k) = A_k*f(k-1)+B_k; \\ .\\ f(n-i) = 1+\frac{i}{n} * f(n-i-1) + \frac{n-i}{n}*f(n);\\ .\\ f(n-i) = 1+\frac{i}{n} * f(n-i-1) + \frac{n-i}{n}*( A_{i}*f(i-1)+B_{i});\\ .\\ f(n-i) = 1+\frac{i}{n}*f(n-i-1) + \frac{n-i}{n}* A_{i}*f(i-1)+ \frac{n-i}{n}*B_{i};\\ .\\ (1-\frac{n-i}{n}*A_i)f(n-i) = \frac{i}{n}*f(n-i-1)+\frac{n-i}{n}*B_i+1;\\ .\\ \frac{n-(n-i)*A_i}{n}*f(n-i) = \frac{i}{n}*f(n-i-1)+\frac{(n-i)B_i+n}{n};\\ .\\ f(n-i) = \frac{n}{n-(n-i)*A_i}*(\frac{i}{n}*f(n-i-1)+\frac{(n-i)B_i+n}{n});\\ .\\ f(n-i) = \frac{1}{n-(n-i)*A_i}*(i*f(n-i-1)+(n-i)B_i+n); f(k)=Akf(k1)+Bk;.f(ni)=1+nif(ni1)+nnif(n);.f(ni)=1+nif(ni1)+nni(Aif(i1)+Bi);.f(ni)=1+nif(ni1)+nniAif(i1)+nniBi;.(1nniAi)f(ni)=nif(ni1)+nniBi+1;.nn(ni)Aif(ni)=nif(ni1)+n(ni)Bi+n;.f(ni)=n(ni)Ain(nif(ni1)+n(ni)Bi+n);.f(ni)=n(ni)Ai1(if(ni1)+(ni)Bi+n);
代码中的t = 1 n − ( n − i ) ∗ A i \frac{1}{n-(n-i)*A_i} n(ni)Ai1就是这么来的。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值