容斥原理基础应用

容斥原理基础应用

\[\left| \bigcup_{i = 1}^{n} S_i \right| = \sum_{P \subseteq \{1, 2, \dotsb, n\}} (-1)^{|P| - 1} \left| \bigcap_{x \in P} S_x \right| \]

容斥原理一般用来实现计数问题中“恰好”与“至少”的转化。

不定方程非负整数解计数

给出 \(\sum_\limits{i = 1}^{n} x_i = m\),另外给出 \(n\) 个限制 \(x_i \le a_i\),其中 \(m, a_i \in \N\),求方程非负整数解个数。

若没有上界限制,用插板法可以得到非负整数解个数为 \(\dbinom{m + n - 1}{n - 1}\)

先进行补集转化,再应用容斥原理。钦定 \(k\)\(x\) 不满足条件,设钦定的位置为 \(\{p_k\}\),考虑去掉这 \(k\) 个下界限制,将方程转化为 \(\sum_\limits{i = 1}^{n} x_i = m - \sum_\limits{i = 1}^{k} (a_{p_i} + 1)\),于是转化为没有上界限制的情况,用组合数计算即可。

全错位排列

设同一集合中的每个元素都同时满足某种性质,

则 “交” 表示“均满足”;“并” 表示“满足任意一个”。

\(n\) 阶全错位排列数为 \(T_n\)

设满足元素 \(i\) 在位置 \(i\) 上的排列集合为 \(S_i\),则所求答案是 \(T_n = \left|\bigcap_\limits{i = 1}^{n} \overline{S_i}\right|\),即 \(n\) 个补集的交大小。

首先根据减法原理 \(T_n = \left|\bigcap_\limits{i = 1}^{n} \overline{S_i}\right| = n! - \left|\bigcup_\limits{i = 1}^{n} S_i\right|\),接下来对等式右边第二项应用容斥原理:

\[\begin{aligned} \left|\bigcup_\limits{i = 1}^{n} S_i\right| &= \sum_{m = 1}^{n}(-1)^{m - 1}\sum_{\{p_m\}}\left|\bigcap_{i = 1}^{m} S_{p_i}\right| \end{aligned} \]

考虑 \(\left|\bigcap_\limits{i = 1}^{m}S_{p_i}\right|\),即有 \(m\) 个元素在原位置的排列数(注意我们并没有钦定剩下的元素是否在原位置,所以准确的说法是“至少有 \(m\) 个元素在原位置的排列数”)。不难发现这个值和我们钦定了哪些位置无关,只与钦定的位置数 \(m\) 有关:这 \(m\) 个元素固定,剩下的 \(n - m\) 个元素任意排列,方案数就是 \((n - m)!\)

那么上式可以化简为

\[\begin{aligned} \left|\bigcup_\limits{i = 1}^{n} S_i\right| &= \sum_{m = 1}^{n} \dbinom{n}{m}(-1)^{m - 1} (n - m)! = \sum_{m = 1}^{n}(-1)^{m - 1}\dfrac{n!}{m!} \end{aligned} \]

所以 \(T_n = n!\sum_\limits{m = 0}^{n} \dfrac{(-1)^{m}}{m!}\)

另外有递推式 \(T_n = (n - 1)(T_{n - 1} + T_{n - 2}) = nT_{n - 1} + (-1)^{n}\),第一个式子可以通过组合意义推导:对于 \(T_n\) 考察元素 \(n\) 放在哪个位置。 首先不能是 \(n\),所以设 \(p_a = n\),考虑 \(a\) 这个元素放在哪里:

  1. 放在 \(n\) 这个位置,则除了互换此两处外仍然保持每个数有 \(n - 3\) 种去处(除 \(a, n\) 和自身位置外),故这部分方案数是 \(T_{n - 2}\)
  2. 放在 \(n\) 以外的位置,则对于 \(a\) 这个元素,其有 \(n - 2\) 种去处;剩余元素亦有除自身位置和 \(a\) 以外的 \(n - 2\) 种去处,故这部分方案是 \(T_{n - 1}\)

\(a\)\(n - 1\) 种取值,故 \(T_{n} = (n - 1)(T_{n - 1} + T_{n - 2})\)

另外考虑代入 \(T_n = n! \sum_\limits{i = 0}^{n} \dfrac{(-1)^i}{i!}\),得到

