数学总结 5(简单容斥、二项式反演、子集反演、Min-Max 容斥初步)

一、简单容斥

错排问题

求有多少种长度为 \(n\) 的排列满足对于每一位 \(i\),有 \(p_i \not= i\)

一种方法是线性递推
显然有 \(f(1)=0,f(2)=1\),考虑 \(f(n)\) 如何求解。
对于 \(n-1\) 的错排,可以把其中每一个数分别和 \(n\) 位置交换,获得新的排列,即 \((n-1) f(n-1)\)
也可以钦定某一位 \(p_i = i\),把 \(i\)\(n\) 位置交换即可,而 \(i\)\(n-1\) 种取值,所以方案数是 \((n-1) f(n-2)\)
因此有:\(f(n) = (n-1)(f(n-1) + f(n-2))\)

也可以从容斥的角度解决该问题:

考虑钦定一些点不满足条件,即 \(p_x = x\)
先选出 \(i\) 个位置不满足条件,则方案数为 \(C_n^i\)
剩下的位置可以随便排,所以方案数为 \(C_n^i (n-i)!\)
然后容斥一下就是:

\[\sum\limits_{i=0}^{n} (-1)^i C_n^i (n-i)! \]

\[=n! \sum\limits_{i=0}^{n} (-1)^i \frac{1}{i!} \]

例 1:洛谷 P1450 HAOI2008 硬币购物

考虑容斥转化为好求的东西。

要容斥肯定要先有总数,这是好求的,是完全背包板子(即每个硬币不限使用量)。
然后枚举哪些硬币超出了范围,直接用 \(s\) 减掉 \((d+1)c\) 就是剩下的价值,也是不限量。
那么只要做一次完全背包就可以容斥算出答案。

例 2:CF1228E Another Filling the Grid

想了各种各样奇怪的做法,例如什么行列分开算之类的,枚举几行 \(\gt 1\) 求出行方案数,再另外枚举几列 \(\gt 1\) 在行的方案数基础上继续算。
但事实证明最直接的做法最简单。

由于 \(n\) 很小,可以直接枚举 \(i,j\) 表示至少\(i\)\(j\) 列全 \(\gt 1\),那么就有 \(t= (i+j)n - ij\) 个格子必须 \(\gt 1\),方案数 \((k-1)^t\);其余的可以随便填方案数 \(k^{n^2-t}\)
然后容斥一下就好了,系数为 \((-1)^{i+j}\)

为什么会想到容斥?

如果直接钦定某一行最小值为 \(x\) 并不好做,但是可以钦定最小值 \(\geq x\),这样 \([x,k]\) 的数随便填,方案数可以直接算出来。
要还原回某一行最小值 \(x\) 只需要做容斥就可以了,类似于莫反,也可以看作是一个后缀差求出单点值。

例 3:洛谷 P5505 JSOI2011 分特产

和之前相同地,刚好有 \(n\) 个同学至少拿到一个,改为前缀形式:\(f_i\) 表示有 \(\leq i\) 个同学获得至少一个。
如何求 \(f_i\)?先组合数确定有 \(C_n^i\) 种选法,然后对每个特产分别算贡献再乘法原理:相当于 \(a_j\) 个球扔进 \(i\) 个盒子,方案数 \(C_{i+a_j-1}^{i-1}\)
容斥一下,答案显然是 \(ans = \sum\limits_{i=0}^n (-1)^{n-i} C_n^i \times \prod \limits_{j=1}^{m} C_{i+a_j-1}^{i-1}\)

例 4:洛谷 P6076 JSOI2015 染色问题

容斥套容斥。
颜色看着很烦,先把它容斥掉变成好做的形式:设 \(dp_i\) 表示用 \(\leq i\) 种颜色填充的方案数,则答案为:

\[\sum\limits_{i=0}^{c} (-1)^{c-i} C_c^i dp_i \]

接下来这题不能像前面 CF1228E 一样枚举 \(i,j\) 分别考虑每个点,因为不能整行整列为空是一个整体,无法用零散的点完整表示信息。

