容容容容斥斥斥容容斥(完善中)
Part 0 容斥原理
§ 0.0 容斥原理及其本质
表达式各个部分的含义
最常见到的容斥原理的形式如下:
如何理解?
假如说我们面对一个特殊的问题,计算某些集合的交集十分容易,也就是说,我们可以在极低的开销下,指定若干个属性,并统计拥有这些属性的元素的个数。
注意,不是“恰好拥有”,而就是简单的“拥有”。
现在我们定义一种操作,指定一个 \(k\),对于所有大小为 \(k\) 的,由属性组成的集合,分别查询拥有这个集合内全部属性的元素个数,然后把所有结果相加。
注意!这里查询的不是并集,有一些元素会被计算多次!一些博客文章会把这种操作称为“查询至少有 \(k\) 个属性的元素数目”,这种称呼其实不是很严谨。
为了下面的叙述方便,我们把这一操作称为 “钦定拥有 \(k\) 个属性的元素数目”,这也是 OI 界对这种形式的操作的通常称呼。
那在这种条件下,如何统计一共有几个元素至少有一种属性呢?
我们统计钦定拥有 \(1\) 个属性的元素数目,显然所有由两个或者以上的属性的元素会被算重恰好两次。
接下来,只要我们参与运算的量都是形如【钦定拥有 \(>1\) 种属性的元素数目】,那么那些只有一个属性的元素就不会受到影响了,他们就已经彻底被解决了。
那么我们减去钦定拥有 \(2\) 个属性的元素的数目,但是这样似乎又会减多了,虽然拥有两个属性的东西的数目都正确了,但是拥有更多属性的都降到零了。
所以为了填补这部分的空缺,继续重复以上过程直到结束(计算完【钦定拥有 \(n\) 个属性的元素的数目】之后就进行不下去了),就得到了最上面的式子。
根据刚刚的过程,回顾一下式子的含义:
这里把 \(S_i\) 展开写成了 \(\{x|p_i(x)\}\),其中标红的 \(p_k(x)\) 就是刚刚说的“属性”。
标为橙色的部分代表的就是“钦定有 \(i\) 个属性”的元素数目。
标为蓝色的叫做容斥系数,代表了刚刚过程中加上还是去掉的动作,一般来说容斥系数的指数就是“钦定”的属性的数目减去一。
变型
一般来说,容斥原理适用于以下的两种情况:
- 计数满足多个条件其一的对象数目。把满足一个条件的对象组成一个集合,然后直接套用容斥即可。
- 计数满足所有条件的对象数目。这个时候把限制取反,那么计数的对象转变为求所有满足至少一条限制的对象数目,这个可以用容斥做,再用全集的大小减去这个答案。
经验:做容斥题的时候,想办法让“限制的数目”变成一个常量,方法包括但不限于加入大小为零的对象、不可能满足的条件等。
而对于后面的一种情况,式子可以写作:
所以,这种情况下需要做的是:把容斥系数的指数加一;限制取反;最终加上全集的大小。
容斥恒等式
事实上,容斥原理的表达式还蕴含了一个信息:每个元素对于右侧式子的贡献为 \(1\),对左侧式子的贡献也为 \(1\) .
换句话说,如果每个元素的权值不一样的情况下,对于任意的函数 \(f(x)\) 而言,也有如下形式的容斥原理:
\[\sum_{x}\left(\left[ x\in \bigcup_{i=1}^{n} S_{i}\right]f(x)\right) = \sum_{i=1}^{n} (-1)^{i-1} \sum_{T\subseteq[1,n],|T|=i }\left(\sum_{x}\left[ x\in \bigcap_{j\in T} S_j \right]f(x)\right) \]
呃这么写似乎有点反人类
用另一种方法来写的话,我们考虑到表达式右侧的部分,相当于在 \(x\) 的限制集合中,挑选出一些,并根据挑选出的多少决定 \(x\) 向总和中贡献 \(1\) 还是 \(-1\) 次,也就是下面的式子:
很自然的,我们想把 \(T=\emptyset\) 的情况包括进去。
但是这里我们默认了 \(n\geq 1\),去掉这个条件之后,就有了
这个恒等式就是容斥原理的本质了,它对于任意的集合 \(S\) 都成立。
证明的话,用二项式系数就可以了。
§ 0.1 子集反演
所以,不知道是出于什么原因,你有了一个关于集合的函数 \(g(A)\) 和一个集合 \(S\),我们定义函数 \(f(A)\) 如下:
现在你已知任意 \(T\subseteq S\) 的 \(f(T)\),能否求得 \(g(S)\) 呢?
这是一个标准的反演问题,笔者会在不久后写一篇专门的博文。但是这里先用容斥原理解决。
考虑用容斥解决,我们定义一堆新的集合 \(\{S_x'\}\),一个元素就是一个 \(g(S_x')\),要求的是 \(\{S_x'\}\)中满足【 \(S\) 中每一个元素被选定到其中】的 \(S_k'\) 所对应的 \(g(S')\) .
而这是限制的交集,每一个限制形如 “\(S\) 中的某个元素 \(x\) 被选定到 \(S_k'\) 中”。
用容斥解决的话先找出全集的贡献:【对于所有 \(T\subseteq S\),\(g(T)\) 的和】。然后再把限制取反:【钦定某几个元素不选定到 \(S'\) 中】。最后容斥系数就是钦定了几个:\((-1)^{|A|}\) .
所以我们轻松地得到了式子:
\(V\) 表示全集的贡献,而不是全集本身。
其中 \(F(T)\) 表示【 \(T\) 中的元素全都不出现在其中】的所有 \(S_k\) 的 \(g\) 函数值之和,而这其实就是 \(f(S-T)\) . 然后交换一下求和顺序,可以得到:
观察到 \(V\) 这一项可以和后面的东西合并(\(T=\emptyset\))。最后换元,整个式子化简成:
加上条件:
这个就叫子集反演。
然后我们令 \(S = \complement_{U}S,T = \complement_{U}T\)
做一些小调整:
然后再定义两个新函数:
带入刚刚的式子:
这就是子集反演的补集形式。能不能叫超集反演
§ 0.2 二项式反演
把刚刚子集反演的 \(g(A)\) 定义为 \(|A|\),就得到了二项式反演。
§ 0.3 Min-Max容斥
基本形式
现在你有一些数字,你需要求出它们的最大值,但是你不能比较两个元素的大小,只能查询任意一个集合里面的最小值。
这该怎么做呢?
我们把一个数字 \(x\) 换成一个集合 \(\{1,2,\cdots,x\}\),那么一堆数字的 \(\max\) 可以看作一堆集合的并集;一堆数字的 \(\min\) 可以看做一堆集合的交集。
诶,这个就可以容斥了。
当然,我们把 \(x\) 映射到的集合改成 \(\{x+1,x+2,\cdots,\max_{k\in S}k\}\),就可以得到利用 \(\max\) 计算 \(\min\) 的情况了,如下(记 \(\max_{k\in S}k = M\)):
化简:
根据容斥恒等式,有:
这个和上面那个式子就叫做 Min-Max 容斥。
虽然没人会用这种方式求最大值,但是这个东西是可以推广到期望中的!
在期望方面的应用
假如我们想要计算一个序列最大值的期望: