第 12 章里,我们用加法原理、乘法原理、排列、组合和二项式系数处理“没有重叠”或“重叠已经被控制好”的计数问题。本章把注意力放到两类更容易出错的情形:有些对象会被重复计数,有些对象虽然无法直接指出是谁,却必然会重复落入同一类。
容斥原理处理“多算了多少”的问题。鸽巢原理处理“平均分也放不下”的问题。组合论证和双计数则把证明改写成计数:只要两种方法数的是同一批对象,它们的结果就必须相等。
本章的共同问题不是“公式是什么”,而是“我们到底在数什么对象”。如果对象说不清,容斥会减错,鸽巢会选错盒子,双计数也会变成形式相似但对象不同的等式。
在计数问题中,加法原理常被写成“互不重叠时可以相加”。这句话里的“互不重叠”很关键。若两个条件可能同时满足,直接相加就会把重叠对象数两次。
例如,某班有学生参加数学社,也有学生参加编程社。若我们把“参加数学社的人数”和“参加编程社的人数”直接相加,那么同时参加两个社团的学生会在两个名单里各出现一次。要得到至少参加一个社团的人数,就必须把这部分重复减掉一次。

这里有一个很实用的检查动作:不要先盯着公式,先盯着一个具体对象。它满足几个条件,就会在“先相加”的步骤里被数几次;目标计数想让它出现几次,就要修正到几次。
设 和 是有限集合。并集 中的对象是“属于 或属于 ,或同时属于两者”的对象。先计算 时,交集 中的每个元素被数了两次,但在并集中只应该出现一次,所以要减去一次交集。

例题:某班 48 人中,30 人选修了离散数学,22 人选修了程序设计,12 人同时选修了这两门课。至少选修其中一门课的学生有多少人?
先确定对象:要数的是“至少选修一门课的学生”,也就是两个选课集合的并集。
直接相加得到 ,但同时选修两门课的 12 人被数了两次。
下面的交互可以调节 、 和 。观察交集变大时,并集为什么不一定变大。
“或”在数学里通常包含“同时”。“属于 或属于 ”不是只属于其中一个,而是至少属于一个。若题目要排除同时满足的对象,会说“恰好一个”“只参加一个”或“二者之一但不同时”。
三集合时,重复计数更容易藏起来。先把 相加,落在两两交集里的对象会被多算;于是减去 。但落在三重交集 的对象,原来被加了三次,后来又在三个两两交集中被减了三次,结果变成零次。它在并集中应该出现一次,所以最后要加回三重交集。

例题:一次调查中,38 人喜欢数学题,32 人喜欢程序题,25 人喜欢逻辑题。喜欢数学题和程序题的有 15 人,喜欢数学题和逻辑题的有 12 人,喜欢程序题和逻辑题的有 10 人,三类都喜欢的有 5 人。至少喜欢其中一类题的人有多少?
这里要数的是三个集合的并集。题目给出的两两交集人数包含三类都喜欢的人,这是容斥公式所需要的交集,不要把三重交集先排除掉。
先加三个单集合:
因此至少喜欢一类题的人有 63 人。
容斥经常和“至少”“至多”“恰好”一起出现。它们不是同一种问法。
“至少一个”常常对应并集。比如至少参加一个活动,就是属于活动集合的并集。
“一个也不”常常用补集处理。若总体有 个对象,而至少满足一个条件的有 个,那么一个条件也不满足的有 个。
“恰好一个”不能直接用并集。它要排除同时满足多个条件的对象。例如对两个集合来说,恰好属于一个集合的人数是
常见错误是看到“至少一个”就直接把各条件人数相加。只要条件之间可能重叠,直接相加就不是并集人数,而是“带重复的出现次数”。
练习:某校 100 名学生中,60 人参加过志愿服务,45 人参加过学术讲座,25 人两者都参加过。至少参加过一种活动的有多少人?两种活动都没参加过的有多少人?恰好参加一种活动的有多少人?
至少参加一种活动的人数是 。两种都没参加过的人数是 。恰好参加一种活动的人数是 ,也可以用 。
容斥处理的是“重复计数已经发生,怎样修正”。鸽巢原理处理的是另一种重复:当物品比盒子多时,即使不知道具体分布,也能断定某个盒子里必然放了不止一个物品。
最基本的鸽巢原理是:若把 个物品放入 个盒子,那么至少有一个盒子中有不少于 个物品。

这个结论的证明很短。若每个盒子最多只有 1 个物品,那么 个盒子最多只能容纳 个物品。这与已经放入 个物品矛盾。所以至少有一个盒子中有 2 个或更多物品。
用鸽巢原理时,真正困难的地方通常不是证明,而是建模。需要明确两件事:物品是什么,盒子是什么。物品是被分配的对象;盒子是按某个特征划分出的类别。
例题:任取 13 个人,必有两个人出生月份相同。
把 13 个人看成物品。每个人都有一个出生月份。
把 12 个月份看成盒子。一个人出生在哪个月,就被放入哪个月份盒子。
若每个月最多只有 1 人,那么 12 个月最多容纳 12 人。
现在有 13 人,所以至少有一个月份盒子中不少于 2 人。也就是至少有两个人出生月份相同。

若把 个物品放入 个盒子,那么至少有一个盒子中有不少于
个物品。这里的天花板符号表示向上取整。
理由仍然来自反证。若每个盒子最多只有 个物品,那么总容量最多是
这个数小于 ,无法放下全部物品。因此必有某个盒子达到至少 个。
下面的模拟器可以调节物品数和盒子数。注意观察:结论保证的是“至少有一个盒子达到下界”,并不保证每个盒子都接近平均。
例题:班里有 41 名学生。若按星期几出生来分组,证明至少有 6 名学生出生在同一个星期几。
物品是 41 名学生,盒子是 7 个星期类别。
按广义鸽巢原理,至少有一个盒子里的人数不少于
鸽巢原理给的是存在性结论。它能证明“必有某个盒子很多”,但通常不能告诉你是哪一个盒子。若题目要求指出具体对象,还需要额外信息。
练习:从 10 双不同颜色的袜子中任意取袜子。最少取多少只,才能保证至少有两只是同一双的左右袜?
最少取 11 只。把 10 双袜子看成 10 个盒子,每取一只袜子就落入对应那一双的盒子。若只取 10 只,可能每双各取一只,还不能保证成双。取 11 只时,10 个盒子放入 11 个物品,至少有一个盒子有 2 只袜子,也就是取到了同一双的左右袜。
组合证明的目标不是先做代数变形,而是给等式两边找到同一个计数对象。若左边和右边都在数同一批东西,只是分组方式不同,那么它们相等。
一个经典例子是
代数上可以用阶乘公式化简。组合上更直接:从 个对象中选出 个,与从 个对象中留下 个没有被选中的对象,是同一个选择的两种描述。每选出一个 人小组,就唯一决定一个 人的未选集合;反过来也一样。
组合证明通常有三步。
先定义一个清楚的对象集合,例如“从 人中选出一个 人小组”或“带组长的 人小组”。
用第一种方法计数,得到等式左边。这里要说明每个选择为什么被数一次,不能只写公式。
组合证明的好处是保留了式子的意义。等式不再只是符号相等,而是在说“同一批对象可以被两种方式组织”。
例题:用组合证明说明
其中 。
证明对象设为“从 个人中选出一个 人小组,并在小组中指定一名组长”。
先按小组来数。先从 人中选出 人小组,有 种;每个小组中再选一名组长,有 种。因此共有 种。
下面的交互把这两个路径放在同一屏中。改变 和 ,观察两边为什么同步变化。
练习:给出一个组合证明说明
数同一批对象:从 个人中选出一对人。按组合数定义,有 种。若先选第一个人再选第二个人,有 种有顺序选择;但每一对人被按两个顺序数了两次,所以无顺序的一对共有 种。两种方法数的是同一批二人组,因此 。
双计数是组合证明中最常见的一种形式:把同一批对象按两种维度求和。它经常用来证明恒等式,也能解释图论里的握手定理。
设一个有限无向图有顶点集合 和边集合 。把所有顶点的度数相加,相当于数“边端点关联”这批对象:
从顶点角度数,对每个顶点 ,与它关联的边有 条,所以总数是
从边角度数,每条边有两个端点,所以总数是
两种方法数的是同一批“顶点与关联边”的配对,因此