所以老老实实一列一列容斥,和“恰好 \(c\) 种颜色一样”,恰好 \(m\) 列也可以变成 \(\leq m\) 列再容斥回来。
先选出 \(j\) 列:\(C_m^j\),然后对于每一行,只关注这 \(j\) 列的取值,它们不能全空,但可以从 \(i+1\) 种颜色(含空)之中任选,最后 \(n\) 行是独立的,所以方案数 \(((i+1)^j-1)^n\),因此:

\[dp_i = \sum\limits_{j=0}^m (-1)^{m-j} C_m^j ((i+1)^j-1)^n \]

……

但显然有一种更简单的方法。
三维枚举 \(i,j,k\) 表示几行全空,几列全空,只用多少种颜色,对于没有被选中的格子可以任意填剩下 \(c-k\) 种颜色或空,那么答案就是:

\[\sum\limits_{i=0}^n \sum\limits_{j=0}^m \sum\limits_{k=0}^c C_n^i C_m^j C_c^k (c-k+1)^{(n-i)(m-j)} \]

例 5:AGC005D ~K Perm Counting

错排问题的拓展,这一步数形结合还是太牛了。
由于和错排问题很相似,所以仍然考虑容斥,求出 \(\geq i\)不合法的位置有多少种方案。
然后数字与位置之间不能匹配(间隔为 \(k\))的条件很像二分图匹配,所以考虑用二分图辅助推导。
对于左部点(数字)向右部点(位置)相差恰好 \(k\) 的点连边,然后钦定它恰好有 \(i\) 条边被选择匹配,剩下的就乱排,方案数是阶乘,乘在一起就是 \(\geq i\) 个不合法的方案数。
注意到这个二分图有一些普通二分图没有的性质:点连成,每条链是独立的
那么对于每条链单独求方案数:设 \(dp_{i,j,0/1}\) 表示这条链计算到第 \(i\) 个点,匹配了 \(j\) 条边,第 \(i\) 个点是否被一条匹配边连上。
显然有:

\[dp_{i,j,0} = dp_{i-1,j,0} + dp_{i-1,j,1} \]

\[dp_{i,j,1} = dp_{i-1,j-1,0} \]

转移就完了,如果对每条链分别做最后还要求一个背包,事实上可以把这些链首尾相连拼在一起,在链头特判不能转移到 \(dp_{i,j,1}\) 即可。
\(f_i=dp_{2n,i,0}+dp_{2n,i,1}\),表示恰好有 \(i\) 个位置不合法(选了 \(i\) 条边),则答案为:

\[ans=\sum\limits_{i=0}^n (-1)^i f_i \times (n-i)! \]

例 6:\(\color{skyblue}{DTOJ ~ P2431 棋盘路径(path)}\)

题目大意:
有一个 \((n+1) \times (m+1)\) 的网格,求从 \((0,0)\) 走到 \((n,m)\) 的方案数(只能往右往下走)。
网格内有 \(k\) 个障碍物 \((x_1,y_1), (x_2,y_2), \dots, (x_k,y_k)\),在走的过程中不能触碰。
答案对 \(10^9+7\) 取模,\(n,m \leq 10^5, k \leq 3000\)

不妨转化一下:求不经过其它障碍物到达第 \(i\) 个障碍物的方案数,设其为 \(f_i\)
钦定 \((n,m)\) 是第 \(k+1\) 个障碍。则答案为 \(f_{k+1}\)
到达一个障碍而不能经过其它障碍,考虑容斥,由于它只可能经过它左上方区域的障碍物,所以用这些障碍物作“中转站”,先到达其它障碍物再走到这个障碍物。
显然从 \((0,0)\) 走到 \((x,y)\) 无障碍的方案数为 \(\binom{x+y}{x}\)
时间复杂度 \(O(k^2)\)


二、二项式反演

学习链接之一

类似于莫反。
\(f_i\) 表示恰好选了 \(i\) 个元素组合成满足条件形式的方案数;设 \(g_i\) 表示用 \(\leq n\) 个元素组合的方案数。
则二项式反演的常用形式为:

  • 一般形式:

