题解 hdu 4336 Card Collector
【大意】
有 \(N\) 种牌,每秒有 \(p_i\) 的概率获得其中的第 \(i\) 张。问所有卡牌都获得的概率。
【分析】
令 \(\max(S)\) 表示获得集合 \(S\) 的最后一张卡牌时间的随机变量
令 \(\min(S)\) 表示获得集合 \(S\) 的第一张卡牌时间的随机变量
由扩展 min-max 容斥得 \(\displaystyle E(\text{k-thmax}(S))=\sum_{T\subseteq S}(-1)^{|T|-k}\binom{|T|-1}{k-1}E(\min(S))\)
故 \(\displaystyle E(\max(S))=\sum_{\varnothing \subset T\subseteq S}(-1)^{|T|-1}E(\min(S))\)
因为 \(\displaystyle P(\min(S)=k)=(\sum_{i\in S}p_i)\cdot (1-\sum_{i\in S}p_i)^{k-1}\)
故 \(\displaystyle E(\min(S))=\sum_{k=1}^{\infty} k\cdot P(\min(S)=k)\) ,求和得 \(\displaystyle {1\over \sum_{i\in S}p_i}\)
【代码】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pii;
typedef double db;
#define fi first
#define se second
bool eps=1e-6;
inline int sgn(db x) { return (x>eps)-(x<-eps); }
int n;
db p[1<<20];
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
while( cin>>n ){
for(int i=0;i<n;++i) cin>>p[1<<i];
for(int i=1;i<1<<n;++i) if(i&(i-1))
p[i]=p[i-(i&-i)]+p[i&-i];
db res=0;
for(int i=1;i<1<<n;++i)
if(__builtin_popcount(i)&1) res+=1/p[i];
else res-=1/p[i];
cout<<fixed<<setprecision(9)<<res<<"\n";
}
cout.flush();
return 0;
}