题目大意:老虎跟猴子比赛,一共n道双选题,每题有分值,猴子每题随机选择,问老虎想要不输给猴子得概率至少为p,那么至少要得多少分。
思路:因为题目最多40道,每题分值最多1000,所以可以求出每种分数可能的情况数,总的情况数是2的n次方种,不输的概率为p即至少要得(2^n)*p分。
开始的时候用位移运算的时候直接用的1<<n,后来发现原来1<<n得到的不是64位整数,改成1LL<<n就对了。最开始的代码写的比较挫,求方法数的时候从前往后求,就用了两个数组。后来发现从后往前求一个数组就够了。
开始的代码如下:
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef __int64 ll;
ll pos[40005];
ll rec[40005];
int main(){
// freopen("data.txt","r",stdin);
ios::sync_with_stdio(false);
int T;
cin>>T;
while(T--){
memset(pos,0,sizeof(pos));
pos[0]=1;
int n;
double p;
cin>>n>>p;
ll tot=1LL<<n;
int maxn=n*1000;
for(int t=0;t<n;++t){
memset(rec,0,sizeof(rec));
int val;
cin>>val;
for(int i=0;i<=maxn;++i){
if(pos[i]){
rec[i+val]+=pos[i];
}
}
for(int i=0;i<=maxn;++i){
pos[i]=pos[i]+rec[i];
}
}
ll num=ceil(tot*p);
ll tmp=0;
int i;
ll tt=0;
for(i=0;i<=n*1000;++i){
tmp+=pos[i];
if(tmp>=num&&pos[i])break;
}
cout<<i<<endl;
}
return 0;
}
在求方法数的时候代码可以改成下面的:
for(int i=maxn;i>=val;--i){
if(pos[i-val]){
pos[i]+=pos[i-val];
}
}