题目大意:
给定整数k,pa,pb。
初始有一个空序列,每次往末尾添加一个字符,有pa/(pa+pb)的概率添加a,有pb/(pa+pb)的概率添加b。
当ab作为子序列出现了至少k次的时候停止,问此时ab子序列出现次数的期望。对10^9+7取模。
1<=k<=1000,1<=pa,pb<=10^6。
解题思路:
设
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示当前有
i
i
i 个a,
j
j
j 个ab子序列到停止时的期望,那么
f
[
i
]
[
j
]
=
p
a
p
a
+
p
b
f
[
i
+
1
]
[
j
]
+
p
b
p
a
+
p
b
f
[
i
]
[
j
+
i
]
f[i][j]=\frac{pa}{pa+pb}f[i+1][j]+\frac{pb}{pa+pb}f[i][j+i]
f[i][j]=pa+pbpaf[i+1][j]+pa+pbpbf[i][j+i]
其实以上都不是重点,重点在于定下目标状态和终止状态值。
1.目标状态:
如果我们把目标状态定为
f
[
0
]
[
0
]
f[0][0]
f[0][0],那么
f
[
0
]
[
0
]
=
(
p
a
∗
f
[
1
]
[
0
]
+
p
b
∗
f
[
0
]
[
0
]
)
/
(
p
a
+
p
b
)
f[0][0]=(pa*f[1][0]+pb*f[0][0])/(pa+pb)
f[0][0]=(pa∗f[1][0]+pb∗f[0][0])/(pa+pb)会死循环,相当于一开始会有无穷多个b:bbbbb…….bbbbaababa…
但也可推出
f
[
0
]
[
0
]
=
f
[
1
]
[
0
]
f[0][0]=f[1][0]
f[0][0]=f[1][0],所以目标状态应为
f
[
1
]
[
0
]
f[1][0]
f[1][0]。
2.终止状态:
当
i
+
j
≥
k
i+j\ge k
i+j≥k 时,再出现一个b就会停止,所以当
i
+
j
≥
k
i+j\ge k
i+j≥k
f
[
i
]
[
j
]
=
(
i
+
j
)
B
+
(
i
+
j
+
1
)
A
B
+
(
i
+
j
+
2
)
A
2
B
+
.
.
.
f[i][j]=(i+j)B+(i+j+1)AB+(i+j+2)A^2B+...
f[i][j]=(i+j)B+(i+j+1)AB+(i+j+2)A2B+...用差比数列的方法计算可得
f
[
i
]
[
j
]
=
i
+
j
+
p
a
p
b
f[i][j]=i+j+\frac{pa}{pb}
f[i][j]=i+j+pbpa
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
if(c=='-')c=getchar(),f=-1;
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=1005,mod=1e9+7;
int k;ll pa,pb,inv_pb,f[N][N];
ll Pow(ll x,int y)
{
ll res=1;
for(;y;y>>=1,x=x*x%mod)
if(y&1)res=res*x%mod;
return res;
}
ll dfs(int i,int j)
{
if(i+j>=k)return (i+j+pa*inv_pb)%mod;
if(f[i][j]!=-1)return f[i][j];
return f[i][j]=(dfs(i+1,j)*pa+dfs(i,j+i)*pb)%mod;
}
int main()
{
//freopen("lx.in","r",stdin);
memset(f,-1,sizeof(f));
k=getint(),pa=getint(),pb=getint();
pa=pa*Pow(pa+pb,mod-2)%mod,pb=(1-pa+mod)%mod,inv_pb=Pow(pb,mod-2);
printf("%lld\n",dfs(1,0));
return 0;
}