CF908D New Year and Arbitrary Arrangement

题意

给定三个数\(k\),\(pa\),\(pb\)
每次有\(\frac{pa}{pa+pb}\) 的概率往后面添加一个'\(a\)'
每次有\(\frac{pb}{pa+pb}\)的概率往后面添加一个'\(b\)'
当出现了\(k\)个形如\(ab\)的子序列(不用连续)时停止
求最后的\(ab\)序列的期望数
答案对\(10^9+7\)取膜

Sol

\(f[i][j]\)表示前面有\(i\)\(a\)\(j\)\(ab\)的期望\(ab\)的对数
倒着来转移
显然
\(f[i][j]=f[i+1][j]*\frac{pa}{pa+pb}+f[i][i+j]*\frac{pb}{pa+pb}\)
答案就是\(f[0][0]\)
然而\(f[0][0]=f[1][0]*\frac{pa}{pa+pb}+f[0][0]*\frac{pb}{pa+pb}\)
不好算
移项后得到\(f[0][0]=f[1][0]\)
所以输出\(f[1][0]\)就好了

然而串长是无限的,\(a\)的个数也是无限的,\(ab\)的对数无限,它们可以到\(\infty\)
这就很不好做了了

但是你会发现,当\(a\)无穷多时,放一个\(b\)\(ab\)对数就会超过\(k\),显然直接就停了
对于\(f[i][j]\),当\(i+j>=k\)时,考虑它的期望
也就是\(f[i][j]=\frac{pb}{pa+pb}\sum_{l=0}^{\infty}(\frac{pa}{pa+pb})^l(i+j+l)\)

\(S=\sum_{l=0}^{\infty}(\frac{pa}{pa+pb})^l(i+j+l)\)

\(\frac{pa}{pa+pb}S=\sum_{l=0}^{\infty}(\frac{pa}{pa+pb})^{l+1}(i+j+l)\)
两式相减得
\((1-\frac{pa}{pa+pb})S=(i+j)+\sum_{l=1}^{\infty}(\frac{pa}{pa+pb})^l\)

\(\sum_{l=1}^{\infty}(\frac{pa}{pa+pb})^l\)
也可以类似处理
得到就是
\(\frac{\frac{pa}{pa+pb}-(\frac{pa}{pa+pb})^{\infty}}{1-\frac{pa}{pa+pb}}=\frac{pa}{pb}\)
带回去
\((1-\frac{pa}{pa+pb})S=(i+j)+\frac{pa}{pb}\)

\(\frac{pb}{pa+pb}S=(i+j)+\frac{pa}{pb}\)

所以
\(f[i][j]=\frac{pb}{pa+pb}S=(i+j)+\frac{pa}{pb}\)

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int Zsy(1e9 + 7);

int k, pa, pb, invb, inv, f[1005][1005], Pa, Pb;

IL int Input(){
    RG int x = 0, z = 1; RG char c = getchar();
    for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    return x * z;
}

IL int Pow(RG ll x, RG ll y){
	RG ll ret = 1;
	for(; y; y >>= 1, x = x * x % Zsy)
		if(y & 1) ret = ret * x % Zsy;
	return ret;
}

int main(RG int argc, RG char *argv[]){
	k = Input(), pa = Input(), pb = Input();
	invb = Pow(pb, Zsy - 2), inv = Pow(pa + pb, Zsy - 2);
	Pa = 1LL * pa * inv % Zsy, Pb = 1LL * pb * inv % Zsy;
	for(RG int i = k; i; --i)
		for(RG int j = k; ~j; --j)
			if(i + j >= k) f[i][j] = ((i + j) + 1LL * pa * invb % Zsy + Zsy) % Zsy;
			else f[i][j] = (1LL * f[i + 1][j] * Pa % Zsy + 1LL * f[i][j + i] * Pb % Zsy) % Zsy;
	printf("%d\n", f[1][0]);
    return 0;
}

posted @ 2018-03-29 19:45  Cyhlnj  阅读(168)  评论(0编辑  收藏  举报