\[\begin{aligned} T_{n} &= (n - 1) \times (n - 1)!\sum_{i = 0}^{n - 1} \dfrac{(-1)^i}{i!} + (n - 1)! \sum_{i = 0}^{n - 2} \dfrac{(-1)^i}{i!} \\ &= (n - 1)! \times \left( (n - 1)\sum_{i = 0}^{n - 1} \dfrac{(-1)^i}{i!} + \sum_{i = 0}^{n - 1} \dfrac{(-1)^i}{i!} - \dfrac{(-1)^{n - 1}}{(n - 1)!} \right) \\ &= n \times (n - 1)! \sum_{i = 0}^{n - 1} \dfrac{(-1)^i}{i!} - (-1)^{n - 1} \\ &= nT_{n - 1} + (-1)^n \end{aligned} \]

上式即第二个递推公式。

例题

P3197

题意:给 \(n\) 个小球染上 \(m\) 种颜色,求至少一对相邻小球颜色相同的方案数,对 \(10^5 + 3\) 取模。\(n \le 10^{12}, m \le 10^8\)

设第 \(i\) 个小球颜色为 \(a_i\),则所求即至少一个位置 \(i\) 满足 \(a_i = a_{i + 1}\) 的方案数。

单步容斥,总方案数为 \(m^n\),而 \(\forall i = 1, 2, \dotsb, n - 1\)\(a_i \ne a_{i + 1}\) 的方案数为 \(m(m - 1)^{n - 1}\)(第一个小球任意涂色,其后每一个都不与上一个同色),两者相减即为答案。

P1450

暴力背包的复杂度是 \(O(nks)\),其中 \(k = 4\) 是硬币种类数。

考虑到这个就是 \(\sum_\limits{i = 1}^{4} c_ix_i = s, x_i \le d_i\) 的非负整数解计数,沿用我们之前的容斥方法,于是只需要求 \(\sum_\limits{i = 1}^{4}c_ix_i = s - \sum_\limits{i = 1}^{k} c_{p_i}(d_{p_i} + 1)\)\(x_i\) 没有上界限制的方案数,这个预处理出背包的答案即可。

P6298

题意:给定长为 \(n\) 的正整数序列 \(\{x_n\}\),满足 \(\forall i \in [1, n], x_i \le m\)。给出 \(k\),对每个 \(t \in [1, m]\),求出 \(\{x_n\}\) 的长度为 \(k\) 的子序列中,满足所有元素的 \(\gcd\) 等于 \(t\) 的数量,对 \(10^9 + 7\) 取模。\(n, m, k \le 10^6\)

我们将问题转化为求出子序列 \(\gcd\)\(t\) 的倍数的方案数。

首先可以对每个 \(t\) 求出序列中能被它整除的数个数 \(cnt_t\),这部分是 \(O(m \ln m)\) 的。

则显然上述方案数为 \(\dbinom{cnt_t}{k}\)

可以得到 \(\dbinom{cnt_t}{k} = \sum_\limits{i = 1}^{\lfloor \dfrac{m}{t} \rfloor} res_{it}\),倒着求解答案即可。复杂度 \(O(m \ln m)\)

FLWRS - Flowers

首先考虑先数出结构数目,即我们不考虑每个位置的数,只考虑它和上一个元素是否合法,最后再把数填进去。设 \(f_{i, j, 0 / 1}\) 表示前 \(i\) 个位置,有 \(j\) 个位置是不合法的,\(i\) 是否合法,容易发现不合法的可以形成连续段(因为每个都和上一个恰好相差 1,而因为是排列,所以连续一段不合法的只能递增或者递减,否则会出现相同元素),则:

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

\(f_{i, j ,0}\) 的转移:上一个位置合法则为 \(f_{i - 1, j, 0}\),否则为 \(f_{i - 1, j, 1}\)

\(f_{i, j, 1}\) 的转移:上一个位置合法,则需要决定这一个位置开始的连续段是递增还是递减,故从 \(-2 f_{i - 1, j - 1, 0}\) 转移;上一个位置不合法,则直接合并进上一段,故为 \(-f_{i - 1, j - 1, 1}\)

最后需要把数填进去,可以发现,每个不合法连续段的值只需要知道这一段之前的那个数即可全部推出,故我们只需知道剩下 \(n - j\) 个合法位置的相对大小,所以填入数的方案数是 \((n - j)!\)。故最后答案即为 \(\displaystyle \sum_{j = 0}^{n - 1} (n - j)!(f_{n, j, 0} + f_{n, j, 1})\)

另外,假设我们换个方向,考虑每个位置和下一个位置是否合法,设 \(f_{i, j, 0 / 1}\) 表示前 \(i\) 个位置,有 \(j\) 个连续段,\(i\) 是否合法,然后将合法的位置看作长度为 \(1\) 的连续段,则有

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

这里需要注意:\(f_{i, j, 0}\)\(f_{i - 1, j, 1}\) 转移,是因为我们考虑的是和下一个位置的合法性,如果 \(i - 1\)\(i\) 之间不合法,那么连续段的终点会是 \(i\),所以不算做新开一段。

同理地,容易发现每个连续段只需要知道开头的那个数是多少,所以填入数的方案数为 \(j!\),于是答案为 \(\displaystyle \sum_{j = 1}^{n} j!f_{n, j, 0}\)(注意 \(n\) 这个位置是一定合法的,因为没有下一个数了)。

另外另外,本题还有无容斥的做法:

题目要求排列中任意相邻两项 \((a_i, a_{i + 1})\) 满足 \(|a_i - a_{i + 1}| \ne 1\),那么定义 \((i, i + 1)\) 位置形成一个不合法对,当且仅当 \((a_{i}, a_{i + 1})\) 满足 \(|a_i - a_{i + 1}| = 1\),于是题目要求的即不合法对数量为 \(0\) 的排列数。考虑插入法构造排列,即从小到大枚举 \(i\),枚举到 \(i\) 时已经有一个 \(1 \sim i - 1\) 的排列,考虑把 \(i\) 插入到当前排列的哪个位置。设 \(f_{i, j, 0 / 1}\) 表示当前枚举到 \(i\),有 \(j\) 个不合法对,\(i\) 是否形成至少一个不合法对的答案,则转移考虑分讨。若 \(i\) 插入后导致 \(i\) 形成了至少一个不合法对,则容易发现,\(1 \sim i\) 的排列中 \(i\) 至多只在一个不合法对中(因为 \(i + 1\) 还没有插入),所以只需要考虑以下情况:

  • \(i\) 插入在了一个合法对中间,此时

    • \(i - 1\) 位于这个合法对中,则会形成一个新的不合法对,此时:
      • \(i - 1\) 没有形成不合法对,则两边都构成上述合法对,故 \(2f_{i - 1, j - 1, 0} \to f_{i, j, 1}\)
      • \(i - 1\) 形成了不合法对,则只有形成合法对的那一边满足上述条件,故 \(f_{i - 1, j - 1, 1} \to f_{i, j, 1}\)
    • \(i - 1\) 不位于这个合法对中,则不会形成新的不合法对,此时:
      • \(i - 1\) 没有形成不合法对,则上述合法对有 \(i - j - 2\) 个(未插入前有 \(i - j\) 个合法对,因为 \((0, 1)\) 也算一个),故 \((i - j - 2) f_{i - 1, j, 0} \to f_{i, j, 0}\)
      • \(i - 1\) 形成了不合法对,则上述合法对有 \(i - j - 1\) 个,故 \((i - j - 1)f_{i - 1, j, 1} \to f_{i, j, 0}\)
  • \(i\) 插入在了一个不合法对中间,则显然这个不合法对会被破坏,因为它们不再相邻了。此时:

    • \(i - 1\) 位于这个不合法对中,则破坏之后 \(i\)\(i - 1\) 会生成新的不合法对,容易发现这样的位置只有一个,故 \(f_{i - 1, j, 1} \to f_{i, j, 1}\)

    • \(i - 1\) 不位于这个不合法对中,则不会形成新的不合法对,此时:

      • \(i - 1\) 位于某个不合法对中,则需要去掉刚才考虑的那个位置,剩下 \(j\) 种位置,故 \(j \times f_{i - 1, j + 1, 0} \to f_{i, j, 0}\)

      • \(i - 1\) 不位于任何不合法对中,则不需要去掉第一种情况的位置,故 \((j + 1) \times f_{i - 1, j + 1, 1} \to f_{i, j, 0}\)

初始值为 \(f_{1, 0, 0} = 1\),最后答案即为 \(f_{n, 0, 0}\)

ABC241Ex

设拿走了 \(x_i\) 张第 \(i\) 堆的卡牌,则数量上的限制形如 \(\sum_\limits{i = 1}^{n}x_i = m, \forall i \in [1, n], x_i \le b_i\),于是仍然直接套用不定方程非负整数解计数的容斥方法,我们钦定 \(k\) 堆卡牌拿了超过 \(b_i\) 张,剩下的贡献即每堆选任意多个,考虑这个怎么做:设 \(f_{i, j}\) 表示拿了 \(i\) 张牌,考虑的是前 \(j\) 堆且钦定第 \(j\) 堆必选的贡献,则每次转移是 \(f_{i, j} = \sum_{k = 0}^{j} f_{i - 1, k} \times a_j\),这个是可以写成矩阵转移的,于是矩阵快速幂即可。复杂度大概是 \(O(n^22^n \log m)\)

ARC101E

计数时容斥系数可以与方案数同时计算。

题意:给出大小为 \(n \le 5000\) 的树,保证 \(n\) 为偶数,求出将树上的点两两配对,使所有配对路径覆盖整个边集的方案数,对 \(10^9 + 7\) 取模。

正着做可以设 \(f_{i, j}\) 表示 \(i\) 子树里还有 \(j\) 个点能向上匹配的方案数,但是转移需要枚举 \(k\) 表示在当前儿子子树中和已经合并过的子树中选 \(k\) 对点,似乎不太能优化。直接做复杂度是 \(O(n^3)\) 的。

考虑容斥,钦定树上有 \(k\) 条边没被覆盖(即,考虑树上至少有 \(k\) 条边没被覆盖的情况),那么对答案的贡献即 \((-1)^k\) 乘上得到的 \(k + 1\) 个连通块内部点随便两两配对的方案数;容易发现一个大小为 \(m\) 的连通块随便两两配对的方案数即 \([2 \mid m](m - 1)!!\)(对当前剩下的每个点考虑,每次配对减少两个点)。

于是重新设 \(f_{i, j}\) 表示 \(i\) 子树内,\(i\) 所在的连通块大小为 \(j\) 的方案数。转移考虑钦定 \(i \to fa_i\) 这条边是否断开,若断开则贡献乘 \(-1\) 即可。

转移大概是这样的(设 \(F(x)\) 表示大小为 \(x\) 的连通块内两两配对的方案数)

\[\begin{aligned} f_{u, i} + f_{v, j} &\to f_{u, i + j} \\ f_{u, i} - F(j) \times f_{v, j} &\to f_{u, i} \end{aligned} \]

这样总复杂度降为 \(O(n^2)\),可以通过。

Bonus: 这场的 D E F 题都挺有意思的,值得一做。

CF1043F

题意:给定序列 \(\{a_n\}\),定义一个子序列合法,当且仅当这个子序列的 \(\gcd\)\(1\)。求出合法子序列的最短长度(若都不合法,输出 \(-1\))。\(n, a_i \le 3 \times 10^5\)

首先判断无解只需要求出所有数的 \(\gcd\) 即可。

考虑答案的上界:假设当前选出的子序列 \(\gcd = x\),如果选入一个数使得 \(\gcd\) 变化,则 \(\gcd\) 至少减半。由于我们保证能缩减到 \(1\),所以答案的一个上界是 \(O(\log V) = 18\)。实际上我们可以进一步考虑:由于保证有解,所以每个质因数一定不能出现在所有数中,而我们一定可以通过选入某个不包含该质因数的数来去除该质因数的影响,所以每个质因数最多花费一次的代价,那么最劣的情况是每个质因数的次幂只有一次。注意到 \(V = 3 \times 10^5\) 内的每个数最多有 \(6\) 个质因数,并且其中最大的一个为 \(3 \times 5 \times 7 \times 11 \times 13 \times 17\),这也就表明我们可以构造出的最大集合大小为 \(7\)(因为可以从 \(2 \times 3 \times 5 \times 7 \times 11 \times 13\) 开始选)。所以答案上界为 \(7\)

我们现在需要判断大小为 \(x\) 的所有子集里是否存在 \(\gcd\)\(1\) 的集合。这是不好做的,我们考虑把判定性问题变为计数,则现在需要求出选出 \(x\) 个数,\(\gcd = i\) 的方案数,设为 \(f_{x, i}\)。这就变成了 P6298,直接套用做法:

考虑对答案后缀和,则我们需要对每个 \(i\) 求出选出 \(x\) 个数,使得 \(i\) 是这些数的公约数的方案数,设为 \(g_{x, i}\)。这是很好做的,只需要数出 \(cnt_i\) 表示序列中有多少个 \(i\) 的倍数,则 \(g_{x, i} = \dbinom{cnt_i}{x}\)。容易得出 \(\displaystyle f_{x, i} = g_{x, i} - \sum_{k = 2} f_{x, ki}\)。注意这里需要添加一个取模,理论上需要使用多个模数来保证正确性,但本题随便取一个大质数即可通过。

实际上,由于 \(\displaystyle g_{x, i} = \sum_{k = 1} f_{x, ki} = \sum_{i \mid d} f_{x, d}\),即 \(g_x\)\(f_{x}\) 的狄利克雷后缀和,所以对 \(g_x\) 做一个狄利克雷后缀差分来求解 \(f_x\) 可以获得更优的复杂度。建议观看 算法学习笔记(28):狄利克雷前/后缀和、差分 - 知乎 来学习相关知识。

posted @ 2026-01-10 22:51  Neutral1sed  阅读(84)  评论(0)    收藏  举报