题目描述
给定三个数k,pa,pb
每次有
的概率往后面添加一个
每次有 的概率往后面添加一个
当出现了K个形如ab的子序列(不用连续)时停止
求最后子序列 ab 个数的期望
Sol
首先我们假设有长度限制,设 表示第到 个字符已经有了 个 和 个 的到最后停止的期望答案
最后答案即为
假设加a和b的概率就是 pa 和 pb
转移:
当
大于
的时候后面一部分可以直接统计答案了
但是如果没有串长限制这样下去就没完没了了 , 主要不好处理的是一下两种情况:
- 一直放 b , 这样就无限转移了
- 一直放 a , 这样也没完没了
对于情况1 , 我们可以先强制放一个 a 这样其实一开始就会有 pa 的概率
然后由于前面的 b 不影响期望的权值 , 因此我们可在计算完答案后再来考虑
对于情况 2 , 我们发现如果 已经大于 K 了的话,那么放一个 b 就会停止
可以把式子不断递归化下去 , 根据我们的极限知识和无穷递减等比数列求和公式,最后式子变成了这个(注意这时i没有意义了,由于是倒推,做到了不重不漏):
这样就可以算了
在回到开头一段有一堆 b 的情况 , 假设我们强制第一个是 a 的期望是 ,那么最后的答案
继续递降无穷等比数列求和:
所以不要管开头的 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);
}