HDU4336 Card Collector

HDU

$n$ 个物品,每次得到第 $i$ 个物品的概率为 $p_i$ ,而且有可能什么也得不到,问期望多少次能收集到全部 $n$ 个物品。

分析

$\text{min-max}$ 容斥。

$$\displaystyle E(\max(S))=\sum\limits_{T\subseteq S}(-1)^{|T|+1}E(\min(T))$$

本题中显然有 $\displaystyle E(\min(T))=\frac{1}{\sum_{i\in T}p_i}$ 。

于是直接枚举子集即可求出 $E(\max(S))$ 。

代码

// ===================================
//   author: M_sea
//   website: http://m-sea-blog.com/
// ===================================
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define re register
using namespace std;

inline int read() {
    int X=0,w=1; char c=getchar();
    while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
    while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar();
    return X*w;
}

const int N=20+10;

int n; double p[N];
double sum[1<<20];

int main() {
    while (scanf("%d",&n)==1) {
        int lim=1<<n;
        for (re int i=0;i<n;++i) scanf("%lf",&p[i]);
        for (re int i=0;i<lim;++i) {
            sum[i]=0;
            for (re int j=0;j<n;++j)
                if (i&(1<<j)) sum[i]+=p[j];
        }
        double ans=0;
        for (re int i=0;i<lim;++i) {
            if (sum[i]<1e-9) continue;
            if (__builtin_popcount(i)&1) ans+=1/sum[i];
            else ans-=1/sum[i];
        }
        printf("%.4lf\n",ans);
    }
    return 0;
}
最后修改:2019 年 09 月 27 日 01 : 20 PM

发表评论