1. 程式人生 > >[HAOI2015]按位或(FWT)

[HAOI2015]按位或(FWT)

cnblogs 需要 ssi clu min 就是 owas tchar 位或

[Luogu3175] [BZOJ4036] [DarkBZOJ沒有spj]

原理-shadowice

本題題解

我們要求的,實際上是一個集合\(n\)\(1\)中最晚出現的\(1\)的期望時間
顯然\(minmax\)容斥

\(E(max\{S\})=∑_{T?S}(?1)^{|T|+1}E(min\{T\})\)

那麽問題就轉化為了求每個集合中最早出現的\(1\)的期望時間
假如在\(k\)時刻出現,那麽前\(k?1\)時刻一定都是取的補集的子集,記\(T\)補集的所有子集概率和為\(P\)
\(E(min\{T\})=∑_{k=1}^{∞}kP(1?P)^{k?1}\)

是一個離散變量的幾何分布

\(P(x=a)=p\)
那麽取到\(a\)的期望為
\(E(x=a)=∑_{k=1}^{∞}k(1?p)^{k?1}p=p∑_{k=1}^{∞}k(1?p)^{k?1}\)

\(f(x)=1+2x+3x^2+4x^3+…\)
\(xf(x)=x+2x^2+3x^3+4x^4+…\)
\((1?x)f(x)=1+x+x^2+x^3+…\)
對於\(0<x<1,(1?x)f(x)\)是收斂的,可以取到
\((1?x)f(x)=\frac{1}{1?x}\)

\(f(x)=\frac{1}{(1?x)^2}\)

所以
\(E(x=a)=p\frac{1}{p^2}=\frac{1}{p}\)

非常棒
於是有
\(E(min{T})=\frac{1}{1?P}\)

我們只需要求出所有集合的子集概率和就好了
其實就是或運算的\(FWT\)

#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int INF=1e9+7;
inline LL read(){
    register LL x=0,f=1;register char c=getchar();
    while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
    while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
    return f*x;
}

const int MAXN=1<<20;
const double eps=1e-8;

double f[MAXN],ans;
int bit[MAXN],n,len;

int main(){
    n=read();len=1<<n;
    for(int i=0;i<len;i++) scanf("%lf",&f[i]);

    for(int i=2;i<=len;i<<=1){
        for(int j=0,p=i>>1;j<len;j+=i)
            for(int k=j;k<j+p;k++)
                f[k+p]+=f[k];//這裏的特殊寫法有助於理解FWT,FFT系列操作
    }

    for(int i=0;i<len;i++) bit[i]=bit[i>>1]+(i&1);
    for(int i=1;i<len;i++){
        double tmp=(1-f[(len-1)^i]);
        if(tmp<eps){printf("INF\n");return 0;}
        if(bit[i]&1) ans+=1.0/tmp;
        else ans-=1.0/tmp;
    }
    printf("%.8lf\n",ans);
}

[HAOI2015]按位或(FWT)