卧薪尝胆,厚积薄发。
More? More!
Date: Sat Mar 23 15:07:01 CST 2019
In Category:
NoCategory
Description:
n个人两两之间都有一场比赛,编号小的人胜率是
$p$
。我们称前
$k$
名可确定,当且仅当存在一个大小为
$k$
的集合
$S$
,使得
$S$
中的每个人都战胜了不在
$S$
中的所有人。问能确定前
$k=1,\dots,n−1$
名的概率。
$1\leqslant n\leqslant 10^6$
Solution:
玄学。
设
$f[i][j]$
表示前
$i$
个人可以确定前
$j$
位的概率。
考虑把第
$i$
个人插进去,那么为了保证可以确定前
$j$
名,要么前
$j$
名都打败了他,要么他打败了后面所有人,即:
$$
f[i][j]=f[i-1][j]\times p^{j}+f[i-1][j-1]\times(1-p)^{i-j}
$$
同样的,把第
$1$
个人插进去,可以得到:
$$
f[i][j]=f[i-1][j]\times (1-p)^j+f[i-1][j-1]\times p^{i-j}
$$
把他们联立:
$$
\begin{align}
f[i-1][j]\times p^j+f[i-1][j-1]\times(1-p)^{i-j}&=f[i-1][j]\times (1-p)^j+f[i-1][j-1]\times p^{i-j}\\
f[i-1][j]\times (p^j-(1-p)^j)&=f[i-1][j-1]\times (p^{i-j}-(1-p)^{i-j})\\
\end{align}
$$
那么就可以得到:
$$
f[n][j]\times (p^j-(1-p)^j)=f[n][j-1]\times (p^{n+1-j}-(1-p)^{n+1-j})\\
f[n][j]=f[n][j-1]\times \frac{p^{n+1-j}-(1-p)^{n+1-j}}{p^j-(1-p)^j}\\
$$
显然有
$f[n][0]=1$
,于是就可以递推了。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
inline int rd()
{
register int res = 0,f = 1;register char c = getchar();
while(!isdigit(c)){if(c == '-')f = -1;c = getchar();}
while(isdigit(c))res = (res << 1) + (res << 3) + c - '0',c = getchar();
return res * f;
}
int n,p,q;
#define P 998244353
int power(int a,int b)
{
int res = 1;
for(;b > 0;b = b >> 1,a = 1ll * a * a % P)if(b & 1)res = 1ll * res * a % P;
return res;
}
#define MAXN 1000010
int main()
{
scanf("%d%d",&n,&p);
q = (1 - p + P) % P;
if(p == q)
{
int C = 1;
for(int i = 1;i < n;++i)
{
C = 1ll * C * power(i,P - 2) % P * (n - i + 1) % P;
cout << 1ll * power(power(p,n - i),i) * C % P << " ";
}
cout << endl;
}
else
{
int last = 1;
for(int i = 1;i < n;++i)
{
last = 1ll * last * (power(p,n + 1 - i) - power(q,n + 1 - i) + P) % P * power((power(p,i) - power(q,i) + P) % P,P - 2) % P;
cout << last << " ";
}
cout << endl;
}
return 0;
}
In tag:
DP-概率DP
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