题目大意:两人竞选,总共有N票,人1已得V1票,人2已得V2票,剩下的人投给每个人的概率都是0.5,
输入:N,V1,V2,W
0<N<=50;
0<=V1,V2<N;
V1+V2<=N;
50<=W<100;
输出:
如果V1赢得的概率大于W,输出 GET A CRATE OF CHAMPAGNE FROM THE BASEMENT!
如果V1赢得的概率P:0<P<=W,输出 PATIENCE, EVERYONE!
否则输出 RECOUNT!
这题求概率,属于二项分布问题。
(二项分布:二项分布即重复n次独立的伯努利试验。在每次试验中只有两种可能的结果,而且两种结果发生与否互相对立,并且相互独立,与其它各 次试验结果无关,事件发生与否的概率在每一次独立试验中都保持不变,则这一系列试验总称为n重伯努利实验 )
计算公式:
如果事件发生的概率是P,N次独立重复试验中发生K次的概率是
P(ξ=K)=C(n,k)*(p^k)*[q^(n-k) ]
注意!:第二个等号后面里的括号里的是写在右上角的.
q=1-p
此处p,q均为0.5, P(ξ=K)=Cn(k)0.5^n.
肯定要求组合数的算法;
二项式系数C(n, k)满足下面的要求:
C(n,k) = C(n−1,k−1) + C(n−1,k) for all 0<k<n.
显然符合DP;
代码:
long long Combina[51][51];
for(int i=1;i<51;++i)
{
Combina[i][0]=Combina[i][i]=1;
}
long long Combination(int d,int u)
{
if(Combina[d][u]) return Combina[d][u];
return Combina[d][u]=Combination(d-1,u)+Combination(d-1,u-1);
}
由于实际,我想过只需要前一半的列(组合数的对称性)
将 Combina[51][51]改为了 Combina[51][26];
结果出现了栈溢出(不懂原因)
1 1
1 0 1
1 0 0 1
1 0 0 0 1
1 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 01 0 1
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 010 0 1
1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 01 0 0 0 1
1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 010 0 0 0 1
1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 01 0 0 0 0 0 1
1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 01 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 01 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 01 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 01 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 01 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 01 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 01 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 01 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 010 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 010 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 01 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 01 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 01 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
本题代码:
/*
v=N/2+1 表示赢必须得到的最少票数;
leave 表示剩下未投票的人数;
p表示概率,W%用来判赢的底线
比较p=sum(C(leave,i))*(0.5^leave)(v-V1<=i<=leave) 与 W% <=> P=p*(2^leave)*100=sum(C(leave,i))*100(v-V1<=i<=leave)与 W*(2^leave)比较
#include <iostream>
using namespace std;
long long Combina[51][51];
long long Combination(int d,int u)
{
if(Combina[d][u])return Combina[d][u];
return Combina[d][u]=Combination(d-1,u)+Combination(d-1,u-1);
}
int main()
{
for(int i=1;i<51;++i)
{
Combina[i][0]=Combina[i][i]=1;
}
int T;
cin>>T;
while (T--)
{
int N,V1,V2;
long long W;
cin>>N>>V1>>V2>>W;
int v=N/2+1;
int leave=N-V1-V2;
long long P=0;
if(V1>=v)cout<<"GET A CRATE OF CHAMPAGNE FROM THE BASEMENT!"<<endl;
else if(leave+V1<v)cout<<"RECOUNT!"<<endl;//平局或肯定输;
else
{
for(int i=leave;i>=v-V1;--i)
{
P+=Combination(leave,leave-i);
}
while (leave--)
{
W*=2;
}
P*=100;
if(P>W)cout<<"GET A CRATE OF CHAMPAGNE FROM THE BASEMENT!"<<endl;
else cout<<"PATIENCE, EVERYONE!"<<endl;
}
}
return 0;
}