【BZOJ4036】按位或(Min-Max容斥,FWT)

【BZOJ4036】按位或(Min-Max容斥,FWT)

题面

BZOJ
洛谷

题解

很明显直接套用\(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;
}

posted @ 2018-08-21 17:35  小蒟蒻yyb  阅读(868)  评论(7编辑  收藏  举报