传送门
题意:
给出 ,一开始串为空,每次有 的概率在串中加一个a, 的概率在串中加一个b,当串中有k个为ab的子序列停止加字符,求停止加字符后串中为ab的子序列的个数的期望,假设结果为最简分数 ,输出 。
Solution:
明显是一道dp题,因为长度可以无穷大,所以说我们需要考虑如何才能限制住“无穷大”,我们发现,如果我们加了一个b,ab的增加量为当前串中a的个数,所以说我们可以用一个状态 表示在串中有i个a,j个ab时开始加字符直到停止的期望ab个数,转移很显然:
那么我们最后的答案应为 ,因为在第一个a出现之前,无论有多少b,ab数量都不会变与,只有当出现第一个a时,我们加入b才会产生ab
那么我们开始考虑临界状况:
首先有一个显然的状态:
其次我们考虑的就是 的情况:在这种情况下,只要出现一个b,就会停止加字符,所以说我们只需要考虑再连续加a的个数的期望:(方便考虑我们设 )
加入n个a再加入一个b的概率为:
所以说再连续加a的个数的期望为:
设
设
运用错位相减法,
那么我们的另一个临界状态也就出来了:
然后这道题就华丽丽的做完了~
代码:
#include<cstdio>
#include<iostream>
using namespace std;
int k,pa,pb;
int f[1010][1010];
const int mod=1e9+7;
int fast_pow(int x,int a)
{
int ans=1;
for (;x;x>>=1,a=1ll*a*a%mod)
if (x&1) ans=1ll*ans*a%mod;
return ans;
}
int inv(int x)
{
return fast_pow(mod-2,x);
}
int dp(int x,int y)
{
if (y>=k) return y;
return f[x][y];
}
int main()
{
scanf("%d%d%d",&k,&pa,&pb);
for (int i=0;i<k;i++)
f[k][i]=(1ll*k+i+1ll*pa*inv(pb))%mod;
for (int i=k-1;i;i--)
for (int j=k-1;j>=0;j--)
{
f[i][j]=(1ll*dp(i+1,j)*pa+1ll*dp(i,j+i)*pb)%mod;
f[i][j]=1ll*f[i][j]*inv(pa+pb)%mod;
}
printf("%d",f[1][0]);
}