容斥原理
引入
入门例题
假设班里有 \(10\) 个学生喜欢数学,\(15\) 个学生喜欢语文,\(21\) 个学生喜欢编程,班里至少喜欢一门学科的有多少个学生呢?
是 \(10+15+21=46\) 个吗?不是的,因为有些学生可能同时喜欢数学和语文,或者语文和编程,甚至还有可能三者都喜欢。
为了叙述方便,我们把喜欢语文、数学、编程的学生集合分别用 \(A,B,C\) 表示,则学生总数等于 \(|A\cup B\cup C|\)。刚才已经讲过,如果把这三个集合的元素个数 \(|A|,|B|,|C|\) 直接加起来,会有一些元素重复统计了,因此需要扣掉 \(|A\cap B|,|B\cap C|,|C\cap A|\),但这样一来,又有一小部分多扣了,需要加回来,即 \(|A\cap B\cap C|\)。即
把上述问题推广到一般情况,就是我们熟知的容斥原理。
定义
设 U 中元素有 n 种不同的属性,而第 i 种属性称为 \(P_i\),拥有属性 \(P_i\) 的元素构成集合 \(S_i\),那么
即
证明
对于每个元素使用二项式定理计算其出现的次数。对于元素 x,假设它出现在 \(T_1,T_2,\cdots,T_m\) 的集合中,那么它的出现次数为
于是每个元素出现的次数为 1,那么合并起来就是并集。证毕。
补集
对于全集 U 下的 集合的并 可以使用容斥原理计算,而集合的交则用全集减去 补集的并集 求得:
右边使用容斥即可。
可能接触过容斥的读者都清楚上述内容,而更关心的是容斥的应用。
那么接下来我们给出 3 个层次不同的例题来为大家展示容斥原理的应用。
不定方程非负整数解计数
不定方程非负整数解计数
给出不定方程 \(\sum_{i=1}^nx_i=m\) 和 \(n\) 个限制条件 \(x_i\leq b_i\),其中 \(m,b_i \in \mathbb{N}\). 求方程的非负整数解的个数。
没有限制时
如果没有 \(x_i\leq b_i\) 的限制,那么不定方程 \(\sum_{i=1}^nx_i=m\) 的非负整数解的数目为 \(\dbinom{m+n-1}{n-1}\).
略证:插板法。
相当于你有 \(m\) 个球要分给 \(n\) 个盒子,允许某个盒子是空的。这个问题不能直接用组合数解决。
于是我们再加入 \(n-1\) 个球,于是问题就变成了在一个长度为 \(m+n-1\) 的球序列中选择 \(n-1\) 个球,然后这个 \(n-1\) 个球把这个序列隔成了 \(n\) 份,恰好可以一一对应放到 \(n\) 个盒子中。那么在 \(m+n-1\) 个球中选择 \(n-1\) 个球的方案数就是 \(\dbinom{m+n-1}{n-1}\)。
容斥模型
接着我们尝试抽象出容斥原理的模型:
- 全集 U:不定方程 \(\sum_{i=1}^nx_i=m\) 的非负整数解
- 元素:变量 \(x_i\).
- 属性:\(x_i\) 的属性即 \(x_i\) 满足的条件,即 \(x_i\leq b_i\) 的条件
目标:所有变量满足对应属性时集合的大小,即 \(|\bigcap_{i=1}^nS_i|\).
这个东西可以用 \(\left|\bigcap_{i=1}^{n}S_i\right|=|U|-\left|\bigcup_{i=1}^n\overline{S_i}\right|\) 求解。\(|U|\) 可以用组合数计算,后半部分自然使用容斥原理展开。
那么问题变成,对于一些 \(\overline{S_{a_i}}\) 的交集求大小。考虑 \(\overline{S_{a_i} }\) 的含义,表示 \(x_{a_i}\geq b_{a_i}+1\) 的解的数目。而交集表示同时满足这些条件。因此这个交集对应的不定方程中,有些变量有 下界限制,而有些则没有限制。
能否消除这些下界限制呢?既然要求的是非负整数解,而有些变量的下界又大于 \(0\),那么我们直接 把这个下界减掉,就可以使得这些变量的下界变成 \(0\),即没有下界啦。因此对于
的不定方程形式为
于是这个也可以组合数计算啦。这个长度为 \(k\) 的 \(a\) 数组相当于在枚举子集。
HAOI2008 硬币购物
HAOI2008 硬币购物
4 种面值的硬币,第 i 种的面值是 \(C_i\)。\(n\) 次询问,每次询问给出每种硬币的数量 \(D_i\) 和一个价格 \(S\),问付款方式。
\(n\leq 10^3,S\leq 10^5\).
如果用背包做的话复杂度是 \(O(4nS)\),无法承受。这道题最明显的特点就是硬币一共只有四种。抽象模型,其实就是让我们求方程 \(\sum_{i=1}^4C_ix_i=S,x_i\leq D_i\) 的非负整数解的个数。
采用同样的容斥方式,\(x_i\) 的属性为 \(x_i\leq D_i\). 套用容斥原理的公式,最后我们要求解
也就是无限背包问题。这个问题可以预处理,算上询问,总复杂度 \(O(4S+2^4n)\)。
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
完全图子图染色问题
前面的三道题都是容斥原理的正向运用,这道题则需要用到容斥原理逆向分析。
完全图子图染色问题
A 和 B 喜欢对图(不一定连通)进行染色,而他们的规则是,相邻的结点必须染同一种颜色。今天 A 和 B 玩游戏,对于 \(n\) 阶 完全图 \(G=(V,E)\)。他们定义一个估价函数 \(F(S)\),其中 S 是边集,\(S\subseteq E\).\(F(S)\) 的值是对图 \(G'=(V,S)\) 用 \(m\) 种颜色染色的总方案数。他们的另一个规则是,如果 \(|S|\) 是奇数,那么 A 的得分增加 \(F(S)\),否则 B 的得分增加 \(F(S)\). 问 A 和 B 的得分差值。
数学形式
一看这道题的算法趋向并不明显,因此对于棘手的题目首先抽象出数学形式。得分差即为奇偶对称差,可以用 -1 的幂次来作为系数。我们求的是
容斥模型
相邻结点染同一种颜色,我们把它当作属性。在这里我们先不遵守染色的规则,假定我们用 m 种颜色直接对图染色。对于图 \(G'=(V,S)\),我们把它当作 元素。属性 \(x_i=x_j\) 的含义是结点 i,j 染同色(注意,并未要求 i,j 之间有连边)。
而属性 \(x_i=x_j\) 对应的 集合 定义为 \(Q_{i,j}\),其含义是所有满足该属性的图 \(G'\) 的染色方案,集合的大小就是满足该属性的染色方案数,集合内的元素相当于所有满足该属性的图 \(G'\) 的染色图。
回到题目,「相邻的结点必须染同一种颜色」,可以理解为若干个 \(Q\) 集合的交集。因此可以写出
上述式子右边的含义就是说对于 S 内的每一条边 \((i,j)\) 都满足 \(x_i=x_j\) 的染色方案数,也就是 \(F(S)\).
是不是很有容斥的味道了?由于容斥原理本身没有二元组的形式,因此我们把 所有 的边 \((i,j)\) 映射到 \(T=\frac{n(n+1)}{2}\) 个整数上,假设将 \((i,j)\) 映射为 \(k,1\leq k\leq T\),同时 \(Q_{i,j}\) 映射为 \(Q_k\). 那么属性 \(x_i=x_j\) 则定义为 \(P_k\).
同时 S 可以表示为若干个 k 组成的集合,即 \(S\iff K=\{k_1,k_2,\cdots,k_m\}\).(也就是说我们在边集与数集间建立了等价关系)。
而 E 对应集合 \(M=\left\{1,2,\cdots,\frac{n(n+1)}{2}\right\}\). 于是乎
逆向分析
那么要求的式子展开
于是就出现了容斥原理的展开形式,因此对这个式子逆向推导
再考虑等式右边的含义,只要满足 \(1\sim T\) 任一条件即可,也就是存在两个点同色(不一定相邻)的染色方案数!而我们知道染色方案的全集是 \(U\),显然 \(|U|=m^n\). 而转化为补集,就是求两两异色的染色方案数,即 \(A_m^n=\frac{m!}{(m-n)!}\). 因此
解决这道题,我们首先抽象出题目数学形式,然后从题目中信息量最大的条件,\(F(S)\) 函数的定义入手,将其转化为集合的交并补。然后将式子转化为容斥原理的形式,并 逆向推导 出最终的结果。这道题体现的正是容斥原理的逆用。
数论中的容斥
使用容斥原理能够巧妙地求解一些数论问题。
容斥原理求最大公约数为 k 的数对个数
考虑下面的问题:
求最大公约数为 \(k\) 的数对个数
设 \(1 \le x, y \le N\),\(f(k)\) 表示最大公约数为 \(k\) 的有序数对 \((x, y)\) 的个数,求 \(f(1)\) 到 \(f(N)\) 的值。
这道题固然可以用欧拉函数或莫比乌斯反演的方法来做,但是都不如用容斥原理来的简单。
由容斥原理可以得知,先找到所有以 \(k\) 为 公约数 的数对,再从中剔除所有以 \(k\) 的倍数为 公约数 的数对,余下的数对就是以 \(k\) 为 最大公约数 的数对。即 \(f(k)=\) 以 \(k\) 为 公约数 的数对个数 \(-\) 以 \(k\) 的倍数为 公约数 的数对个数。
进一步可发现,以 \(k\) 的倍数为 公约数 的数对个数等于所有以 \(k\) 的倍数为 最大公约数 的数对个数之和。于是,可以写出如下表达式:
由于当 \(k>N/2\) 时,我们可以直接算出 \(f(k)= \lfloor (N/k) \rfloor ^2\),因此我们可以倒过来,从 \(f(N)\) 算到 \(f(1)\) 就可以了。于是,我们使用容斥原理完成了本题。
1 2 3 4 |
|
上述方法的时间复杂度为 \(O( \sum_{i=1}^{N} N/i)=O(N \sum_{i=1}^{N} 1/i)=O(N \log N)\)。
附赠三倍经验供大家练手。
容斥原理推导欧拉函数
考虑下面的问题:
欧拉函数公式
求欧拉函数 \(\varphi(n)\)。其中 \(\varphi(n)=|\{1\leq x\leq n|\gcd(x,n)=1\}|\)。
直接计算是 \(O(n\log n)\) 的,用线性筛是 \(O(n)\) 的,杜教筛是 \(O(n^{\frac{2}{3}})\) 的(话说一道数论入门题用容斥做为什么还要扯到杜教筛上),接下来考虑用容斥推出欧拉函数的公式
判断两个数是否互质,首先分解质因数
那么就要求对于任意 \(p_i\),\(x\) 都不是 \(p_i\) 的倍数,即 \(p_i\nmid x\). 把它当作属性,对应的集合为 \(S_i\),因此有
全集大小 \(|U|=n\),而 \(\overline{S_i}\) 表示的是 \(p_i\mid x\) 构成的集合,显然 \(|\overline{S_i}|=\frac{n}{p_i}\),并由此推出
$$ \left|\bigcap_{a_i
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:OI-wiki
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用