[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;
}