\[\color{red}{g_n = \sum\limits_{i=0}^{n} \binom{n}{i} f_i \Longleftrightarrow f_n = \sum\limits_{i=0}^{n} (-1)^{n-i} \binom{n}{i} g_i} \]

  • 加下界:

\[g_n = \sum\limits_{i=m}^{n} \binom{n}{i} f_i \Longleftrightarrow f_n = \sum\limits_{i=m}^{n} (-1)^{n-i} \binom{n}{i} g_i \]

  • 上指标求和(常用于钦定至少有、恰好有,如错排问题):

\[\color{red}{g_n = \sum\limits_{i=m}^{n} \binom{i}{m} f_i \Longleftrightarrow f_m = \sum\limits_{i=m}^{n} (-1)^{i-m} \binom{i}{m} g_i} \]

例 7:CF285E Positions in Permutations

和 AGC005D 很相似。
要求恰好 \(m\) 个满足条件的位置,这不好做,还是转化为 \(\geq m\) 个之后再容斥
首先钦定有 \(m\) 个满足条件,然后剩下的可以随便放。钦定部分还是 AGC005D 的 DP 部分方案数,剩下乱排方案数还是阶乘。
我们设 \(f_m\) 表示恰好 \(m\) 个,\(g_m\) 表示 \(\geq m\) 个。
于是有 \(g_m = \sum\limits_{i=m}^n \binom{i}{m} f_i\),根据上述推导还有 \(g_m = dp_{2n,i,0/1} \times (n-i)!\)
那么 \(g\) 是容易求的,这个形式很二项式反演,所以 \(f_m = \sum\limits_{i=m}^n (-1)^{i-m} \binom{i}{m} g_i\)

例 8:洛谷 P4859 已经没有什么好害怕的了

首先并不难推出需要恰好 \(\frac{n+k}{2}\) 个满足 \(a \gt b\) 的位置,以下设其为 \(m\)
恰好不好做,改为钦定再做容斥。
\(g_i\) 表示有 \(\geq i\) 个位置满足条件,则先钦定有 \(i\) 个剩下乱排。
如何求出恰好有 \(i\) 个的方案数?由于 \(n \leq 2000\),考虑 \(O(n^2)\) 做法,例如 DP 计数。
\(dp_{i,j}\) 表示做到 \(a\) 的第 \(i\) 个(\(a,b\) 均已排序),有 \(j\)\(a \gt b\) 的方案数,设 \(c_i\) 表示 \(b\) 中有多少个 \(\lt a_i\) 的数。
则不难推出转移式:

\[dp_{i,j} = dp_{i-1,j} + dp_{i-1,j-1} \times (c_i-j+1) \]

于是有 \(g_i = dp_{n,i} (n-i)!\)
由于 \(g_m = \sum\limits_{i=m}^n \binom{i}{m} f_i\),不难反演得到 \(f_m\)


三、子集反演

\[\color{red}{g_S = \sum\limits_{T \subseteq S} f_T \Longleftrightarrow f_S = \sum\limits_{T \subseteq S} (-1)^{|S|-|T|} g_T } \]

例 9:Bitwise And Convolution

求 And 卷积。
一眼 FWT 啊但是我 FWT 才学了一半。
那就上子集反演吧。

先转化为 \(g\) 的子集和形式,相当于要求 \(x,y\) 同时包含 \(z\) 就把 \(c_z\) 加上 \(a_x \times b_y\)
即求出所有满足 \(x\) 包含 \(z\)\(a_x\) 之和,\(b\) 同理,再相乘。
最后反演回 \(f\) 就是答案,复杂度 \(O(3^n)\)
然后被卡了。

所以又回来补 FWT 了。跳转链接

不过后来想了想貌似不需要 \(O(3^n)\)?类似于状压 DP 一位一位转移好像也可以做到 \(O(n 2^n)\)

例 10:CF449D Jzzhu and Numbers

事实上,对于 \(\forall i\),都可以算出与和为 \(i\) 的方案数。
\(f_i\) 表示与和恰好为 \(i\) 的方案数,考虑子集反演,设 \(g_i\) 表示与和是 \(i\)超集的方案数。
既然是超集首先要知道 \(i\)多少个超集,设它为 \(c_i\),那么显然有 \(g_i = 2^{c_i} - 1\),因为不能选空。
显然 \(g_i,f_i\) 可以子集反演互推。

