You are given three integers k, pa and pb.
You will construct a sequence with the following algorithm: Initially, start with the empty sequence. Each second, you do the following. With probability pa / (pa + pb), add 'a' to the end of the sequence. Otherwise (with probability pb / (pa + pb)), add 'b' to the end of the sequence.
You stop once there are at least k subsequences that form 'ab'. Determine the expected number of times 'ab' is a subsequence in the resulting sequence. It can be shown that this can be represented by P / Q, where P and Q are coprime integers, and . Print the value of .
The first line will contain three integers integer k, pa, pb (1 ≤ k ≤ 1 000, 1 ≤ pa, pb ≤ 1 000 000).
Print a single integer, the answer to the problem.
1 1 1
2
3 1 4
370000006
The first sample, we will keep appending to our sequence until we get the subsequence 'ab' at least once. For instance, we get the sequence 'ab' with probability 1/4, 'bbab' with probability 1/16, and 'aab' with probability 1/8. Note, it's impossible for us to end with a sequence like 'aabab', since we would have stopped our algorithm once we had the prefix 'aab'.
The expected amount of times that 'ab' will occur across all valid sequences is 2.
For the second sample, the answer is equal to .
/*
题意:从一个空串开始每次在串的末尾添加a或b,几率分别为pa和pb,而一旦在整个串中产生了k个及以上的'ab'子序列(a、b可以分开),
操作就会停止,现在需要求结束后串中'ab'序列总个数的期望
思路:看了网上各路大神的思路才懂了一点点。
把不断增长串的过程看成是树,每个节点后面都有两个分叉,即为后一位添加a或b,在每个节点中储存的就是从这个节点这个状态开始
向后添加a、b所得到的'ab'序列总个数的期望,这样从所有最末的状态(达到k个'ab'子序列)就可以递推到最初的状态(即空串)的期望
结果。
令dp[i][j]表示前缀包含i个a,j个ab子串的所有字符串,得到的期望ab子串个数。
转移:
在此前缀后添上a:dp[i][j]+=dp[i+1][j]*Pa/(Pa+Pb)
在此前缀后添上b:dp[i][j]+=dp[i][j+i]*Pb/(Pa+Pb)
初始状态:dp[i][j]=j (j≥k)
目标状态:dp[0][0](无前缀,代表所有串)
然而由于有些无穷的情况(有无穷多a),所以这是不可行的。
但是考虑dp[i][j](i+j≥k) ,可以先把这个的期望通过数学方法算出来,继而在通过递归算出目标情况。
这种情况下,只有后面出现一个b就会立即停止操作。
设它后面添加的串中'ab'序列个数为ans,P=pb/(pa+pb)则:
ans=(1-P)*P*1+((1-P)^2)*P*2+((1-P)^3)*P*3+...
计算得ans=pa/pb
则dp[i][j]=i+j+pa/pb
此外,由于最终序列中必然有至少一个a,目标状态可以使用dp[1][0]
分数取模:
(a/b)%m=(a*b^(m-2))%m
*/
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
#define maxk 1010
#define MOD 1000000007
typedef __int64 LL;
LL k,pa,pb;
LL dp[maxk][maxk];
LL quick_pow(LL x,LL p)
{
LL ans=1;
while(p)
{
if(p&1)ans=(ans*x)%MOD;
p>>=1;
x=(x*x)%MOD;
}
return ans;
}
LL DP(int i,int j)
{
if(i+j>=k)
{
return (i+j+(pa*quick_pow(pb,MOD-2))%MOD)%MOD;
}
if(dp[i][j]!=-1)
{
return dp[i][j];
}
return dp[i][j]=(((pa*DP(i+1,j))%MOD+(pb*DP(i,i+j))%MOD)*quick_pow(pa+pb,MOD-2))%MOD;
}
int main()
{
while(~scanf("%I64d%I64d%I64d",&k,&pa,&pb))
{
memset(dp,-1,sizeof(dp));
printf("%I64d\n",DP(1,0));
}
}