




















抽屉原理(又称鸽巢原理)是组合数学中最基础但又极其强大的工具之一,它的核心思想极其直观:如果物品的数量多于容器的数量,那么至少有一个容器里盛放了不止一个物品。虽然原理本身非常简单,但通过巧妙地“构造抽屉”和“确定物品”,它可以用来证明很多看似难以下手的存在性问题。
简单抽屉原理:若将 \(n+1\) 个物体放入 \(n\) 个抽屉,则至少有一个抽屉中包含 \(2\) 个或 \(2\) 个以上的物体。
反证法。
假设每个抽屉包含的物体数量都少于 \(2\) 个(即最多包含 \(1\) 个),那么 \(n\) 个抽屉所能容纳的物体总数最多为 \(n \times 1 = n\) 个,这与总共有 \(n+1\) 个物体的已知条件相矛盾。因此,假设不成立,原命题成立。
例如:\(13\) 个人中,至少有 \(2\) 个人的出生月份相同(\(13\) 个物品放入 \(12\) 个月份抽屉);从一副扑克牌中任意抽取 \(5\) 张普通牌(不含大小王),因为扑克牌只有 \(4\) 种花色(黑桃、红心、梅花、方块),所以至少有 \(2\) 张牌的花色相同(\(5\) 个物品放入 \(4\) 个花色抽屉)。
在实际应用中,物品的数量往往多于抽屉的数量,此时需要更一般的结论。
推广抽屉原理:若将 \(N\) 个物体放入 \(k\) 个抽屉中,则至少有一个抽屉中包含不少于 \(\lceil \frac{N}{k} \rceil\) 个物体。
推论(加权/平均值形式):若 \(a_1 + a_2 + \cdots + a_k = N\),则存在至少一个 \(i \in \{ 1, 2, 3, \dots, k \}\),使得 \(a_i \ge \lceil \frac{N}{k} \rceil\)。
反向表达(极值推论):要确保至少有一个抽屉里有 \(m\) 个物体,物体的总数 \(N\) 至少需要达到 \(N = k(m-1)+1\)。
练习:在 \(1,2,3,\dots,10\) 这 \(10\) 个自然数中,任意取出 \(6\) 个数,证明“其中必有两个数的和等于 \(11\)”。
将这 \(10\) 个数配对成 \(5\) 个集合(抽屉)\(\{ 1,10 \}, \{ 2,9 \}, \{ 3,8 \}, \{ 4,7 \}, \{ 5,6 \}\),共 \(5\) 个抽屉。从 \(10\) 个数中取出 \(6\) 个数(\(6\) 个物体),根据抽屉原理,至少有两个数来自于同一集合。而每个集合中两数之和均为 \(11\),故必有两个数的和等于 \(11\)。
练习:在一个 \(3 \times 7\) 的网格图中,每个小方格涂上红色或蓝色,证明“图中必然存在一个矩形,它的四个角上的小方格颜色完全相同”。
考虑每一列的 \(3\) 个格子的颜色,因为只有 \(2\) 种颜色,根据抽屉原理,每列的 \(3\) 个格子中至少有 \(2\) 个格子颜色相同(同红或同蓝)。
每一列中“相同颜色的两个位置”共有 \(C_3^2 = 3\) 种位置组合 \((1,2), (2,3), (1,3)\),且颜色有 \(2\) 种(红/蓝),因此位置组合与颜色的形态共有 \(3 \times 2 = 6\) 种(即 \(6\) 个抽屉)。
网格一共有 \(7\) 列(\(7\) 个物体),根据抽屉原理,在这 \(7\) 列中,至少有 \(2\) 列具有完全相同的“同色位置与颜色”形态,这两列中对应的 \(4\) 个角上的方格就构成了一个四角同色的矩形。
在数论中,余数是天然的“抽屉”。模 \(m\) 的余数只有 \(0, 1, 2, \dots, m-1\) 共 \(m\) 种可能。
例题:证明“任意给定 \(n+1\) 个整数,其中必有两个数的差是 \(n\) 的倍数”。
给定的 \(n+1\) 个整数 \(a_1, a_2, \dots, a_{n+1}\) 即 \(n+1\) 个物体,按照除以 \(n\) 的余数分类。任何整数除以 \(n\) 的余数只能是 \(0,1,2, \dots, n-1\),共 \(n\) 种可能的余数(共 \(n\) 个抽屉)。把 \(n+1\) 个整数按其余数放入 \(n\) 个抽屉中,根据抽屉原理,必有两个整数 \(a_i\) 和 \(a_j \ (i \ne j)\) 落在同一个抽屉中,即它们除以 \(n\) 的余数相同。余数相同,则它们的差 \(a_i-a_j\) 必能被 \(n\) 整除。
练习:证明“在任意给定的 \(n\) 个整数 \(a_1, a_2, \dots, a_n\) 中,必能找到若干个连续的数,它们的和能够被 \(n\) 整除”。
考虑 \(n\) 个前缀和 \(S_1, S_2, \dots, S_n\),若其中某个 \(S_k \equiv 0 \pmod{n}\),则前 \(k\) 个数之和就能被 \(n\) 整除,命题得证。
若所有 \(S_k\) 都不能被 \(n\) 整除,则它们模 \(n\) 的余数只能在 \(1,2, \dots, n-1\) 中取值(共 \(n-1\) 种余数,即 \(n-1\) 个抽屉)。
将 \(n\) 个前缀和放入这 \(n-1\) 个抽屉中,由抽屉原理,必有两个前缀和 \(S_i\) 和 \(S_j \ (i \lt j)\) 模 \(n\) 同余,即 \(S_j \equiv S_i \pmod{n}\),此时连续段之和 \(\sum \limits_{k=i+1}^j a_k = S_j - S_i\) 必能被 \(n\) 整除。
几何问题通常利用面积划分或距离分割来构造抽屉。
例题:证明“在边长为 \(1\) 的正方形内任意放入 \(5\) 个点,必有两个点之间的距离不超过 \(\frac{\sqrt{2}}{2}\)”。
将边长为 \(1\) 的正方形连接各边中点,等分成 \(4\) 个边长为 \(\frac{1}{2}\) 的小正方形。将 \(5\) 个点放入 \(4\) 个小正方形中,由抽屉原理,至少有 \(2\) 个点落在同一个边长为 \(\frac{1}{2}\) 的小正方形内(或边界上)。边长为 \(\frac{1}{2}\) 的正方形内,任意两点间的最大距离即为其对角线长 \(d_{\max} = \sqrt{ \left( \frac{1}{2} \right) ^2 + \left( \frac{1}{2} \right) ^2 } = \frac{\sqrt{2}}{2}\)。因此,这两个点之间的距离必然不超过 \(\frac{\sqrt{2}}{2}\)。
图论中的节点度数、边着色等问题,经常可以通过抽屉原理寻找对称性或局部结构。
例题:假设在一个由 \(6\) 个人组成的群体中,任意两个人之间的关系恰为两种之一(两两相互认识,或者两两相互不认识,即“认识”关系满足对称性),证明“该群体中必然存在 \(3\) 个人,他们两两相互认识;或者存在 \(3\) 个人,他们两两相互不认识”。
将 \(6\) 个人抽象为无向图 \(G\) 的 \(6\) 个顶点 \(V = \{ v_1, v_2, \dots, v_6 \}\),任意两个顶点之间都有连线(构成完全图 \(K_6\)):若两人相互认识,则连线涂成红色;若两人相互不认识,则连线涂成蓝色。
问题严格转化为:证明在用 \(2\) 种颜色对 \(K_6\) 的 \(15\) 条边进行任意着色后,图中必然存在一个同色三角形(全红三角形或全蓝三角形)。
任意挑选一个顶点 \(A\),在完全图 \(K_6\) 中,除去 \(A\) 之外还有 \(5\) 个顶点,因此从 \(A\) 出发共有 \(5\) 条边。这 \(5\) 条边只能涂上红色或蓝色(\(2\) 个颜色抽屉)。将 \(5\) 条边放入 \(2\) 种颜色抽屉中,根据推广抽屉原理,从 \(A\) 出发的 \(5\) 条边中,至少有 \(3\) 条边的颜色相同。
不妨设这 \(3\) 条同色边分别连接到顶点 \(B,C,D\),且颜色均为红色。考察 \(B,C,D\) 这三个顶点之间的 \(3\) 条连线 \((B,C),(C,D),(D,B)\):
综上所述,无论边如何着色,均能保证存在一个同色三角形,即群体中必存在 \(3\) 个人两两相互认识或两两相互不认识。
有 \(N \ (1 \le N \le 10^5)\) 头奶牛排成一队(编号从 \(1\) 到 \(N\)),初始时奶牛 \(1\) 在队首,奶牛 \(N\) 在队尾。Farmer John 按以下规则发礼物:
- 位于队首的奶牛拿到一份礼物。
- 拿到礼物的奶牛 \(i\) 会选择插队,使得其身后恰好留有 \(c_i \ (0 \le c_i \le N-1)\) 头奶牛(即插入到队首数起的第 \(N-c_i\) 个位置)。
- 重复上述过程。
在送出无限份礼物的过程中,请求出永远无法拿到礼物的奶牛数量。
若编号为 \(k\) 的奶牛能够拿到礼物,说明在前 \(k-1\) 头奶牛不断领礼物插队的过程中,队首指针能够顺利推进到第 \(k\) 头奶牛。由于前面的奶牛领完礼物后只会插入到队列的某个位置,不会凭空消失;如果第 \(k\) 头奶牛能够到达队首,那么所有编号小于 \(k\) 的奶牛必然也都在它之前到达过队首并拿到了礼物。因此,能够拿到礼物的奶牛编号必然构成一个连续的前缀 \([1, k]\),具有单调性。可以通过二分答案,在 \(O(\log N)\) 次检查内确定最大能拿到礼物的奶牛编号 \(k\),最终永远无法拿到礼物的奶牛数量即为 \(n-k\)。
需要判定“在前 \(k-1\) 头奶牛领礼物的过程中,第 \(k\) 头奶牛能否成功到达队首?”。
奶牛 \(i\) 领到礼物后,身后留有 \(c_i\) 头奶牛,这意味着它插队后的位置为从队首数起第 \(N-c_i\) 个位置。\(c_i\) 的值越大,说明插队后身后留的人越多,则越靠近队首(位置编号 \(N-c_i\) 越小)。如果关注队列最前面的 \(N-x\) 个位置(其中 \(x \in [0,N-1]\)),那么只有满足 \(N-c_i \le N-x\)(即 \(c_i \ge x\))的奶牛,插队后才会落在队首的前 \(N-x\) 个位置之内。
在前 \(k-1\) 头奶牛中,设恰有 \(s\) 头奶牛满足 \(c_i \le x\)(这些奶牛插队位置较靠后,落在第 \(N-x\) 个位置之后),那么剩下的 \(k-1-s\) 头奶牛均满足 \(c_i \ge x\)(这些奶牛插队位置均落在队首前 \(N-x\) 个位置之内)。此时,包含第 \(k\) 头奶牛本身在内,这 \(k-s\) 头奶牛(即第 \(k\) 头奶牛以及那 \(k-1-s\) 头插队位置靠前的奶牛)只要拿到礼物,其插队后的位置都会不超过 \(N-x\)。
队首的前 \(N-x\) 个位置,最多只能容纳 \(N-x\) 头奶牛。如果试图挤进这前 \(N-x\) 个位置的奶牛数量 \(k-s\) 严格大于可用的位置数 \(N-x\),即 \(k-s \gt N-x \iff x \gt N - (k-s)\)。根据抽屉原理,这 \(k-s\) 头奶牛将无法全部容纳在后方的队列中,它们会在队首的前 \(N-x\) 个位置中形成内部死循环,不断轮流领礼物并相互插队,导致队首指针永远无法越过它们推进到第 \(k\) 头奶牛。
因此,第 \(k\) 头奶牛能够成功到达队首的充要条件是:对于任意的 \(x \in [0,N-1]\),均不触发上述死循环,即必须满足 \(x \le N-(k-s)\),其中 \(s\) 为前 \(k-1\) 头奶牛中满足 \(c_i \lt x\) 的奶牛总数。
#include <iostream>
using namespace std;
const int N = (int)1e5 + 5;
int n, c[N], cnt[N];
// 判定第 $k$ 头奶牛是否能够拿到礼物
bool check(int k) {
// 统计前 k-1 头奶牛的 c[i] 频次
for (int i = 1; i < k; i++) {
cnt[c[i]]++;
}
bool ok = true;
int s = 0; // 记录 c[i]<x 的奶牛数量
// 检查每一个可能的位置分割参数 x
for (int x = 0; x < n; x++) {
if (cnt[x] > 0) {
// 根据抽屉原理,若 x>n-(k-s),说明奶牛无法通过该瓶颈
if (x > n - (k - s)) {
ok = false;
break;
}
s += cnt[x];
}
}
// 清理 cnt 数组
for (int i = 1; i < k; i++) {
cnt[c[i]] = 0;
}
return ok;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> c[i];
}
// 二分最大能够拿到礼物的奶牛编号
int l = 1, r = n, ans = 1;
while (l <= r) {
int m = l + (r - l) / 2;
if (check(m)) {
ans = m; l = m + 1;
} else {
r = m - 1;
}
}
// 输出无法拿到礼物的奶牛数量
cout << n - ans << "\n";
return 0;
}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。