【CF 908D】New Year and Arbitrary Arrangement

洛谷链接

题目描述

给定三个数k,pa,pb
每次有 p a p a + p b \frac{pa}{pa+pb} ​ 的概率往后面添加一个 a a

每次有 p b p a + p b \frac{pb}{pa+pb} 的概率往后面添加一个 b b

当出现了K个形如ab的子序列(不用连续)时停止

求最后子序列 ab 个数的期望

Sol

首先我们假设有长度限制,设 f [ i ] [ j ] [ k ] f[i][j][k] 表示第到 i i 个字符已经有了 j j a a k k a b ab 的到最后停止的期望答案

最后答案即为 f [ 0 ] [ 0 ] [ 0 ] f[0][0][0]
假设加a和b的概率就是 pa 和 pb
转移:
f [ i ] [ j ] [ k ] = p a f [ i + 1 ] [ j + 1 ] [ k ] + p b f [ i + 1 ] [ j ] [ j + k ] f[i][j][k]=pa*f[i+1][j+1][k]+pb*f[i+1][j][j+k]
j + k j+k 大于 K K 的时候后面一部分可以直接统计答案了

但是如果没有串长限制这样下去就没完没了了 , 主要不好处理的是一下两种情况:

  1. 一直放 b , 这样就无限转移了
  2. 一直放 a , 这样也没完没了

对于情况1 , 我们可以先强制放一个 a 这样其实一开始就会有 pa 的概率
然后由于前面的 b 不影响期望的权值 , 因此我们可在计算完答案后再来考虑

对于情况 2 , 我们发现如果 j + k j+k 已经大于 K 了的话,那么放一个 b 就会停止

可以把式子不断递归化下去 , 根据我们的极限知识和无穷递减等比数列求和公式,最后式子变成了这个(注意这时i没有意义了,由于是倒推,做到了不重不漏):

f [ j ] [ k ] = ( i + j ) + p a p b f[j][k]=(i+j)+\frac{pa}{pb}

这样就可以算了

在回到开头一段有一堆 b 的情况 , 假设我们强制第一个是 a 的期望是 E E ,那么最后的答案 E a n s = p a E + p b p a E + p b 2 p a E + . . . . . . . E_{ans}=pa*E+pb*pa*E+pb^2*pa*E+.......

继续递降无穷等比数列求和:
E a n s = E E_{ans}= E

所以不要管开头的 b

(应该也可以通过期望的线性性来理解)

代码:

#include<bits/stdc++.h>
using namespace std;
int k,pa,pb;
const int mod=1e9+7;
const int N=1001;
inline int fpow(int x,int k)
{
	register int res=1;
	while(k){
		if(k&1) res=1ll*res*x%mod;
		x=1ll*x*x%mod;k>>=1;
	}
	return res;
}
int f[N][N];
int D;
int dfs(int i,int j)
{
	if(i+j>=k) return f[i][j]=(i+j+D)%mod;
	if(f[i][j]!=0) return f[i][j];
	f[i][j]=1ll*pa*dfs(i+1,j)%mod+1ll*pb*dfs(i,i+j)%mod;
	f[i][j]%=mod;
	return f[i][j];
}
int main()
{
	scanf("%d %d %d",&k,&pa,&pb);
	register int inv=fpow(pa+pb,mod-2);
	pa=1ll*pa*inv%mod;pb=1ll*pb*inv%mod;
	D=1ll*pa*fpow(pb,mod-2)%mod;
	dfs(1,0);
	printf("%lld\n",1ll*f[1][0]%mod);
}

猜你喜欢

转载自blog.csdn.net/element_hero/article/details/82771980