例 11:AT_tokiomarine2020_e O(rand)

简单题想了两个小时 /ll
看到这题有两个思路:

  1. 类似于之前某道题,把下界干成 \(0\) 变成单上界,接下来再搞一堆观察或许会有性质。
  2. 直接对二进制位容斥。

结果最后的做法成了两个的杂交版。
首先显然有 \(S \subseteq T\),为了简化问题,先进行如下转化:

  1. 依次考虑每一个二进制位,若 \(T=0,a=1\) 则这个 \(a\) 对答案没有贡献可以删掉,即 \(T ~|~ a \not= T\)
  2. \(S=1, a=0\) 也没有贡献,即 \(S \& a \not= S\)
  3. 把确定无贡献的数全都踢出去之后,为了简化二进制形式,只把 \(T - S\) 二进制下为 \(1\) 的位保留,其它都删掉(类似于线性基重排二进制位)。

此时 \(T\)\(1\),只需要选择一些 \(a\) 使得它们与和为 \(0\) 或和为全集即可。
正难则反,考虑一个二进制位如何才能不满足条件

  1. 选出的所有数这一位都为 \(0\)
  2. 选出的所有数这一位都为 \(1\)

接下来对二进制位容斥,设 \(f_i\) 表示选择了 \(i\) 这个集合的二进制位,恰好只有这些位不满足条件的方案数。
一种转化是位置集合 \(i\) 的每一位都必须至少有一个 \(0\)\(1\),但推了半天没什么进展。
然后转回来想想直接做就是对的:即对于 \(i\) 集合的每一位,选出的数在这一位都必须相同
设选出的数是 \(a_1,a_2,\dots,a_k\),则 \(a_j \& i\) 相同的 \(a\) 才能同时被选择。

显然可以用一个桶维护 \(a_j \& i\) 的数字数量,然后组合数前缀和求一下选 \(1 \leq x \leq k\) 个数的方案数。
由于算出来的是 \(g_i\) 表示 \(i\)超集选择方案数,所以最后子集反演即可求出 \(f_0\)

例 12:CF1530F Bingo

首先如果只有行的限制是好做的。
但题目添加了列和对角线,由于只有两条对角线,考虑简化问题,不管后面怎么做先把对角线 \(2^2\) 种方案容斥掉。
首先最暴力的做法是枚举选择的行列集合,它们全为 \(1\) 的概率是包含格子的概率乘积,剩下的格子随便取,设乘积为 \(val\) 则答案为 \(\sum\limits_{S} \sum\limits_{T} val(S,T)\)
这样复杂度是 \(O(2^{2n})\),但容易发现只需要枚举 \(T\),对于 \(S\) 按行做容斥即可。
具体地,记 \(s0,s1\) 表示 \(|S|\) 分别为偶数、奇数的权值乘积之和,转移的时候考虑这一位选和不选的情况即可。
容易做到 \(O(2^n n^2)\),瓶颈在预处理,但是预处理也容易优化到 \(O(2^n n)\),注意求逆元不要套一个 \(\log V\),逆元也要预处理。

例 13:洛谷 P3349 ZJOI2016 小星星

不难写出朴素 DP:设 \(dp_{u,S,v}\) 表示树上 \(u\) 子树对应原图编号 \(S\) 集合,\(u\) 对应的编号是 \(v\) 的方案数。
这样枚举 \(u\) 和树上儿子,再枚举它们分别对应什么编号,还需要枚举对应集合,复杂度达到了高贵的 \(O(2^{2n}n^4)\)
考虑优化,首先由于儿子的集合一定是 \(u\) 集合的子集,改为子集枚举可以优化到 \(O(3^n)\);其次并不需要枚举儿子对应的编号,可以邻居和搞一下变成 \(O(1)\) 查询,至此复杂度为 \(O(3^n n^3)\)
枚举 \(u\) 和它的编号,再枚举儿子转移显然没有优化空间了,而主要瓶颈在于子集枚举。

