zoukankan      html  css  js  c++  java
  • [HAOI2015]按位或(min-max容斥,FWT,FMT)

    题目链接:洛谷

    题目大意:给定正整数 $n$。一开始有一个数字 $0$,然后每一秒,都有 $p_i$ 的概率获得 $i$ 这个数 $(0le i< 2^n)$。一秒恰好会获得一个数。每获得一个数,就要将我们有的数与获得的数进行按位或。问期望经过多少秒后,我们的数变成 $2^n-1$。

    $1le nle 20,sum p_i=1$。


    %%%stO shadowice1984 Orz%%%

    首先定义 $min(S)$ 表示 $S$ 中第一个变为 $1$ 的元素的时间。(其中 $S$ 是一个二进制数,是 $1$ 的位表示这一位计入答案)

    $max(S)$ 表示最后一个变为 $1$ 的元素的时间。这也符合 $min$ 和 $max$ 的定义。

    (以下定义全集 $U=2^n-1$)

    我们要求的就是 $E(max(U))$。

    容斥:$E(max(U))=sumlimits_{S eqvarnothing}(-1)^{|S|+1}E(min(S))$

    现在问题就是求 $E(min(S))$,就是有元素变为 $1$。

    套期望的公式:$E(min(S))=sumlimits^{+infty}_{i=1}iP(min(S)=i)$

    $P(min(S)=i)$ 表示恰好在第 $i$ 秒出现 $1$ 的概率。

    前 $i-1$ 秒都没有出现,所以应该是 $sumlimits_{Tcap S=varnothing}P(T)$。其中 $P(T)$ 表示出现的数是 $T$ 的概率。

    第 $i$ 秒有出现,所以应该是 $1-sumlimits_{Tcap S=varnothing}P(T)$。

    乘法原理,$P(min(S)=i)=(sumlimits_{Tcap S=varnothing}P(T))^{i-1}(1-sumlimits_{Tcap S=varnothing}P(T))$

    那么经过一通爆算,$E(min(S))=dfrac{1}{1-sumlimits_{Tcap S=varnothing}P(T)}$。

    转换一下:$E(min(S))=dfrac{1}{1-sumlimits_{Tsubseteqcomplement_US}P(T)}$。

    现在最严峻的问题就是计算每个集合的子集和。

    最裸的枚举,$O(4^n)$。

    技巧一点的枚举,$O(3^n)$。

    那么就要说到一个很有趣的事情了,我也是做了这题才知道的……

    回想一下FWT(或者FMT)做按位或卷积的时候:

    $C_i=sumlimits_{j|k=i}A_jB_k$

    令 $widehat{C}_i=sumlimits_{jsubseteq i}C_j$

    那么就有 $widehat{C}_i=sumlimits_{j|ksubseteq i}A_jB_k$

    也就是 $widehat{C}_i=sumlimits_{jsubseteq i,ksubseteq i}A_jB_k$

    也就是 $widehat{C}_i=widehat{A}_iwidehat{B}_i$!

    于是需要一种从 $A$ 到 $widehat{A}$ 的变换还有它的逆变换。

    于是就有了FWT(或者FMT)……

    (所以说,FWT比FFT要好理解,那就要理解啊)

    那么我们就知道了,FWT的或变换一次后新的序列就是原序列的子集和形式!

    好的,时间复杂度 $O(n2^n)$。

    代码:(实际上特别好写)

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1111111;
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline int read(){
        char ch=getchar();int x=0,f=0;
        while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return f?-x:x;
    }
    int n,cnt[maxn];
    double p[maxn];
    void FWTor(double *A){
        for(int i=1;i<1<<n;i<<=1)
            for(int j=0,r=i<<1;j<1<<n;j+=r)
                FOR(k,0,i-1) A[i+j+k]+=A[j+k];
    }
    int main(){
        n=read();
        FOR(i,0,(1<<n)-1) scanf("%lf",p+i);
        FWTor(p);
        FOR(i,1,(1<<n)-1) cnt[i]=cnt[i>>1]+(i&1);
        double ans=0;
        FOR(i,1,(1<<n)-1){
            if(1-p[((1<<n)-1)^i]<1e-8) return puts("INF"),0;
            ans+=1/(1-p[((1<<n)-1)^i])*(cnt[i]&1?1:-1);
        }
        printf("%.10lf
    ",ans);
    }
    View Code
  • 相关阅读:
    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结v2
    JS设置cookie、读取cookie、删除cookie
    Atitit 图像处理30大经典算法attilax总结
    Atitit数据库层次架构表与知识点 attilax 总结
    Atitit 游戏的通常流程 attilax 总结 基于cocos2d api
    Atitti css transition Animation differ区别
    Atitit 图像清晰度 模糊度 检测 识别 评价算法 源码实现attilax总结
    Atitit 全屏模式的cs桌面客户端软件gui h5解决方案 Kiosk模式
    Atitit 混合叠加俩张图片的处理 图像处理解决方案 javafx blend
    Atitit  rgb yuv  hsv HSL 模式和 HSV(HSB) 图像色彩空间的区别
  • 原文地址:https://www.cnblogs.com/1000Suns/p/10388001.html
Copyright © 2011-2022 走看看