zoukankan      html  css  js  c++  java
  • 【bzoj4036】[HAOI2015]按位或 fmt+期望

    Description

    刚开始你有一个数字0,每一秒钟你会随机选择一个[0,2^n-1]的数字,与你手上的数字进行或(c++,c的|,pascal

    的or)操作。选择数字i的概率是p[i]。保证0<=p[i]<=1,Σp[i]=1问期望多少秒后,你手上的数字变成2^n-1。

    Input

    第一行输入n表示n个元素,第二行输入2^n个数,第i个数表示选到i-1的概率

    Output

    仅输出一个数表示答案,绝对误差或相对误差不超过1e-6即可算通过。如果无解则要输出INF

    Sample Input

    2
    0.25 0.25 0.25 0.25

    Sample Output

    2.6666666667

    HINT

    对于100%的数据,n<=20

    Sol

    快速莫比乌斯变换和快速莫比乌斯逆变换自行百度。

    (h(U)=)最终答案,(f_i(S))表示进行i次变换之后集合为(S)的概率,那么显然:

    (h(U)=sum_{i=1}^{infty}i*(f_i(U)-f_{i-1}(U)))

    (F_i(S))(f_i(s))的莫比乌斯变换,观察(f_i(S))的定义,我们可以得到(F_i(S))的式子:

    (F_i(S)=sum_{s_1in U}f_{i-1}(S_1)*sum_{s_2in U}f_1(S_2))

    那么(F_i(U)=(F_1(U))^i)

    所以(H(U)=sum_{i=1}^{infty}i*((F_1(U))^i-(F_1(U))^{i-1}))

    (-H(U)=sum_{i=1}^{infty}(F_1(U))^i)

    显然右边是一个等比数列求和的形式,而且数列的第(infty)项是0,所以:

    (H(S)=frac{F_1(S)}{F_1(S)-1})

    然后就可以直接算了。注意全集的H是1。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    int n,vis[1048577];double f[1048577];
    void fmt(double *a){for(int k=0;k<n;k++) for(int i=0;i<(1<<n);i++) if((i>>k)&1) a[i]+=a[i^(1<<k)];}
    void ufmt(double *a){for(int k=0;k<n;k++) for(int i=0;i<(1<<n);i++) if((i>>k)&1) a[i]-=a[i^(1<<k)];}
    int main()
    {
    	scanf("%d",&n);
    	for(int i=0;i<(1<<n);i++)
    	{
    		scanf("%lf",&f[i]);
    		if(f[i]>0) for(int j=0;j<n;j++) if((i>>j)&1) vis[j]=1;
    	}
    	for(int i=0;i<n;i++) if(!vis[i]) return puts("INF"),0;
    	fmt(f);
    	for(int i=0;i<(1<<n);i++) f[i]=(i==((1<<n)-1))?1:f[i]/(f[i]-1);
    	ufmt(f);
    	printf("%.10lf
    ",f[(1<<n)-1]);
    }
    
  • 相关阅读:
    .net 日期格式化
    grunt 上手
    设计模式的认识
    顺时针打印矩阵
    WCF 框架运行时类图
    Python闭包详解
    软件用了那些技术
    zoj 1610 Count the Colors(线段树延迟更新)
    快速提高自己的技术的办法?有两个方法
    纯win32实现PNG图片透明窗体
  • 原文地址:https://www.cnblogs.com/CK6100LGEV2/p/9412641.html
Copyright © 2011-2022 走看看