能否通过“篡改”题目要求让 DP 状态更简单?
可以的,利用子集反演。
之前的算法为什么要枚举 \(S\)?因为图中的点不能算重,而子集反演转化后钦定它“可以算重”。
设树上点 \(u\) 的一个儿子是 \(v\)\(u\) 对应编号 \(a\)\(v\) 对应编号 \(b\),那只要满足图中 \(a,b\) 相邻即可。
\(f_S\) 表示树上的点恰好对应图中 \(S\) 集合的编号,则 \(f_{2^n-1}\) 就是答案;能算重意味着设 \(g_S = \sum\limits_{T \subseteq S}\),对于 \(g_S\) 的计算只要求 \(a,b \in S\)
那么枚举 \(S\),树形 DP 求出 \(g_S\) 之后再子集反演求 \(f_{2^n-1}\)。具体地,设 \(dp_{u,a}\) 表示树上 \(u\) 子树,\(u\) 对应编号 \(a\) 的方案数。
复杂度降低为 \(O(2^n \times n^4)\),但跑不满,而且用邻居 dp 值之和优化可以降低为 \(O(2^n \times n^3)\)


四、Min-Max 容斥(最值反演)初步

常用于 \(\max, \min\) 其一求解简单的时候用来求另一个。

\[\max \{S\} = \sum_{T \subseteq S}(-1)^{|T|+1} \min \{T\} \]

\[\min \{S\} = \sum_{T \subseteq S}(-1)^{|T|+1} \max \{T\} \]

简单证明一下第一个式子,至于第二个式子同理。

\(k\)\(S\) 中最大的数。
右边的式子只有当 \(T= \{k\}\) 的时候才等于 \(k\)
其它情况有 \(k\) 和没 \(k\)\(\min\) 是相同的,所以加减抵消为 \(0\)

还有扩展 Min-Max 容斥:

\[\text{kmax} \{ S \} = \sum\limits_{T \subseteq S, |T| \geq k} (-1)^{|T| - k} \binom{|T|-1}{k-1} \min \{ T \} \]

\[\text{kmin} \{ S \} = \sum\limits_{T \subseteq S, |T| \geq k} (-1)^{|T| - k} \binom{|T|-1}{k-1} \max \{ T \} \]

其中 \(\text{kmax}\) 表示集合中第 \(k\) 大的,\(\text{kmin}\) 同理。

Min-Max 容斥一般和期望、gcd 相关题结合,这里以期望举几个例子:

例 14:洛谷 P3175 HAOI2015 按位或

直接做看上去是一个很难的东西。
不妨先来想想弱化版:

有一个抽奖机,内置 \(n\) 种卡牌,每次抽奖编号为 \(i\) 的卡牌有 \(p_i\) 的概率被抽到,\(\sum\limits_{i=1}^{n} p_i = 1\),问抽到所有卡的期望次数。

抽到所有卡的期望次数相当于最晚被抽到的卡的时间
但这个也非常难做……所以 Min-Max 容斥一下!
由于期望的线性性,有:

\[E \big[ \max \{S\} \big] = \sum_{T \subseteq S}(-1)^{|T|+1} E \big[ \min \{T\} \big] \]

因此转化一下变成求解一个卡牌编号集合 \(T\) 的期望 \(\min\),即最早被抽到的卡期望抽到时间
这个就简单了,先求概率:\(P(T) = \sum\limits_{i \in T} p_i\),就是抽一发抽到 \(T\) 集合内的概率。
那么不难推导出期望次数就是 \(\frac{1}{P(T)}\)
于是就做完了,最后容斥回来就行,复杂度 \(O(2^n)\)


回到本题,改变之处在于一次可以抽到多种卡牌,即一个集合 \(S\) 内的所有卡同时获得。
但还是一样地,只要 \(T\) 内有至少一个元素被抽到,那么它就满足条件。
所以现在要求 \(P(T)\) 表示所有和集合 \(T\) 有交的集合的概率之和。
这不好做。正难则反,求和 \(T\) 无交的集合的概率之和。
这依然不好做。正难则反,求为 \(T\)补集的子集的概率之和。
好了,这下就是高维前缀和板子了,复杂度 \(O(n 2^n)\)

