zoukankan      html  css  js  c++  java
  • 【洛谷P3175】按位或

    题目

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

    思路

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

    [E(max(S))=sum_{Tin 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 eq varnothing) 的期望次数”。
    (f(T)) 表示在 ([0,2^n-1]) 中随机取数,取到 (T) 子集内的数的期望。那么

    [f(T)=frac{1}{sum_{xin 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;
    }
    
  • 相关阅读:
    android adb常用命令
    weblogic 优化设置 http://wenku.baidu.com/view/c42e7a5bbe23482fb4da4cf2.html
    Ajax+json实现菜单动态级联
    浏览器兼容性
    登录相关
    Java 日期处理
    QBC分页查询
    WebService
    MD5加密
    JSON与JAVA数据的转换
  • 原文地址:https://www.cnblogs.com/stoorz/p/14325355.html
Copyright © 2011-2022 走看看