首页 > 其他 > 详细

Min-Max容斥学习笔记

时间:2020-02-24 20:20:14      阅读:70      评论:0      收藏:0      [点我收藏+]

越学了Min-Max容斥 , 越发察觉到自己的弱小。。。
对于一个集合S , 设S中最大的元素为max(S) , 最小的是min(S)
那么Min-Max容斥的结论是
技术分享图片

这个Min-Max容斥一般用于集合内的元素没有办法比较大小时。
对于期望也成立。

简略证明一下正确性
(其实就是搬运题解)
设S中的最大值是maxval
若一个集合中的最小值是maxval , 那这个集合一定是 { maxval } , 也就是maxval这个元素组成的集合。
这个时候系数是1 , 没毛病。
之后对于一个元素x , 他是第k大 k < n 那么他作为min出现了\(2^{n-k}\) 次 , 这其中有一半集合大小为偶数 , 另一半集合大小为奇数 。 这样一抵消 , 就把x消去了。

一道例题

在这个题里 , max(S) 就是所有位上都是1 , min(S) 就是S集合中有一位是1的最早的。
集合里的元素就是各个位置变成1的期望步数,这个东西显然没法比较大小。
由于Min-Max容斥对于期望也成立 。 那么现在问题就变成了怎么求min(S);

考虑总的集合为U , 那么P(min(S) == k)是啥。
P是概率。
会有前k-1次选择的是 U ^ S 中的元素 , 且在第K次选了S中的元素。
\(P(min(S) == k) = P(U xor S) ^{k-1} * (1 - P(U xor S))\)

有一个玩意叫 离散随机变量的几何分布

先说啥叫离散随机变量

离散随机变量就是一个随机变量只可以取一些特定的不连续值,比如全体正整数之类的……

那么我们描述一个离散随机变量的最朴素的方式就是列一个表……,打出每个值的概率,然后就可以描述一个离散随机变量的分布了

那么所谓的集合分布呢,就是这里有一个离散型随机变量X,满足
\(P(x == k) = (1 - p) ^ {k-1} * p\)

其中p是一个常量

那他的期望呢

\(E(x) = \sum_{i=0}^inf P(x == i)\)
$ = \sum_{i=0}^inf (1-p)^(i-1) * p = p * \sum_{i=0}^inf (1-p)^(i-1) = 1 / p$

然后再看\(P(min(S) == k) = P(U xor S) ^{k-1} * (1 - P(U xor S))\)
发现这个式子是满足p = (1 - P(U xor S)) 的离散型随机变量的集合分布。

那么最后一个问题 P(U^S) 怎么求。
P(x) = P(x所有子集)
这个东西用FWT解决即可。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
const double eps = 1e-8;
inline int read()
{
    register int x = 0 , f = 0; register char c = getchar();
    while(c < '0' || c > '9') f |= c == '-' , c = getchar();
    while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
    return f ? -x : x;
}
int n;
int siz[1<<21];
double a[1<<21];
int main()
{
    n = read(); int lim = 1 << n;
    for(int i = 0 ; i < lim ; ++i) scanf("%lf" , &a[i]);
    for(int mid = 1 ; mid < lim ; mid <<= 1)
        for(int j = 0 ; j < lim ; j += mid << 1)
            for(int k = 0 ; k < mid ; ++k)
                a[j + k + mid] += a[j + k];
    for(int i = 1 ; i < lim ; ++i) siz[i] = siz[i >> 1] + (i & 1);
    #define stop { puts("INF"); return 0; }
    double ans = 0;
    for(int i = 1 ; i < lim ; ++i)
    {
        double k = 1.0 - a[(lim - 1) ^ i];
        if(k < eps) stop; k = 1.0 / k;
        if(siz[i] & 1) ans += k; else ans -= k;
    }
    printf("%.10f\n" , ans);
    return 0;
}

Min-Max容斥学习笔记

原文:https://www.cnblogs.com/R-Q-R-Q/p/12358279.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!