Let dp[i][j] be the expected answer given that there are i subsequences of the form ‘a’ in the prefix and j subsequences of the form ‘ab’ in the prefix.
Then, we have something like dp[i][j] = (pa * dp[i + 1][j] + pb * dp[i][i + j]) / (pa + pb).The first term in this sum comes from adding another ‘a’ to our sequence, and the second comes from adding a ‘b’ to our sequence. We also have dp[i][j] = j if j ≥ k as a base case.
The answer should be dp[0][0].
官方题解说的比较清楚了。dp[i][j]表示前缀有i个a,j个ab的期望个数。
则显然有转移:
dp[i][j] = (pa ∗ dp[i + 1][j] + pb ∗ dp[i][i + j]) / (pa + pb).
答案就是dp[0][0]。
问题在于边界如何确定。首先我们根据题意有
dp[i][j]=j,j>=k
。
序列中可能会有任意多个a,因为我们可以一直往里扔a,不扔b。
那么我们的边界显然不能只限定j。我们发现当i+j>=k时,只要再出现一个b,这个序列就一定会结束。因此当i+j>=k时,我们手动算一下期望个数,作为边界。还有一个问题,在出现第一个a之前,我可能会有无限个b。但是我们发现,这些b对答案完全没有影响。或者我们可以列出一个方程:
dp[0][0]=(pa∗dp[1][0]+pb∗dp[0][0])/(pa+pb)
dp[0][0]就等于dp[1][0]!所以答案就是dp[1][0]即可。
那么如何计算i+j>=n时的期望个数呢?记个数为ANS,i+j=k,则:
ANS=pbpa+pb∗∑j=0inf(papa+pb)j∗(k+j)
拿等比数列什么的算一算可以得到:
ANS=k+pa/pb
,即i+j+pa/pb。
因此我们就可以dp了。复杂度
O(n2)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 1100
#define mod 1000000007
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,pa,pb,invb,invab,f[N][N];//f[i][j]表示前缀有i个a,j个ab的期望个数
inline int ksm(int x,int k){
int res=1;
for(;k;k>>=1,x=(ll)x*x%mod)
if(k&1) res=(ll)res*x%mod;return res;
}
inline int dp(int i,int j){
if(j>=n) return j;
if(i+j>=n) return (i+j+(ll)pa*invb)%mod;
if(f[i][j]!=-1) return f[i][j];
f[i][j]=((ll)pa*dp(i+1,j)+(ll)pb*dp(i,i+j))%mod*invab%mod;
return f[i][j];
}
int main(){
// freopen("a.in","r",stdin);
n=read();pa=read();pb=read();memset(f,-1,sizeof(f));
invb=ksm(pb,mod-2);invab=ksm(pa+pb,mod-2);
printf("%d\n",dp(1,0));
return 0;
}