【BZOJ4036】按位或(Min-Max容斥,FWT)
【BZOJ4036】按位或(Min-Max容斥,FWT)
题面
题解
很明显直接套用\(min-max\)容斥。
设\(E(max\{S\})\)表示\(S\)中最晚出现元素出现时间的期望,\(min\)同理。
那么\(E(max\{S\})=\sum_{T\subseteq S}(-1)^{|T|}E(min\{T\})\)
考虑怎么求\(E(min\{T\})\),很容易发现只需要或上了任何一位就行了。
也就是
\[E(min\{T\})=\frac{1}{\sum_{G\cap T\neq \phi }p[G]}
\]
只需要任意一个和\(T\)存在交的集合\(G\)就会产生至少一个位。
现在的问题转换成了怎么求任何一个和\(T\)有交的东西。
正难则反,求所有和\(T\)无交集的集合,设\(x=T\oplus(2^n-1)\),也就是\(T\)的补集。
显然所有的与\(T\)无交集的集合都是\(x\)的子集,那么只需要预处理子集和就好了,\(FWT\)实现。
时间复杂度\(O(2^n n)\),代码短的不行。
#include<cstdio>
int n,cnt[1<<20],N;
double P[1<<20],ans;
int main()
{
scanf("%d",&n);N=1<<n;
for(int i=0;i<N;++i)scanf("%lf",&P[i]),cnt[i]=cnt[i>>1]+(i&1);
for(int i=1;i<N;i<<=1)
for(int p=i<<1,j=0;j<N;j+=p)
for(int k=0;k<i;++k)
P[i+j+k]+=P[j+k];
for(int i=1;i<N;++i)if(1-P[(N-1)^i]>1e-8)ans+=((cnt[i]&1)?1:-1)/(1-P[(N-1)^i]);
if(ans<1e-10)puts("INF");else printf("%.10lf\n",ans);
return 0;
}