[HDU4336]Card Collector

题目描述

题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4336

题目大意:有\(n\)张卡牌,每秒有\(p_i\)的概率买到第\(i\)张卡,\(\sum p_i\leqslant 1\),问期望多少秒之后集齐所有卡。

Solution

\(\min-\max\)容斥板子题。

\(\min-\max\)容斥是说一个这样的式子:

\[\max\{S\}=\sum_{T\subseteq S}(-1)^{|T|+1}\min\{T\} \]

这个式子在期望下成立,在这题\(\min\{S\}\)就表示\(S\)集合中第一张卡出现时间的期望,\(\max\)就是最后一张的期望。

那么显然可以得到:

\[\min\{S\}=\frac{1}{\sum_{i\in S}p_i} \]

然后范围比较小直接暴力算就好了。

时间复杂度\(O(2^n)\)

#include<bits/stdc++.h>
using namespace std;
 
void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
 
void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

#define lf double

const int maxn = 2e5+10;
const lf eps = 1e-6;

int n;
lf p[maxn],ans;

void dfs(int now,lf sum,int f) {
	if(now==n+1) return ans+=fabs(sum)<eps?0:(lf)f*1.0/sum,void();
	dfs(now+1,sum+p[now],-f);
	dfs(now+1,sum,f);
}

int main() {
	while(scanf("%d",&n)!=EOF) {
		for(int i=1;i<=n;i++) scanf("%lf",&p[i]);
		dfs(1,0,-1);
		printf("%lf\n",ans);ans=0;
	}
	return 0;
}
posted @ 2019-03-12 10:32  Hyscere  阅读(113)  评论(0编辑  收藏  举报