双计数最容易出错的地方,是两边实际上数了不同对象。例如,一边数“有组长的小组”,另一边却数“没有组长的小组”;或者一边允许重复,另一边不允许重复。这时即使式子看起来相近,也不能构成证明。
写双计数证明时,可以用下面的问题自查:
例题:证明在任意有限无向图中,奇度数顶点的个数是偶数。
由握手定理,所有顶点度数之和是 ,所以它是偶数。
偶度数顶点的度数相加仍然是偶数。
因此奇度数顶点的度数总和也必须是偶数。
这个结论很小,但它展示了本章三种思想的连接:先明确计数对象,再用双计数得到总量约束,最后从奇偶性推出必然结构。
很多题目不会直接告诉你“请使用容斥”或“请使用鸽巢”。选择工具时,先看题目中的信号。
若问题问“至少满足一个条件”“没有满足任何条件”“重复名单如何合并”,通常考虑容斥或补集。
若问题问“证明必有两个对象共享某个特征”“最少多少个才能保证重复”,通常考虑鸽巢原理。
若问题问“证明一个组合恒等式”“同一对象能不能从两条路径计数”,通常考虑组合证明或双计数。
证明:任取 6 个整数,必有两个整数的差能被 5 整除。
两个整数的差能被 5 整除,等价于它们除以 5 的余数相同。
把 6 个整数看成物品,把除以 5 的余数 看成 5 个盒子。
长度为 4 的数字串允许首位为 0。问:至少含有一个 0 或至少含有一个 1 的数字串有多少个?
设 为含有至少一个 0 的数字串集合, 为含有至少一个 1 的数字串集合。题目要数 。
这里最后的结果也有一个更短解释:至少含 0 或至少含 1,等价于“不全由 2 到 9 这 8 个数字组成”,所以是 。容斥推导和补集推导得到同一个结果,说明它们确实在数同一批对象。
当条件很多时,容斥不一定是最短路线。若题目问“至少满足某些条件”,先看补集是否更简单;若补集只需要排除少数情况,通常比逐层容斥更干净。
容斥原理的核心是修正重复。两集合时,先加两个集合,再减交集;三集合时,先加单集合,减两两交,再加三重交。
鸽巢原理的核心是容量不足。只要物品数超过盒子按某个上限能容纳的总数,就能推出某个盒子超过这个上限。广义形式给出至少 的下界。
组合证明和双计数的核心是对象一致。先说清同一批对象,再分别从两条路径计数,得到等式或结构约束。
练习 1:某班 70 人中,42 人会 Python,35 人会 Java,18 人两种都会。至少会一种语言的有多少人?两种都不会的有多少人?
至少会一种语言的人数是 。两种都不会的人数是 。
练习 2:证明任取 9 个整数,必有两个整数除以 8 的余数相同。
把 9 个整数看成物品,把除以 8 的余数 看成 8 个盒子。9 个物品放入 8 个盒子,按鸽巢原理,至少有一个盒子中有两个整数,所以这两个整数除以 8 的余数相同。
练习 3:用组合证明说明
其中 。
数同一批对象:从 个对象中先选出一个 个对象的集合,并在其中标出一个 个对象的子集合。左边先选 个对象,再从这 个对象中选出被标出的 个对象,所以是 。右边先选出被标出的 个对象,再从剩下的 个对象中选出 个普通对象,所以是 。两种方法数的是同一批带标出子集的 元集合,因此相等。
按两集合容斥减去这 12 次重复,得到
因此至少选修一门课的学生有 40 人;没有选修这两门课中任何一门的学生有 人。
减去三类两两重叠:
三重交集里的 5 人被加三次、减三次,现在还没有被计入,所以加回一次:
因此至少有 6 名学生出生在同一个星期几。
用第二种方法计数,得到等式右边。最后说明两种方法数的是同一批对象,所以结果相等。
再按组长来数。先从 人中选组长,有 种;组长确定后,还要从剩下的 人中选出 名普通成员,有 种。因此共有 种。
两种方法数的都是“带组长的 人小组”,每个对象都被数一次,所以两边相等。
奇数个奇数相加是奇数,偶数个奇数相加才是偶数。所以奇度数顶点的个数只能是偶数。
6 个物品放入 5 个盒子,按鸽巢原理,至少有一个盒子中有两个整数。
这两个整数余数相同,所以它们的差能被 5 整除。
用补集计算 。全部长度为 4 的数字串有 个,不含 0 的有 个,所以
同理,。同时含有至少一个 0 和至少一个 1 的数量可用二次补集计算:
代入两集合容斥: