Solution -「CF 908D」New Year&Arbitrary Arrangement

(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;
}
原文地址:https://www.cnblogs.com/rainybunny/p/13428480.html