min-max 容斥学习笔记

定义

max(S) 为集合 S 中的最大值, min(S) 为集合 S 中的最小值,|S| 为集合 S 的元素数量,那么有以下两个等式:

max(S)=TS(1)|T|+1min(T)

min(S)=TS(1)|T|+1max(T)

对于 min-max 容斥,最简单的应用其实就是 min(a,b)=a+bmax(a,b)

在一些题目中,如果题目要求的是最大值,但是直接求最大值比较困难,而求最小值很方便,那么就可以用到 min-max 的方式 O(2n) 枚举子集容斥得出答案。

按位或

刚开始你有一个数字 0,每一秒钟你会随机选择一个 [0,2n1] 的数字,与你手上的数字进行或操作。选择数字 i 的概率是 pi。保证 0pi1pi=1 。问期望多少秒后,你手上的数字变成 2n1

n20

思路

一个事实是,min-max 容斥定理在期望下也成立,记 E(max(S)) 为集合中 max 值的期望,那么有

E(max(S))=TS(1)|T|+1E(min(T))

E(min(S))=TS(1)|T|+1E(max(T))

在本题中,E(max(S)) 可以定义为 S 集合中最后一个变为 1 的数的期望时间,那么也就是 S 集合中全部变为 1 的期望时间,发现这个直接求是做不到的;而 E(min(S)) 就定义为 S 集合中第一个变为 1 的数的期望时间,而求这个就比较方便了。

令离散型随机变量 X 表示第一次变为 1 的时间,由高中概率相关的数学知识可以知道:

P(X=k)=(1p)k1p

那么根据期望的定义,可以知道:

E(X)=i=1p(x=i)=i=1(1p)i1p=p+(1p)p+(1p)2p++(1p)p

不难发现这就是一个等比数列求和的式子,套用等比数列求和公式,可以得到:

E(X)=p×1(1(1p))2=1p

那么对于一个集合 T 来说,Px 表示选到 x 这个数的概率,那么对于每次选择的数 G,只需要满足 GT 就代表选到了这个集合,于是就有:

E(min(T))=1PT=1GTPG=11GT=PG

注意到 GT=PG 实际上就是一个高维前缀和的形式,于是就可以用到 FWT。最后再套用一下 min-max 容斥即可得到答案。时间复杂度为 O(2nn)

code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1<<20;
const double eps=1e-8;
double p[N],ans;
int n,cnt[N];
void OR(double f[],int op)
{
	for(int i=0;i<n;i++)
	    for(int j=0;j<(1<<n);j++)
	        if((j>>i)&1) f[j]+=op*f[j^(1<<i)];
}
int main()
{
	scanf("%d",&n);for(int i=0;i<(1<<n);i++) scanf("%lf",&p[i]);OR(p,1);
	for(int i=0;i<(1<<n);i++) cnt[i]=cnt[i>>1]+(i&1);
	for(int i=1;i<(1<<n);i++)
	{
		if(1-p[((1<<n)-1)^i]<eps) continue;double val=1.0/(1-p[((1<<n)-1)^i]);
		if(cnt[i]&1) ans+=val;else ans-=val;
	}
	if(ans>eps) printf("%.10lf\n",ans);else puts("INF");
	return 0;
}
posted @   曙诚  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
历史上的今天:
2022-03-21 UVA1201 Taxi Cab Scheme(二分图最小点覆盖)
点击右上角即可分享
微信分享提示