小区楼下的快递驿站里,王师傅有个朴素的烦恼:货架只有 5 个格子,快递员却总在高峰期一口气送来 6 个包裹。怎么办?硬塞呗——不管怎么摆,总有一个格子得放下两件包裹。这个连小学生都能听懂的事实,就是组合数学里赫赫有名的鸽巢原理。 别看它简单得像一句废话,鸽巢原理是数学界最会“四两拨千斤”的工具。数学家拿它证明:任意 5 个整数中必有两个数之差能被 4 整除,任意 6 个人中必有 3 人两两认识或两两不认识;程序员靠它理解:哈希表塞得太满就必然冲突;算法工程师拿它证明:某些问题再快也有理论下限。一个生活观察,贯穿了数论、图论、算法分析和软件工程的半壁江山。 接下来,我们就跟着王师傅的驿站,从“多一件包裹”出发,看这条原理如何一步步长出广义形式,潜入数论的余数世界,爬上图论的社交网络,最后变成你代码里的哈希函数和面试题里的得分点。
对 AI 从业者而言,鸽巢原理是复杂度分析与系统边界设计的底层直觉:它教你一眼看穿“什么时候冲突无法避免、什么时候下界不可突破”,是面试算法题与系统设计题的隐形杀手锏。
可视化演示
鸽巢原理指出将多于n个物品放入n个容器必有一容器含至少两物品,是组合数学的基本工具。本文详解原理的基本形式与广... 切换模式查看不同维度。
本节配有交互动效(进入视口后自动加载,约 3KB)。
鸽巢原理的基:核心原理 动态展示关键流程与数据流动 交互控件调节参数实时渲染 f(x) = transform(x) 核心概念的可视化呈现
基本原理
一天傍晚,快递员又给王师傅送来 6 件包裹,而货架只有 5 个格子。王师傅叹了口气:“又要硬塞了。”他试着把包裹平均摊开——第一格一件、第二格一件……放到第五格时手里还剩一件,第六件无论塞进哪一格,那一格都将有两件包裹。他甚至不需要尝试,就知道这个结果是躲不掉的。这个“躲不掉”的直觉,正是鸽巢原理的核心。
把 6 件包裹抽象成“物品”,5 个货架格子抽象成“盒子”,就得到鸽巢原理的基本形式:将 n+1 件物品放入 n 个盒子,必定存在一个盒子至少含有 2 件物品。注意两个关键词:第一,结论是确定性的,不因分配策略而改变,哪怕你故意把六件全塞进一个格子,结论依然成立;第二,它是存在性命题,只保证“有”,不保证“哪个”。
证明只需要反证法。假设每个盒子至多装 1 件物品,那么 n 个盒子总容量最多是 n 件。可我们明明有 n+1 件物品要放,数量上就矛盾了。所以假设不成立,必有一盒至少 2 件。整个论证不到三行,却为后面所有应用提供了地基。
1. 总数定格:n+1 件物品全部参与分配,一件都不能少
2. 极限假设:假设每盒至多 1 件,盒子总容量锁死为 n
3. 矛盾爆发:n+1 件物品塞进最多 n 的容量,n+1>n 直接冲突
4. 结论落地:至少存在一个盒子 i 满足 |B_i| ≥ 2
王师傅拍拍手上的灰:“所以啊,不是我会魔法,是数学把话说死了。”鸽巢原理的第一课,就是学会接受这种“必然”——当数量越过临界点,你再怎么安排,命运都写好了答案。而接下来的每一节,都是在“多一件”这个临界点上做文章。
广义原理
双十一那天,快递员送来不止 6 件,而是 m 件。王师傅的货架还是那 n 个格子。平均每个格子会摊到 m/n 件,但真实的分配往往不均匀——有的格子空着,有的格子堆成小山。王师傅想知道:最少有多少件包裹一定堆在同一个小格子里?答案就是广义鸽巢原理。
广义鸽巢原理说:若将 m 件物品放入 n 个盒子,则至少有一个盒子含有不少于 ⌈m/n⌉ 件物品,其中 ⌈x⌉ 表示向上取整,即不小于 x 的最小整数。举例来说,100 件物品放进 30 个盒子,平均每盒 3.33 件,那么至少有一盒装了不少于 4 件——因为若每盒至多 3 件,总共最多 90 件,根本装不下 100 件。
证明仍然沿用反证法:设 q=⌈m/n⌉,如果每个盒子都至多 q−1 件,那么总容量至多 n(q−1)。而由 q 的定义可知 q−1 < m/n,所以 n(q−1) < m,与 m 件物品的事实矛盾。这个形式把“多 1 件”推广到“多任意件”,是解决最坏情况分析的核心工具。
1. 算平均值:m/n 是每个盒子承载的平均物品数,它可能不是整数
2. 向上取整:⌈m/n⌉ 是堵住“平均线”的最小整数,比如 3.33 变 4
3. 反证收网:若每盒至多 ⌈m/n⌉−1 件,总容量仍小于 m,矛盾
王师傅算了一笔账:哪怕包裹再多,只要算出 ⌈m/n⌉,就知道最挤的那个格子至少堆几件。这是管理货架的“最低保证线”——平均之后必有幸运儿,数学帮你提前锁定它的下限。
数论应用
王师傅发现每个包裹上都有订单号。他突发奇想:如果只看订单号除以 n 的余数,把它们分成 n 类——余数相同的算一类。只要有 n+1 个包裹,就必然有两个包裹的余数相同,这两个订单号之差,恰好被 n 整除。他试着验证了一下,居然一次都没落空。
这就是数论中的同余思想。任意 n+1 个整数中,必存在两个数,它们的差能被 n 整除。原因是:一个整数除以 n 的余数只有 0, 1, …, n−1 共 n 种可能。把每个整数按余数放入对应的“余数盒子”,鸽巢原理立刻告诉我们至少有一个盒子装了至少两个数——它们对 n 同余,其差自然是 n 的倍数。
举个例子:任意 5 个整数中,必有一对数之差能被 4 整除。因为除以 4 的余数只有 4 类,5 个数放进 4 个余数盒子,必然撞车。这种“构造余数盒子”的手法,是数论证明的经典起手式,也是密码学中许多结论的根基。
1. 余数分类:每个整数 a 都可以写成 qn+r 的形式,r 只有 n 种取值
2. 鸽巢落子:n+1 个整数按余数放入 n 个类别,必有 a、b 落入同一类
3. 同余求差:同类别两数之差等于商之差乘 n,因此被 n 整除
王师傅把这条规律编进了驿站系统:每当收到 n+1 个订单号,系统就自动预警“有一对订单号之差是 n 的倍数”。他恍然大悟——余数是数字的指纹,而鸽巢原理就是那个让指纹必然重复的魔术师。
图论应用
驿站常有客户来取件。王师傅观察到一件怪事:随便找 6 个彼此都打过照面的客户,其中要么有 3 人两两认识,要么有 3 人两两不认识。他一开始以为是巧合,后来才知道,这是拉姆齐定理的经典情形 R(3,3)=6,背后站着的正是鸽巢原理。
把 6 个人看成完全图 K₆ 的 6 个顶点:两人认识连红边,不认识连蓝边。任取一个顶点 v,它引出 5 条边。这 5 条边只有红蓝两种颜色,由鸽巢原理,至少 3 条同色。不妨设 v 到 A、B、C 都是红边。现在看 A、B、C 之间的 3 条边:只要有一条红边(比如 AB),就与 v 构成红色三角形;如果三条全是蓝边,那么 A、B、C 自身构成蓝色三角形。两种情况都必然出现同色三角形。
这个证明的精妙之处在于:6 这个数字不是拍脑袋定的。5 个人做不到?因为从一个顶点只引出 4 条边,红蓝两色只能保证 2 条同色,推不出三角形。而 6 恰好是“多一件”的临界点,这正是鸽巢原理在起作用。
1. 建图染色:6 个顶点两两连边,红蓝两色分别表示认识与不认识
2. 聚焦单点:从任一顶点 v 出发有 5 条边,按颜色只有两类
3. 鸽巢取三:5 条边放进 2 类,至少 3 条同色,记到 A、B、C 三点
4. 二分支收尾:AB、BC、CA 中若有一红则与 v 成红三角,否则全蓝自成蓝三角
王师傅成了小区里的“社交预言家”。他不懂玄学,只懂鸽巢原理:6 个人组团取件,关系网中必然藏着三人的小圈子——要么亲密,要么陌生,数学把所有的可能性都堵死了,只留下这一条路。
算法下界
如果包裹混在一起,王师傅想知道:把 3 件包裹按订单号排好,最少得比较几次?3 件包裹有 3!=6 种可能的顺序。每次比较两个包裹,最多只能排除一半的可能性。要把 6 种可能收敛到 1 种正确顺序,至少需要 ceil(log₂6)=3 次。这背后的逻辑,又是一次漂亮的鸽巢计数。
基于比较的排序可以建模为决策树:每个内部节点是一次“谁大谁小”的比较,每条从根到叶子的路径对应一种比较序列。n 个互异元素有 n! 种排列,决策树必须至少有 n! 片叶子,否则两种不同排列会走到同一片叶子,算法就无法区分它们。而一棵深度为 d 的二叉树,最多只有 2^d 片叶子。
用鸽巢原理的语言说:把 n! 种“可能的排列结果”当作物品,把 2^d 条“可用的比较路径”当作盒子。如果 d 太小,使得 n! 大于 2^d,那么必定有至少两件“物品”挤进同一个“盒子”——也就是两种排列共用同一条路径,算法必然出错。所以深度必须满足 2^d ≥ n!,即 d ≥ ⌈log₂(n!)⌉。
1. 排列总数:n 个互异元素有 n! 种排列结果,这是需要区分的“物品”
2. 叶子上限:深度 d 的二叉决策树至多容纳 2^d 片叶子,这是可用的“盒子”
3. 鸽巢引爆:若 2^d < n!,物品多于盒子,必有两条不同输入走到同一路径
4. 取对数得下界:两边取以 2 为底的对数并向上取整
王师傅恍然大悟:算法快慢不是靠“手速”,而是被数学画好了下限。鸽巢原理告诉他,有些事再快也有边界——就像货架只有 n 个格子,信息不够时,再多可能性也挤不进同一条路。
经典例题
王师傅统计驿站会员生日,发现一个“巧合”:只要有 367 个会员,就一定有至少两位会员生日相同。一年最多 366 天(含 2 月 29 日),把 366 个日期当盒子,367 个生日当包裹,鸽巢原理一步到位——连统计都不需要。这就是他在小区里最爱炫耀的“生日魔法”。
第二个经典问题藏在订单号里:任意 n 个整数排列成一串,其中必存在一段连续的子序列,其和能被 n 整除。证明用前缀和技巧。设 s₀=0,s₁ 是前 1 个数的和,s₂ 是前 2 个数的和,依此类推,一共得到 n+1 个前缀和。每个前缀和对 n 取模,余数只有 0 到 n−1 共 n 种可能。由鸽巢原理,n+1 个余数中必有两个相同,设它们对应的前缀和为 sᵢ 和 sⱼ(i<j),则 sⱼ−sᵢ 就是第 i+1 到第 j 个数的连续和,它被 n 整除。
整除证明的套路在这里一目了然:前缀和把“一段连续和”翻译成“两个前缀和的差”,鸽巢原理保证差被 n 整除。这个手法在动态规划和算法竞赛中反复出现,是典型的“构造 + 鸽巢”双人舞。
1. 列出前缀和:从 0 开始累加,共 n+1 个前缀和,比 n 个数多一个
2. 余数只有 n 类:每个 s_i 对 n 取模,落点只有 0 到 n−1
3. 鸽巢找重合:n+1 个余数放入 n 类,必有 i<j 使余数相同
4. 还原连续和:sⱼ−sᵢ 正是 a_{i+1} 到 aⱼ 的连续和,且被 n 整除
王师傅把“生日魔法”挂在嘴边:367 个会员,不用翻会员册,他就能断言有两人同一天生日。这就是鸽巢的力量——有些结论,数学已经把后门焊死,你只需要往里面丢东西。
编程应用
王师傅请程序员开发了一套自动分拣系统:每个包裹按订单号哈希到对应货架。系统上线第一天就出问题——两个包裹被分到了同一个格子。程序员挠头找 bug,王师傅笑了:这不是 bug,这是鸽巢原理。只要货架格子数少于包裹数,冲突就注定发生,再厉害的哈希函数也逃不掉。
哈希表的本质,是把 key 映射到有限的槽位。当插入的元素个数超过槽位数时,冲突不可避免——这是鸽巢原理的直接推论。工程上的应对不是“消灭冲突”,而是“管理冲突”:链地址法把冲突元素串成链表挂在槽位下,开放寻址法向后探测下一个空位。理解了鸽巢原理,你就理解了为什么所有哈希表都必须内置冲突处理策略,而不是事到临头才想补救。
另一个经典套路是“抽屉计数”:值域有限时,用一个计数数组(抽屉)统计每个值的出现次数。已知 n+1 个整数都在 [1, n] 内时,用长度 n 的计数数组扫一遍就能找出重复元素,时间 O(n)、空间 O(n)。鸽巢原理保证重复必定存在,所以代码可以理直气壮地写“找到第一个重复就返回”,绝不落空。
1. 槽位即盒子:哈希表的 n 个槽位等价于 n 个盒子,容量固定
2. key 即物品:插入 k 个 key 时,若 k>n 则物品多于盒子
3. 冲突无可避免:至少一个槽位要承接不少于 2 个 key
王师傅的分拣系统后来加了链表:冲突的包裹排队挂在同一个格子边上。他彻底明白了,鸽巢原理不是诅咒,而是提醒——正视“格子不够”的事实,提前设计好容错机制,系统才能稳如泰山。
AI 应用场景
大数据分桶去重
阶段:数据预处理 / 数据工程
解决的问题:日志系统每天产生亿级记录,需要按用户 ID 分桶去重。传统方案要么全局排序(O(n log n) 耗时),要么全部载入内存(直接爆内存)。鸽巢原理帮助工程师预判桶数与冲突率:当桶数 m 远小于 key 数 k 时,桶内冲突必然发生,因此必须设计“内存桶 + 磁盘溢写”的分层结构,而不是奢望完美散开。这种“先认命、再容错”的思路,正是鸽巢原理给大数据工程的第一课。
具体案例:某推荐系统离线任务要把 10 亿用户行为日志按 user_id 哈希到 4096 个分片。工程师事先用鸽巢原理估算:10^9 远大于 4096,某些分片必然成为热点。于是为每个分片配置溢写阈值和重平衡策略,成功避免了单分片 OOM 导致的整个流水线失败。
特征哈希与碰撞控制
阶段:特征工程
解决的问题:高基数类别特征(如用户 ID、商品 ID)做 one-hot 后维度爆炸,模型根本无法训练。特征哈希(hashing trick)把类别映射到固定维度 d,但 d 小于类别总数时碰撞不可避免——这正是鸽巢原理的领域。与其恐惧碰撞,不如量化碰撞对模型的影响,用实验数据决定维度选择。
具体案例:某 CTR 预估模型使用特征哈希,把百万级稀疏类别压缩到 2^18 维。工程师知道 d=2^18 < 100 万,碰撞必然存在,但离线实验表明适度碰撞对 AUC 影响小于 0.1%,而内存占用下降了 90%。在这个案例里,鸽巢原理不是用来“避免碰撞”,而是用来“接受碰撞并评估代价”。
分布式任务调度的热点预判
阶段:模型训练 / 推理服务
解决的问题:动态到达的推理请求要分发到 N 个 GPU worker。当请求总数远超 N 时,鸽巢原理告诉你某些 worker 必然承接更多请求,热点无法消除。系统设计必须包含排队、超时、幂等重试机制,而不是天真地以为负载均衡器能做到完全均匀。
具体案例:线上 LLM 服务把请求轮询到 8 个推理节点,高峰时单秒请求数达数千。由于计算时长差异,轮询也无法阻止单个节点堆积。工程师根据鸽巢原理预判“热点必然存在”,为每个节点配置了独立队列和慢启动丢弃策略,最终将尾延迟从 8 秒降到 600 毫秒。
Python 演示
def hash_collision_demo(num_items, num_slots): """把 num_items 件物品哈希进 num_slots 个槽位, 观察必然冲突.""" slots = [0] * num_slots collisions = 0 first_collision = None for i in range(num_items): slot = i % num_slots # 最简单的哈希函数 if slots[slot] > 0: collisions += 1 if first_collision is None: first_collision = i slots[slot] += 1 max_count = max(slots) return slots, collisions, first_collision, max_count def find_duplicate_pigeonhole(nums): """nums 长度 n+1, 元素都在 [1, n], 鸽巢原理保证必有重复.""" n = len(nums) - 1 counter = [0] * (n + 1) for x in nums: if counter[x] > 0: return x counter[x] = 1 return -1 def main(): print("=== 鸽巢原理: 哈希冲突必现 ===") for slots_num in (5, 10): for items_num in (5, 6, 11): slots, collisions, first, max_count = hash_collision_demo(items_num, slots_num) expect = max(1, (items_num + slots_num - 1) // slots_num) assert max_count >= expect, "广义鸽巢原理被违反" print(f"{slots_num} 槽 / {items_num} 件 -> 最大槽 {max_count} 件, 冲突 {collisions} 次" + (f", 首次冲突在 item_{first}" if first is not None else "")) print() print("=== 鸽巢原理: n+1 个数找重复 ===") sample = [3, 1, 4, 2, 3, 4, 5, 6, 7, 8, 9] dup = find_duplicate_pigeonhole(sample) print(f"样例 {sample} 中重复的数字是 {dup}") if __name__ == "__main__": main()
for i in range(num_items): slot = i % num_slots用取模模拟哈希函数,把每个物品映射到固定槽位,这是理解冲突的最小模型。if slots[slot] > 0: collisions += 1当目标槽位已有物品时记一次冲突,这正是鸽巢原理所说的“两个物品挤进同一个盒子”。assert max_count >= (items_num + slots_num - 1) // slots_num用上取整公式 ⌈m/n⌉ 验证广义鸽巢原理,任何违反都会让程序直接报错。counter = [0] * (n + 1)抽屉计数法:为每个可能取值准备一个“抽屉”,空间换时间。if counter[x] > 0: return x第二次见到同一个数字立即返回,鸽巢原理保证这个分支必定会被触发。
常见误区
误区“鸽巢原理只告诉我有重复,但具体是哪个我根本不知道,所以证明完了等于白说。”
正解鸽巢原理给出的确实是存在性命题,但很多场景下可以构造性证明。比如哈希表逐项插入时,记录第一个冲突的位置;n+1 个数找重复时,用计数数组扫一遍,重複元素立刻现形。证明负责告诉你“一定有”,构造负责告诉你“在哪里”,两者配合才是完整武器。就像王师傅知道“必有格子放两件”,他挨个格子看一眼就能找到它。
为何常见:初学者把“存在性”误解为“不可构造”,忽视了鸽巢证明本身往往就带着构造线索——你只需要顺着分配过程走一遍。
误区“5 个苹果放 4 个抽屉,那每个抽屉差不多都有一个吧,至少一盒有两个的前提是大家都要有。”
正解鸽巢原理只保证下限,即至少一个盒子不少于 2 件,它从不承诺每个盒子都有货。极端情况下 5 个苹果全塞进一个抽屉,其他三个空着,结论依然成立——因为“最挤的那个”从不落空。数学的反证法恰恰允许极端分布存在,均匀只是众多可能中的一种。
为何常见:生活直觉倾向于平均主义,而鸽巢原理关注的是“最差情况的下限”,这是初学者最常栽的思维陷阱。
误区“100 个鸡蛋放 30 个筐,平均每筐 3.33 个,那至少一筐有 3 个呗。”
正解正确的保底数是向上取整的 ⌈100/30⌉=4。如果只保证 3 个,相当于说“每筐至多 3 个也能装下 100 个”,但 30×3=90<100,矛盾。口诀是:平均之后必有幸运儿超过平均线。向上取整是“装得下的底线”,向下取整是“分得开的幻想”。
为何常见:日常四舍五入和向下取整的习惯根深蒂固,而严格证明里区分“<”与“≤”是生死线,一不留神就滑向错误结论。
误区“概率上说 23 人就有 50% 概率两人生日相同,所以 23 人时鸽巢原理也保证有重复。”
正解鸽巢原理给的是确定性结论:367 个人必定有两人生日相同。23 人 50% 是概率论的结果,性质完全不同——概率可能失手,鸽巢原理永不失手。一个说“很可能”,一个说“必然”,二者是并行不悖的两条数学路线。用王师傅的话说:概率是天气预报,鸽巢原理是数学定律。
为何常见:同一个生日场景出现两种结论,初学者容易混淆“概率存在”与“确定存在”的逻辑边界,尤其当数值差异很大时更容易晕头转向。
误区“n+1 个物品放 n 个盒子必然冲突,那 n 个物品放 n 个盒子也大概率冲突吧?”
正解n 个物品放 n 个盒子完全可以一一对应、井水不犯河水,比如每个格子恰好一件。鸽巢原理的关键在于“比盒子多一件”这个条件,多出的一件打破了一切完美匹配的可能。差一件和差一百件,结论都是“必然冲突”,但刚好相等时,命运还没被锁定。这是“临界点”思维的起点。
为何常见:人们习惯把“差不多”当成“一样”,在数学里差一件就是质变——就像货架满格时,再多一个包裹,整个系统就从有序滑向必然的混乱。
面试题
Q1. 将 6 个苹果放入 5 个抽屉,鸽巢原理断言必然存在一个抽屉至少有多少个苹果?
- A.1 个
- B.2 个← 正确答案
- C.3 个
- D.5 个
答案:B。6 件物品放 5 个盒子,n+1>n,至少一盒 ≥2 件。选 A“1 个”虽然恒真但太弱,不是鸽巢原理的断言;C 和 D 是过度推断。用快递驿站联想:6 个包裹放 5 个格子,最挤的格子至少 2 件。
Q2. 不考虑闰年,要保证一群人中有两人生日相同,至少需要多少人?
- A.183
- B.23
- C.366← 正确答案
- D.367
答案:C。不考虑闰年一年 365 天,把 365 个日期当盒子,366 个人当包裹,366>365,鸽巢原理保证有两人生日相同。367 是考虑 2 月 29 日时的答案;23 人是概率论中 50% 碰撞所需的规模,不是确定性保证。
Q3. 已知一个长度为 n+1 的整数数组,所有元素取值都在 [1, n],鸽巢原理保证什么?
- A.数组一定有序
- B.至少两个元素相等← 正确答案
- C.所有元素之和能被 n 整除
- D.数组中存在负数
答案:B。n 个可能的取值是“盒子”,n+1 个元素是“包裹”,必有至少两个元素落入同一个取值,即相等。这正是哈希去重和抽屉计数法的数学根基。数组是否有序、和能否整除都与鸽巢原理无关。
Q4. 100 个鸡蛋放入 30 个筐,至少有一筐不少于多少个鸡蛋?
- A.2
- B.3
- C.4← 正确答案
- D.5
答案:C。平均每筐 100/30≈3.33 个,向上取整得 ⌈100/30⌉=4。若每筐至多 3 个,30 筐最多装 90 个,装不下 100 个。记住口诀:平均之后必有幸运儿超过平均线,答案取上整而非下整。
Q5. 任意 5 个整数中,必有某两个数之差能被以下哪个数整除?
- A.2
- B.3
- C.4← 正确答案
- D.5
答案:C。整数除以 4 的余数只有 0、1、2、3 共 4 类,5 个整数放入 4 个余数盒子,鸽巢原理保证有两个数同余,它们的差被 4 整除。余数是最省心的分类器,5 > 4 是关键。
Q6. 证明“6 人中必有 3 人两两认识或两两不认识”依赖的是哪个理论?
- A.费马小定理
- B.欧拉公式
- C.Ramsey 定理 R(3,3)=6← 正确答案
- D.中国剩余定理
答案:C。把 6 人作为完全图顶点、认识关系染成红/蓝边。从任一顶点引出的 5 条边中,鸽巢原理保证至少 3 条同色,再看这 3 个顶点之间的边,必形成同色三角形。这正是拉姆齐定理的经典起点 R(3,3)=6。费马小定理和欧拉公式属于数论,与社交关系图无关。
Q7. 有 5 种颜色的袜子,闭着眼睛至少取多少只才能保证有 3 只同色?
- A.10
- B.11← 正确答案
- C.15
- D.6
答案:B。最坏情况是每种颜色恰好取 2 只,共 10 只仍无三只同色;再取第 11 只,5 种颜色中必有一种达到 3 只。这是广义鸽巢原理:保证 3 只同色需要 5×(3−1)+1=11 只。10 只是“可能不同色”的极限,11 只是“保证同色”的临界。
Q8. 下列哪些问题可以用鸽巢原理直接证明?
- A.n+1 个 key 放入 n 个哈希槽位必有冲突← 正确答案
- B.任意 n+1 个取值在 [1,n] 内的整数必有重复← 正确答案
- C.素数有无穷多个
- D.任意 6 人中必有 3 人两两认识或两两不认识← 正确答案
答案:ABD。A 和 B 是鸽巢原理的直接套用:物品多于盒子,必有重叠。D 是 Ramsey 经典情形,核心推导依赖鸽巢原理(一个顶点引出 5 条边、2 色取 3 条同色)。C 是欧几里得的经典证明,用反证与乘法构造,与鸽巢无关。
Q9. 关于广义鸽巢原理 ⌈m/n⌉,下列说法正确的有?
- A.m 件物品放入 n 个盒子,至少一盒不少于 ⌈m/n⌉ 件← 正确答案
- B.当 m=n 时,至少一盒不少于 2 件
- C.当 m<n 时,盒子中一定存在空盒← 正确答案
- D.⌈m/n⌉ 表示不大于 m/n 的最大整数
答案:AC。A 是广义鸽巢原理的标准表述。B 错误:m=n 时可能每盒恰好 1 件,鸽巢只保证不少于 1 件。C 正确:m<n 时若每盒至少 1 件则总容量至少 n 件,超过 m,矛盾,所以必有空盒。D 错误:⌈⌉ 是向上取整,向下取整写作 ⌊⌋。
Q10. 关于哈希表与鸽巢原理的关系,下列说法正确的有?
- A.向 n 个槽位插入 n+1 个 key 必定发生冲突← 正确答案
- B.插入 n 个 key 时可以做到无冲突← 正确答案
- C.链地址法从根本上消除了冲突
- D.槽位数越少,冲突概率越高← 正确答案
答案:ABD。A 是鸽巢原理的直接结论。B 正确:n 个 key 与 n 个槽可一一对应,完美哈希理论存在,鸽巢不保证冲突。C 错误:链地址法只是把冲突元素串成链表存起来,冲突事件本身没有消失。D 正确:槽位越少,平均每个槽位 key 越多,碰撞概率越高,超过临界点后冲突由“可能”变为“必然”。