题目大意: 给出 k , p a , p b k,pa,pb k,pa,pb,一开始有一个空序列,每次有 p a p a + p b \frac {pa} {pa+pb} pa+pbpa 的概率在末尾放一个 a a a,有 p b p a + p b \frac {pb} {pa+pb} pa+pbpb 的概率在末尾放一个 b b b,当存在 k k k 个形如 a b ab ab 的子序列时停止,问最后期望有多少个 a b ab ab 子序列。
题解
值得注意的是,同一个 a a a 可以存在于多个子序列 a b ab ab 中, b b b 也是。
那么每一次放
b
b
b 时,就要考虑到前面有多少个
a
a
a,假如有
j
j
j 个,那么子序列数量就要加
j
j
j。那么就能顺理成章的得到
d
p
dp
dp 数组的定义:设
f
[
i
]
[
j
]
f[i][j]
f[i][j] 表示有
i
i
i 个子序列,
j
j
j 个
a
a
a 的序列的期望答案,方程为:
f
[
i
]
[
j
]
=
p
a
p
a
+
p
b
f
[
i
]
[
j
+
1
]
+
p
b
p
a
+
p
b
f
[
i
+
j
]
[
j
]
f[i][j]=\frac {pa} {pa+pb}f[i][j+1]+\frac {pb} {pa+pb}f[i+j][j]
f[i][j]=pa+pbpaf[i][j+1]+pa+pbpbf[i+j][j]
最后,还要考虑到你是非酋的情况,有可能最后放了很多个 a a a 都放不出一个 b b b,导致 j j j 太大然后爆炸,于是我们需要判断,当 i + j ≥ k i+j\geq k i+j≥k 时,此时但凡只要来一个 b b b 就能停止。
设
x
=
p
a
p
a
+
p
b
,
y
=
p
b
p
a
+
p
b
x=\frac {pa} {pa+pb},y=\frac {pb} {pa+pb}
x=pa+pbpa,y=pa+pbpb于是有:
f
[
i
]
[
j
]
=
i
+
j
+
0
y
+
1
x
y
+
2
x
2
y
+
3
x
3
y
+
.
.
.
=
i
+
j
+
x
y
(
1
+
2
x
+
3
x
2
+
4
x
3
+
.
.
.
)
\begin{aligned} f[i][j]&=i+j+0y+1xy+2x^2y+3x^3y+...\\ &=i+j+xy(1+2x+3x^2+4x^3+...)\\ \end{aligned}
f[i][j]=i+j+0y+1xy+2x2y+3x3y+...=i+j+xy(1+2x+3x2+4x3+...)
里面这个柿子是个经典的数列求和,学过生成函数的肯定很眼熟,推导一下就是:
1
+
2
x
+
3
x
2
+
4
x
3
+
.
.
.
=
(
1
+
x
+
x
2
+
x
3
+
.
.
.
)
2
1+2x+3x^2+4x^3+...=(1+x+x^2+x^3+...)^2
1+2x+3x2+4x3+...=(1+x+x2+x3+...)2
右边是一个等比数列,那就好办了,设最后一项为 n n n,则有 1 + x + x 2 + x 3 + . . . = 1 − x n 1 − x 1+x+x^2+x^3+...=\frac {1-x^n} {1-x} 1+x+x2+x3+...=1−x1−xn
由于 0 < x < 1 0<x<1 0<x<1, n n n 趋于无穷大,所以 x n x^n xn 趋于 0 0 0,不妨就当成 0 0 0,就得到 1 + x + x 2 + x 3 + . . . = 1 1 − x 1+x+x^2+x^3+...=\frac 1 {1-x} 1+x+x2+x3+...=1−x1,于是那个数列就等于 1 ( 1 − x ) 2 \frac 1 {(1-x)^2} (1−x)21。
因为 x + y = 1 x+y=1 x+y=1,所以 1 ( 1 − x ) 2 = 1 y 2 \frac 1 {(1-x)^2}=\frac 1 {y^2} (1−x)21=y21。
带回原柿子得到:
f
[
i
]
[
j
]
=
i
+
j
+
x
y
×
1
y
2
=
i
+
j
+
p
a
p
b
f[i][j]=i+j+xy\times \frac 1 {y^2}=i+j+\frac {pa} {pb}
f[i][j]=i+j+xy×y21=i+j+pbpa
于是就可以 d p dp dp 了,以及, d p dp dp 的时候从 f [ 0 ] [ 1 ] f[0][1] f[0][1] 开始,避免一直出 b b b 而毫无进展的情况。
代码如下:
#include <cstdio>
#include <cstring>
#define mod 1000000007
int k,a,b,inv_a,inv_b,inv_ab;
int ksm(int x,int y)
{
int re=1;
while(y)
{
if(y&1)re=1ll*re*x%mod;
x=1ll*x*x%mod;y>>=1;
}
return re;
}
#define inv(x) ksm(x,mod-2)
int f[1010][1010];
int dp(int i,int j)
{
if(i+j>=k)return (i+j+1ll*a*inv_b%mod)%mod;
if(f[i][j]!=-1)return f[i][j];
return f[i][j]=(1ll*a*inv_ab%mod*dp(i,j+1)+1ll*b*inv_ab%mod*dp(i+j,j))%mod;
}
int main()
{
scanf("%d %d %d",&k,&a,&b);
inv_a=inv(a);inv_b=inv(b);inv_ab=inv(a+b);
memset(f,-1,sizeof(f));
printf("%d",dp(0,1));
}