题意
刚开始你有一个数字 (0),每一秒钟你会随机选择一个 ([0,2^n-1]) 的数字,与你手上的数字进行或操作。选择数字 (i) 的概率是 (p[i]) 。 问期望多少秒后,你手上的数字变成 (2^n-1)。(n leq 20) 。
Solution
$ ext{min-max}$ 容斥。
答案即求 (E(max(S))) 即全集 (S) 最后一个元素出现时间的期望。
根据 $ ext{min-max}$ 容斥 :
[E(max(S))=sum_{Tsubseteq S} ( -1)^{T+1} E(min(T))
]
(注:下文中 (S,T) 并非上文中的 (S,T) )
考虑求 (E(min(S))) 即集合 (S) 第一个元素出现时间的期望。
[E(min(S)) = frac{1}{sum_{Tcap S
eq emptyset}P_T}
]
考虑补集转化,设 (S') 为 (S) 的补集。
[E(min(S)) = frac{1}{1-sum_{Tsubseteq S'}P_T}
]
直接高维前缀和即可。复杂度 (O(2^n cdot n)) 。
code
#include<bits/stdc++.h>
const int N=(1<<20)+5;
double p[N],ans;
int main()
{
int n; scanf("%d",&n);
for(int i=0;i<(1<<n);++i)
{
scanf("%lf",&p[i]);
if(fabs(p[i])<1e-7)
{
puts("INF");
return 0;
}
}
for(int i=0;i<n;++i)
for(int j=0;j<(1<<n);++j)
if(j&(1<<i)) p[j]+=p[j^(1<<i)];
for(int i=1;i<(1<<n);++i)
{
double tmp=1.0/(1.0-p[i^((1<<n)-1)]);
__builtin_popcount(i)&1?ans+=tmp:ans-=tmp;
}
printf("%.7lf",ans);
}