CF908D New Year and Arbitrary Arrangement

简单题。

发现最终状态无限,起始状态有限,考虑逆推(辅以记忆化)

\(f[x][y][z]\)\(x\) 个 a,\(y\)\(b\)\(z\) 个 ab 的期望 ab 个数。

则考虑能怎样走到哪些状态。

选 a,\(f[x+1][y][z]\)

选 b,\(f[x][y+1][x+y]\)

发现 b 这一维没啥用,因为前面的 b 对当前构不成影响,删去。

\(f[x][y]\)\(x\) 个 a,\(y\) 个 ab 的期望。

\[f[x][y]=P(A)*f[x+1][z]+P(B)*f[x][x+y] \]

但是可能会有 \(\lim_{x\to +\infty}\),即无法知道边界。

考虑当 \(x+y \ge k\),我们只需要算出在选一定次数 a 后选到 b 的期望和即可。

\[P(B)*\sum_{i=0}^{\infty}P(A)^i*(x+y+i) \]

代下

\[{\sum_{i=0}^{\infty}p^i=\dfrac{1}{1-p}} \]

\[\sum_{i=0}^{\infty}p^ii=\dfrac{p}{(1-p)^2} \]

补充下 2 式证明

\[\sum_{i=0}^{\infty}p^ii=s \]

\[s-sp=\sum_{i=1}^{\infty}p^ii \]

\[\dfrac{s(1-p)}{p}=\sum_{i=0}^{\infty}p^ii \]

\[s=\dfrac{p}{(1-p)^2} \]

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <map>
#include <vector>
#include <set>
#include <cmath>
#define int long long
using namespace std;

int rd() {
	char ch=getchar(); int sum=0,f=1;
	while(!isdigit(ch)) {
		if(ch=='-') f=-1; ch=getchar();
	}
	while(isdigit(ch)) sum=sum*10+ch-'0',ch=getchar();
	return f*sum;
}

const int mod=(int)(1e9+7);
int k,a,b,pa,pb,A1,A2;
int f[2005][2005];

int fpow(int x,int y) {
	int res=1; x=(x%mod+mod)%mod;
	while(y) {
		if(y&1) res=res*x%mod;
		x=x*x%mod; y>>=1;
	}
	return res;
}

int dfs(int x,int y) {
	if(x+y>=k) return  pb*((x*A1%mod+y*A1%mod+A2)%mod)%mod;
	if(f[x][y]) return f[x][y];
	return f[x][y]=(pa*dfs(x+1,y)%mod+pb*dfs(x,x+y)%mod)%mod;
}

signed main() {
	k=rd(); a=rd(); b=rd(); pa=a*fpow(a+b,mod-2)%mod; pb=b*fpow(a+b,mod-2)%mod; A1=fpow(1-pa,mod-2)%mod; A2=pa*fpow(1-pa,mod-2)%mod*fpow(1-pa,mod-2)%mod;
	printf("%lld",(dfs(1,0)%mod+mod)%mod);
	return 0;
}
posted @ 2022-02-08 18:08  FxorG  阅读(21)  评论(0编辑  收藏  举报