#概率,dp#JZOJ 4212 我想大声告诉你

题目

\(x\)和他的\(n-1\)个朋友,进行\(k\)轮游戏,每轮等概率选出一个人作为获胜者并退出游戏,
其余在游戏中的人有\(p\)的概率被迫退出游戏,问对于任意的轮数\(k\),使小\(x\)获胜的概率


分析

\(dp[i][j]\)表示前\(i\)轮有\(j\)个人退出游戏的概率,
那么

\[dp[i][j]=dp[i-1][j-1]*(1-p)^{i-1}+dp[i][j-1]*(1-(1-p)^i) \]

也就是主动退出(前\(i-1\)轮都在内)或被迫退出(前\(i\)轮不能都在内)的概率之和。
最后对于单个\(k\),答案就是

\[\frac{1}{n}\sum_{i=k}^{n-1}dp[k][i]*(1-p)^{k} \]


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
const int mod=258280327,N=2011;
int n,p,dp[N],inv[N],pw[N],f[N];
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
inline signed ksm(int x,int y){
	rr int ans=1;
	for (;y;y>>=1,x=1ll*x*x%mod)
	    if (y&1) ans=1ll*ans*x%mod;
	return ans;
}
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
signed main(){
	inv[0]=inv[1]=pw[0]=1;
	for (rr int i=2;i<N;++i) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	for (rr int Test=iut();Test;--Test){
		n=iut(),p=1ll*iut()*ksm(iut(),mod-2)%mod,dp[0]=1;
		for (rr int i=1;i<=n;++i) pw[i]=1ll*pw[i-1]*(mod-p+1)%mod,dp[i]=0;
		for (rr int i=1;i<=n;++i){
			int ans=0;
			for (rr int j=i-1;j<n;++j)
		        ans=mo(ans,1ll*pw[i-1]*dp[j]%mod);
		    print(1ll*ans*inv[n]%mod),putchar(i==n?10:32);
		    if (i==n) break;
			for (rr int j=i-1;j<n;++j) f[j]=dp[j],dp[j]=0;
			for (rr int j=i;j<n;++j)
			    dp[j]=mo(1ll*dp[j-1]*(mod-pw[i]+1)%mod,1ll*f[j-1]*pw[i-1]%mod);
		}
	}
	return 0;
}
posted @ 2020-08-15 17:21  lemondinosaur  阅读(150)  评论(0编辑  收藏  举报