容容容容斥斥斥容容斥(完善中)

Part 0 容斥原理

§ 0.0 容斥原理及其本质

表达式各个部分的含义

最常见到的容斥原理的形式如下:

|i=1nSi|=i=1n(1)i1T[1,n],|T|=i|jTSj|

如何理解?

假如说我们面对一个特殊的问题,计算某些集合的交集十分容易,也就是说,我们可以在极低的开销下,指定若干个属性,并统计拥有这些属性的元素的个数。

注意,不是“恰好拥有”,而就是简单的“拥有”。

现在我们定义一种操作,指定一个 k,对于所有大小为 k 的,由属性组成的集合,分别查询拥有这个集合内全部属性的元素个数,然后把所有结果相加。

注意!这里查询的不是并集,有一些元素会被计算多次!一些博客文章会把这种操作称为“查询至少有 k 个属性的元素数目”,这种称呼其实不是很严谨。

为了下面的叙述方便,我们把这一操作称为 “钦定拥有 k 个属性的元素数目”,这也是 OI 界对这种形式的操作的通常称呼。

那在这种条件下,如何统计一共有几个元素至少有一种属性呢?

我们统计钦定拥有 1 个属性的元素数目,显然所有由两个或者以上的属性的元素会被算重恰好两次。

接下来,只要我们参与运算的量都是形如【钦定拥有 >1 种属性的元素数目】,那么那些只有一个属性的元素就不会受到影响了,他们就已经彻底被解决了。

那么我们减去钦定拥有 2 个属性的元素的数目,但是这样似乎又会减多了,虽然拥有两个属性的东西的数目都正确了,但是拥有更多属性的都降到零了。

所以为了填补这部分的空缺,继续重复以上过程直到结束(计算完【钦定拥有 n 个属性的元素的数目】之后就进行不下去了),就得到了最上面的式子。

根据刚刚的过程,回顾一下式子的含义:

|i=1n{x|pi(x)}|=i=1n(1)i1T[1,n],|T|=i|jT{x|pj(x)}|

这里把 Si 展开写成了 {x|pi(x)},其中标红的 pk(x) 就是刚刚说的“属性”。

标为橙色的部分代表的就是“钦定有 i 个属性”的元素数目。

标为蓝色的叫做容斥系数,代表了刚刚过程中加上还是去掉的动作,一般来说容斥系数的指数就是“钦定”的属性的数目减去一。

变型

一般来说,容斥原理适用于以下的两种情况:

  1. 计数满足多个条件其一的对象数目。把满足一个条件的对象组成一个集合,然后直接套用容斥即可。
  2. 计数满足所有条件的对象数目。这个时候把限制取反,那么计数的对象转变为求所有满足至少一条限制的对象数目,这个可以用容斥做,再用全集的大小减去这个答案。

经验:做容斥题的时候,想办法让“限制的数目”变成一个常量,方法包括但不限于加入大小为零的对象、不可能满足的条件等。

而对于后面的一种情况,式子可以写作:

|i=1nSi|=|U||i=1nSi|=|U|i=1n(1)i1T[1,n],|T|=i|jTSj|=|U|+i=1n(1)iT[1,n],|T|=i|jTSj|

所以,这种情况下需要做的是:把容斥系数的指数加一;限制取反;最终加上全集的大小。

容斥恒等式

事实上,容斥原理的表达式还蕴含了一个信息:每个元素对于右侧式子的贡献为 1,对左侧式子的贡献也为 1 .

换句话说,如果每个元素的权值不一样的情况下,对于任意的函数 f(x) 而言,也有如下形式的容斥原理:

x([xi=1nSi]f(x))=i=1n(1)i1T[1,n],|T|=i(x[xjTSj]f(x))

呃这么写似乎有点反人类

用另一种方法来写的话,我们考虑到表达式右侧的部分,相当于在 x 的限制集合中,挑选出一些,并根据挑选出的多少决定 x 向总和中贡献 1 还是 1 次,也就是下面的式子:

