【洛谷P3175】按位或

题目

题目链接:https://www.luogu.com.cn/problem/P3175
刚开始你有一个数字 \(0\),每一秒钟你会随机选择一个 \([0,2^n-1]\) 的数字,与你手上的数字进行或(C++,C 的 |,pascal 的 or)操作。选择数字 \(i\) 的概率是 \(p_i\)。保证 \(0\leq p_i \leq 1\)\(\sum p_i=1\) 。问期望多少秒后,你手上的数字变成 \(2^n-1\)

思路

\(S\) 为全集 (\(S=\{x|0\leq x<2^n\}\)),设 \(E(x)\) 表示 \(x\) 被包含于得到的数字数字的期望次数,根据 min-max 容斥,有

\[E(\max(S))=\sum_{T\in S}(-1)^{|T|+1}E(\min(T)) \]

其中 \(E(\max(S))=E(2^n-1)\) 即为我们所求。
考虑如何求出 \(E(\min(T))\)。显然 \(E(\min(T))\) 等于“一直在 \([0,2^n-1]\) 中随机取数,直到取到一个数 \(x\ \mathrm{and}\ T\neq \varnothing\) 的期望次数”。
\(f(T)\) 表示在 \([0,2^n-1]\) 中随机取数,取到 \(T\) 子集内的数的期望。那么

\[f(T)=\frac{1}{\sum_{x\in T}p(x)} \]

这个东西就是子集卷积,直接上 FWT 即可。
那么

\[E(\min(T))=\frac{(f(T\ \mathrm{xor}\ S)E(\min(T))+1)+1}{2}=\frac{1}{1-f(T\ \mathrm{xor}\ S)} \]

这样就在 \(O(2^nn)\) 内搞定了这道题。

代码

#include <bits/stdc++.h>
using namespace std;

const int N=(1<<20)+10;
const double eps=1e-12;
int n,lim,bit[N];
double ans,p[N];

int main()
{
	scanf("%d",&n);
	lim=(1<<n);
	for (int i=0;i<lim;i++)
		scanf("%lf",&p[i]);
	for (int k=1;k<lim;k<<=1)
		for (int i=0;i<lim;i+=(k<<1))
			for (int j=0;j<k;j++)
				p[i+j+k]+=p[i+j];
	for (int i=0;i<lim-1;i++) 
	{
		if (1-p[i]<eps) return printf("INF"),0;
		p[i]=1.0/(1-p[i]);
	}
	for (int i=1;i<lim;i++)
	{
		bit[i]=bit[i^(i&-i)]+1;
		ans+=((bit[i]&1)?1.0:-1.0)*p[lim-1-i];
	}
	printf("%.10lf",ans);
	return 0;
}
posted @ 2021-01-25 15:12  stoorz  阅读(63)  评论(0编辑  收藏  举报