Solution -「CF 908D」New Year&Arbitrary Arrangement
阿新 • • 發佈:2020-08-03
\(\mathcal{Description}\)
Link.
給定 \(n,p_a,p_b\),初始有一個空串,每次操作有 \(\frac{p_a}{p_a+p_b}\) 的概率在其後新增字元 \(\texttt{'a'}\),\(\frac{p_b}{p_a+p_b}\) 的概率新增字元 \(\texttt{'b'}\),當子序列 \(\{\texttt{'a'},\texttt{'b'}\}\) 的個數不小於 \(n\) 時,結束操作。求子序列的期望個數,對 \(10^9+7\) 取模。
\(n\le1000\)。
\(\mathcal{Solution}\)
顯然狀態,\(f(i,j)\)
\[f(i,j)=p_af(i+1,j)+p_bf(i,i+j) \]
當 \(i+j\ge n\),若再出現一個 \(\texttt{'b'}\),操作必然停止。那麼:
\[\begin{align} f(i,j)&=p_b\sum_{k=0}^{+\infty}p_a^k(i+j+k)\\ p_af(i,j)&=p_b\sum_{k=1}^{+infty}p_a^k(i+j+k-1)\\ (1-p_a)f(i,j)&=p_b\left(i+j+\sum_{k=1}^{+\infty}p_a^k\right)\\ p_bf(i,j)&=p_b\left(i+j+\frac{p_a}{p_b}\right)\\ f(i,j)&=i+j+\frac{p_a}{p_b} \end{align} \]
而初始狀態有:
\[\begin{align} f(0,0)&=p_af(1,0)+p_bf(0,0)\\ &=\frac{p_a}{1-p_b}f(1,0)\\ &=f(1,0) \end{align} \]
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\n", solve ( 1, 0 ) ); return 0; }