#概率,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;
}