【大意】
有 (N) 种牌,每秒有 (p_i) 的概率获得其中的第 (i) 张。问所有卡牌都获得的概率。
【分析】
令 (max(S)) 表示获得集合 (S) 的最后一张卡牌时间的随机变量
令 (min(S)) 表示获得集合 (S) 的第一张卡牌时间的随机变量
由扩展 min-max 容斥得 (displaystyle E( ext{k-thmax}(S))=sum_{Tsubseteq S}(-1)^{|T|-k}inom{|T|-1}{k-1}E(min(S)))
故 (displaystyle E(max(S))=sum_{varnothing subset Tsubseteq S}(-1)^{|T|-1}E(min(S)))
因为 (displaystyle P(min(S)=k)=(sum_{iin S}p_i)cdot (1-sum_{iin S}p_i)^{k-1})
故 (displaystyle E(min(S))=sum_{k=1}^{infty} kcdot P(min(S)=k)) ,求和得 (displaystyle {1over sum_{iin 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<<"
";
}
cout.flush();
return 0;
}