bzoj4036 / P3175 [HAOI2015]按位或

Posted yijan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4036 / P3175 [HAOI2015]按位或相关的知识,希望对你有一定的参考价值。

bzoj4036 / P3175 [HAOI2015]按位或

是一个 min-max容斥 的板子题。

min-max容斥 式子:

$ displaystyle max(S) = sum_{Tsube S} (-1)^{|T|+1} min(T) $

并且很优秀的是,它在期望情况下成立!

这个有什么关系呢。。

如果每一位分开考虑,如果第 $ i $ 位变成 1 的期望时间是 $ T(i) $

那么求的是 $ E(max(T_{1dots n})) $

这个可以 min-max容斥

求 $ min $ 的就是某一个子集让其中某一个变成 1 的期望次数。

考虑一次选择可以让这个子集的某一个变成 1 的概率,就是 1 - 这个子集所有位都是 0 的数字的概率的和,可以考虑令 $ S $ 是除了子集的位是0其他都是1的数(集合),概率就是 $ 1 - sum_{A[i] sube S} p_i $ 每次选择是等价的,所以期望就是 $ frac{1}{p} $

然后minmax容斥式子种 $ |T| $ 其实就是 $ S $ 中 0 的个数,就是n - popcount

这个的计算其实就是半个 或卷积

复杂度 $ O(n2^n) $

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<map>
using namespace std;
#define MAXN ( 1 << 21 ) + 6
int n;
double p[MAXN];

inline void FWT(double a[], int len) {
    for (int mid = 2; mid <= len; mid <<= 1) 
        for (int i = 0; i < len; i += mid)
            for (int j = i; j < i + (mid >> 1); j++) 
                a[j + (mid >> 1)] += a[j];
}

int main() {
    cin >> n;
    for( int i = 0 ; i < ( 1 << n ) ; ++ i ) scanf("%lf",&p[i]);
    FWT( p , ( 1 << n ) );
    double ans = 0.0;
    for( int i = 0 ; i < ( 1 << n ) - 1; ++ i ) {
        ans += ( ( n - __builtin_popcount( i ) & 1 ) ? 1.0 : -1.0 ) / ( 1.0 - p[i] );
    }
    if( ans > 1e50 ) puts("INF");
    else printf("%.7lf",ans);
}

以上是关于bzoj4036 / P3175 [HAOI2015]按位或的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 4036 [HAOI2015]按位或——min-max容斥+FMT

BZOJ 4036: [HAOI2015]按位或 集合幂函数 莫比乌斯变换 莫比乌斯反演

bzoj4036[HAOI2015]set 按位或

luogu P3175 [HAOI2015]按位或

bzoj千题计划199:bzoj1055: [HAOI2008]玩具取名

P3175 [HAOI2015]按位或(Min - Max容斥,FMT,概率期望,全网最清晰的题解!)