例 15:洛谷 P5643 PKUWC2018 随机游走

太喜欢这题了,一路推下来真的很顺……

首先看到所有点都经过至少一次,这很困难,所以 Min-Max 容斥转成经过集合内至少一个点的期望步数。
然后考虑这个怎么求,这不就是 概率与期望专题 的经典问题吗……
如果直接高斯消元,那总复杂度达到了高贵的 \(O(2^n n^3)\),但显然有 \(O(n)\) 做法。

不妨枚举 \(T\) 集合,设 \(f_i\) 为从 \(i\) 走到 \(T\) 集合内任意一点的期望步数,显然对于 \(i \in T\),有 \(f_i = 0\)

\[f_u = \frac{1}{deg_u} \times \Big( f_{fa} + \sum\limits_{v \in son_u} f_{v} \Big) + 1 \]

\[deg_u \times f_u = f_{fa} + \sum\limits_{v \in son_u} \Big( k_v \times f_u + b_v \Big) + deg_u \]

\[(deg_u - \sum\limits_{v \in son_u} k_v) f_u = f_{fa} + deg_u + \sum\limits_{v \in son_u} b_v \]

\[\color{red}{ k_u = \frac{1}{deg_u - \sum\limits_{v \in son_u} k_v} } \quad \color{blue}{ b_u = \frac{\sum\limits_{v \in son_u} deg_u + b_v}{deg_u - \sum\limits_{v \in son_u} k_v} } \]

于是 \(O(n)\) 就可以求解 \(f\) 数组。
接下来 min-max 容斥回去:

\[E \big[ \max \{S\} \big] = \sum_{T \subseteq S}(-1)^{|T|+1} E \big[ \min \{T\} \big] \]

这是个简单的高维前缀和
所以总复杂度 \(O(2^n n)\)

例 16:洛谷 P4707 重返现世

由于 \(n-k\) 很小,做法大概率要基于这件事。
题目要求的是一个类似于 \(\text{kmin}\) 的东西,不妨先令 \(k \leftarrow n-k+1\),然后求 \(\text{kmax}\)。这两件事本质上是等价的,因为第 \(k\) 小的元素就是第 \(n-k+1\) 大的元素。
然后代入式子:

\[\text{kmax} \{ S \} = \sum\limits_{T \subseteq S, |T| \geq k} (-1)^{|T| - k} \binom{|T|-1}{k-1} \min \{ T \} \]

这也可以改写为期望形式。
对于一个集合的 \(\min\) 是好求的,显然为 \(\displaystyle \frac{m}{\sum\limits_{i \in T} p_i}\)
难点在于如何求出所有满足条件 \(T\) 的和

考虑一个个加入元素 \(i\),设 \(\sum p = j\),容斥的“下界”为 \(k\)\(|T| \geq k\)),以此设计一个 DP 状态 \(dp_{i,j,k}\) 表示容斥系数之和
这样的好处是对于同一个 \(j\),它的贡献 \(\min \{T\}\) 是已知的,所以只要 DP 求出容斥系数总和即可。

然后就是很妙的由状态反推转移方程

\[\sum\limits_{|T| \geq k} (-1)^{|T| - k} \binom{|T|-1}{k-1} \]

由于 \(\binom{|T|-1}{k-1} = \binom{|T|-2}{k-2} + \binom{|T|-2}{k-1}\)
所以有:

\[(-1)^{|T|-k} \binom{|T|-1}{k-1} = (-1)^{(|T|-1)-(k-1)} \binom{|T|-2}{k-2} - (-1)^{(|T|-1)-k} \binom{|T|-2}{k-1} \]

这是选择元素 \(i\) 的转移,再加上不选择元素 \(i\),就是:

\[dp_{i,j,k} = dp_{i-1,j,k} + (dp_{i-1,j-p_i,k-1} - dp_{i-1,j-p_i,k}) \]

转移是 \(O(nm(n-k))\) 的,显然可以滚动数组优化空间。
初始化 \(dp_{0,0,0}=1\)

posted @ 2025-05-22 17:31  Conan15  阅读(108)  评论(0)    收藏  举报