(mathcal{Description})
Link.
给定 (n,p_a,p_b),初始有一个空串,每次操作有 (frac{p_a}{p_a+p_b}) 的概率在其后添加字符 ( exttt{'a'}),(frac{p_b}{p_a+p_b}) 的概率添加字符 ( exttt{'b'}),当子序列 ({ exttt{'a'}, exttt{'b'}}) 的个数不小于 (n) 时,结束操作。求子序列的期望个数,对 (10^9+7) 取模。
(nle1000)。
(mathcal{Solution})
显然状态,(f(i,j)) 表示有 (i) 个 ( exttt{'a'}),(j) 个 ({ exttt{'a'}, exttt{'b'}}) 的期望串长。为方便转移,令 (p_a) 为出现 ( exttt{'a'}) 的概率,(p_b) 同理。对于一般情况的转移:
[f(i,j)=p_af(i+1,j)+p_bf(i,i+j)
]
当 (i+jge n),若再出现一个 ( exttt{'b'}),操作必然停止。那么:
[egin{aligned}
f(i,j)&=p_bsum_{k=0}^{+infty}p_a^k(i+j+k)\
p_af(i,j)&=p_bsum_{k=1}^{+infty}p_a^k(i+j+k-1)\
(1-p_a)f(i,j)&=p_bleft(i+j+sum_{k=1}^{+infty}p_a^k
ight)\
p_bf(i,j)&=p_bleft(i+j+frac{p_a}{p_b}
ight)\
f(i,j)&=i+j+frac{p_a}{p_b}
end{aligned}
]
而初始状态有:
[egin{aligned}
f(0,0)&=p_af(1,0)+p_bf(0,0)\
&=frac{p_a}{1-p_b}f(1,0)\
&=f(1,0)
end{aligned}
]
DP 就好了 w。
(mathcal{Code})
#include <cstdio>
#include <cstring>
typedef long long LL;
const int MAXN = 1000, MOD = 1e9 + 7;
int n, pa, pb, div, f[MAXN + 5][MAXN + 5];
inline int add ( int a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; }
inline int mul ( LL a, const int b ) { return ( a *= b ) < MOD ? a : a % MOD; }
inline int sub ( int a, const int b ) { return ( a -= b ) < 0 ? a : a + MOD; }
inline int qkpow ( int a, int b ) {
int ret = 1;
for ( ; b; a = mul ( a, a ), b >>= 1 ) ret = mul ( ret, b & 1 ? a : 1 );
return ret;
}
inline int solve ( const int a, const int k ) {
if ( a + k >= n ) return add ( a, add ( k, div ) );
if ( ~ f[a][k] ) return f[a][k];
return f[a][k] = add ( mul ( pa, solve ( a + 1, k ) ), mul ( pb, solve ( a, a + k ) ) );
}
int main () {
int ta, tb;
scanf ( "%d %d %d", &n, &ta, &tb );
memset ( f, -1, sizeof f );
pa = mul ( ta, qkpow ( add ( ta, tb ), MOD - 2 ) );
pb = mul ( tb, qkpow ( add ( ta, tb ), MOD - 2 ) );
div = mul ( pa, qkpow ( pb, MOD - 2 ) );
printf ( "%d
", solve ( 1, 0 ) );
return 0;
}