1=T[1,n],T(1)|T|1

很自然的,我们想把 T= 的情况包括进去。

0=T[1,n](1)|T|1

但是这里我们默认了 n1,去掉这个条件之后,就有了

[S=]=TS(1)|T|

这个恒等式就是容斥原理的本质了,它对于任意的集合 S 都成立。

证明的话,用二项式系数就可以了。

§ 0.1 子集反演

所以,不知道是出于什么原因,你有了一个关于集合的函数 g(A) 和一个集合 S,我们定义函数 f(A) 如下:

f(A)=BAg(B)

现在你已知任意 TSf(T),能否求得 g(S) 呢?

这是一个标准的反演问题,笔者会在不久后写一篇专门的博文。但是这里先用容斥原理解决。

考虑用容斥解决,我们定义一堆新的集合 {Sx},一个元素就是一个 g(Sx),要求的是 {Sx}中满足【 S 中每一个元素被选定到其中】的 Sk 所对应的 g(S) .

而这是限制的交集,每一个限制形如 “S 中的某个元素 x 被选定到 Sk 中”。

用容斥解决的话先找出全集的贡献:【对于所有 TSg(T) 的和】。然后再把限制取反:【钦定某几个元素不选定到 S 中】。最后容斥系数就是钦定了几个:(1)|A| .

所以我们轻松地得到了式子:

g(S)=V+i=1n(1)iT[1,n],|T|=iF(T)

V 表示全集的贡献,而不是全集本身。

其中 F(T) 表示【 T 中的元素全都不出现在其中】的所有 Skg 函数值之和,而这其实就是 f(ST) . 然后交换一下求和顺序,可以得到:

g(S)=V+TS,T(1)|T|f(ST)

观察到 V 这一项可以和后面的东西合并(T=)。最后换元,整个式子化简成:

g(S)=TS(1)|S||T|f(T)

加上条件:

f(S)=TSg(T)g(S)=TS(1)|S||T|f(T)

这个就叫子集反演

然后我们令 S=US,T=UT

f(US)=UTUSg(UT)g(US)=UTUS(1)|US||UT|f(UT)

做一些小调整:

f(US)=TSg(UT)g(US)=TS(1)|T||S|f(UT)

然后再定义两个新函数:

F(A)=f(UA)G(A)=g(UA)

带入刚刚的式子:

F(S)=TSG(T)G(S)=TS(1)|T||S|G(T)

这就是子集反演的补集形式。能不能叫超集反演

§ 0.2 二项式反演

把刚刚子集反演的 g(A) 定义为 |A|,就得到了二项式反演。

§ 0.3 Min-Max容斥

基本形式

现在你有一些数字,你需要求出它们的最大值,但是你不能比较两个元素的大小,只能查询任意一个集合里面的最小值。

这该怎么做呢?

我们把一个数字 x 换成一个集合 {1,2,,x},那么一堆数字的 max 可以看作一堆集合的并集;一堆数字的 min 可以看做一堆集合的交集

诶,这个就可以容斥了。

maxxSx=TS,|T|>0(1)|T|1minyTy

当然,我们把 x 映射到的集合改成 {x+1,x+2,,maxkSk},就可以得到利用 max 计算 min 的情况了,如下(记 maxkSk=M):

MminxSx=TS,|T|>0(1)|T|1(MmaxyTy)

化简:

MminxSx=TS,|T|>0(1)|T|1MTS,|T|>0(1)|T|1maxyTy

根据容斥恒等式,有:

minxSx=TS,|T|>0(1)|T|1maxyTy

这个和上面那个式子就叫做 Min-Max 容斥。

虽然没人会用这种方式求最大值,但是这个东西是可以推广到期望中的!

在期望方面的应用

假如我们想要计算一个序列最大值的期望:

d|nφ(d)=n

posted @   HMSF  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示