抽屉原理

· · 个人记录

抽屉原理

敬请往下浏览!

原理:

第一抽屉原理:

原理1: 把多于 n+1 个的物体放到 n 个抽屉里,则至少有一个抽屉里的东西不少于两件。

证明(反证法):如果每个抽屉至多只能放进一个物体,那么物体的总数至多是 n×1,而不是题设的 n+k(k≥1) ,故不可能。

原理2 : 把多于mn(m \times n)+1 (n!=0) 个的物体放到 n 个抽屉里,则至少有一个抽屉里有不少于 (m+1) 的物体。

证明(反证法):若每个抽屉至多放进 m 个物体,那么 n 个抽屉至多放进 mn 个物体,与题设不符,故不可能。

原理3 : 把无穷多件物体放入 n 个抽屉,则至少有一个抽屉里 有无穷个物体。

原理1 、2 、3都是第一抽屉原理的表述。

第二抽屉原理:

(mn-1) 个物体放入 n 个抽屉中,其中必有一个抽屉中至多有 (m-1) 个物体

运用:

构造抽屉的方法:

运用抽屉原理的核心是分析清楚问题中,哪个是物件(元素),哪个是抽屉。

形如:任意写一个数字 1,2,3 组成的 30 位数,从这 30 位数中任意截取相邻的三位,求证在各个不同的位置上所截得的三位数至少有两个相等。

证明:由题可知,共截取 28 个三位数=> 28 个元素,而三位数所构成的情况为 3^3=27 ,视为 27 个抽屉。根据抽屉原理必有两数相同。

最差原则:

什么是最差原则?

所谓最差原则(又称“最不利原则”),就是考虑问题发生的最差情况,然后就最差情况进行分析。最差原则是极端法的一种应用,一般情况下,我们优先考虑用最差原则来解决抽屉问题。

形如1:300 人去雅礼中学考试,AKIOI 的有 150 人,AKIMO 的有 80 人,AKIPhO70 人,吊打集训队的有 50 人。求至少录取多少学生才能保证特长 70 人的特长相同。

解析1:此时我们考虑的最差情况为:AKIOIAKIMOAKIPhO 各录取 69 人,吊打集训队的 50 人全部录取,则此时再录取 1 人就能保证有 70 人找到的特长生相同。

推导1: 根据第二抽屉原理, mn+1 个人的时候必有 m+1 个人找到的特长相同,所以是要求出 mn+1 的人数,现在已知n=4,m+1=70。考虑到吊打集训队只有50人,得出 mn+1=(69*3+50)+1=258人。

形如2: lrj124 去参加IOI考试,出发的时候,发现自己价值 10 亿 美元的自行车,被人多上了10 把锁(他自己本来车子上就有一把),地上有 10 把与锁配对的钥匙。请问,可怜的 lrj124 最多要试才能将车子解开去AKIOI

解析2:此时我们考虑的最差情况为:在 10 把锁中,第n把锁最差的情况要试(11 - n)次,还有第 11 把锁则是 lrj124 自己的,要试一次。所以一共要试1->10锁最多次数的总和 +1。所以 lrj124 要用 10+9+8+7+6+5+4+3+2+1+1=56次 才能将车子解开去AKIOI

推导2: 条件十分清晰,这是一道经典的小奥题。我们只要根据最差原则来推出次数,再依次相加即可得出。

表现形式:

把它推广到一般情形有以下几种表现形式。

形式1: 设把 n+1 个元素划分至 n 个集合中 (A1,A2,…,An) ,用 a1,a2,…,an 分别表示这 n 个集合对应包含的元素个数,则:至少存在某个集合 Ai ,其包含元素个数值 ai≥2

证明1:(反证法)假设结论不成立,即对每一个 ai 都有 ai<2 ,则因为 ai 是整数,应有 ai≤1 ,于是有: a1+a2+…+an≤1+1+…+1=n<n+1,这与题设矛盾。

所以,至少有一个 ai≥2 ,即必有一个集合中含有两个或两个以上的元素。

形式2: 设把 nm+1 个元素划分至 n 个集合中 (A1,A2,…,An) ,用 a1,a2,…,an 表示这n个集合对应包含的元素个数,则:至少存在某个集合 Ai ,其包含元素个数值 ai 大于或等于 m+1

证明2:(反证法)假设结论不成立,即对每一个 ai 都有 ai<m+1 ,则因为 ai 是整数,应有 ai≤m ,于是有: a1+a2+…+an≤m+m+…+m=nm<nm+1 ,这与题设相矛盾。

所以,至少有存在一个 ai≥m+1

知识扩展--高斯函数 [x] 定义:对任意的实数 x[x]表示"不大于 x 的最大整数"。例如: [3.5]=3[2.9]=2[-2.5]=-3[7]=7,……一般地,我们有:[x]≤x<[x]+1

形式3: 设把 n 个元素分为k个集合 A_1A_2,…,A_k ,用 a_1,a_2…,a_k 表示这k个集合里相应的元素个数,需要证明至少存在某个 a_i 大于或等于 [n/k]

证明3:(用反证法)假设结论不成立,即对每一个 a_i 都有 a_i<[n/k] ,于是有: a_1+a_2+…+a_k<[n/k]+[n/k]+…+[n/k] =k?[n/k]≤k?(n/k)=n

**形式4:** 设把 $q_1+q_2+…+q_n-n+1$ 个元素分为 $n$ 个集合 $A_1$,$A_2$,…,$A_n$,用 $a_1$,$a_2$,…,$a_n$表示这n个集合里相应的元素个数,需要证明至少存在某个 $i$ ,使得 $a_i$ 大于或等于 $q_i$ 。 **证明4:**(用反证法)假设结论不成立,即对每一个 $a_i$ 都有 $a_i<q_i$ ,因为 $a_i$ 为整数,应有 $a_i≤q_i-1$ ,于是有: $a_1+a_2+…+a_n≤q_1+q_2+…+q_n-n <q_1+_q2+…+q_n-n+1$ 这与题设矛盾。 所以,假设不成立,故必有一个i,在第i个集合中元素个数 $a_i≥q_i$ 。 **形式5:** 证明:(用反证法)将无穷多个元素分为有限个集合,假设这有限个集合中的元素的个数都是有限个,则有限个有限数相加,所得的数必是有限数,这就与题设产生矛盾,所以,假设不成立,故必有一个集合含有无穷多个元素。(借由康托的无穷基数可将鸽巢原理推广到无穷集中。) ------------ ## 例题1: **已知 $n + 1$ 个正整数,它们全都小于或等于 $2n$ ,证明当中一定有两个数是互质的。** 匈牙利大数学家厄杜斯(PaulErdous,1913 - 1996) 向当年年仅 $11$ 岁的波萨 (LouisPósa) (年少有为...)提出这个问题,而小波萨思考了不足半分钟便能给出正确的答案。 波萨是这样考虑问题:取 $n$ 个盒子,在第一个盒子我们放 $1$ 和 $2$ ,在第二个盒子我们放 $3$ 和 $4$ ,第三个盒子是放 $5$ 和 $6$ ,依此类推直到第 $n$ 个盒子放 $2n-1$ 和 $2n$ 这两个数。 如果我们在 $n$ 个盒子里随意抽出 $n+1$ 个数。我们马上看到一定有一个盒子是被抽空的。因此在这 $n+1$ 个数中必有两个数是连续数,很明显的连续数是互质的。因此这问题就解决了! 这就是利用了抽屉原理的核心思想。 ------------ ## 例题2: ** Ramsey定理 (又称广义抽屉原理) ** 狭义解释1:任意六个人中要么至少三个人认识,要么至少三个不认识。 狭义解释2:设空间内任意三个点不共面,若将其中的任意两个点的连线染成红色或蓝色,则必存在三边颜色相同的三角形。 狭义证明1:如狭义解释1,首先,把这 $6$ 个人设为 $A$、$B$、$C$、$D$、$E$、$F$ 六个点。由 $A$ 点可以引出$AB$、$AC$、$AD$、$AE$、$AF$五条线段。设:如果两个人认识,则设这两个人组成的线段为红色;如果两个人不认识,则设这两个人组成的线段为蓝色。由抽屉原则可知:这五条线段中至少有三条是同色的。不妨设$AB$、$AC$、$AD$为红色。若$BC$或$CD$为红色,则结论显然成立。若$BC$和$CD$均为蓝色,则若$BD$为红色,则一定有三个人相互认识;若$BD$为蓝色,则一定有三个人互相不认识。 ------------ ## 例题3: **$17$个科学家中,每个科学家都和其他科学家通信,他们之间讨论$3$个题目,且任意两个科学家之间只讨论$1$个题目,证明其中至少有$3$名科学家,他们互相通信中讨论的是同一题目。** **思路:**视$17$个科学家为$17$个点,每两个点之间连一条线表示这两个科学家在讨论同一个问题,若讨论第一个问题则在相应两点连红线,若讨论第$2$个问题则在相应两点连条黄线,若讨论第$3$个问题则在相应两点连条蓝线。三名科学家研究同一个问题就转化为找到一个三边同颜色的三角形。 **证明:** 考虑科学家$A$,他要与另外的$16$位科学家每人通信讨论一个问题,相应于从$A$出发引出$16$条线段,将它们染成$3$种颜色,而$16=3×5+1$,因而必有$6=5+1$条同色,不妨记为$AB1,AB2,AB3,AB4,AB5,AB6$同红色,若$Bi$($i=1$,$2$,…,$6$)之间有红线,则出现红色三角线,命题已成立;否则$B1$,$B2$,$B3$,$B4$,$B5$,$B6$之间的连线只染有黄蓝两色。考虑从$B1$引出的$5$条线,$B1B2$,$B1B3$,$B1B4$,$B1B5$,$B1B6$,用两种颜色染色,因为$5=2×2+1$,故必有$3=2+1$条线段同色,假设为黄色,并记它们为$B1B2$,$B1B3$,$B1B4$。这时若$B2$,$B3$,$B4$之间有黄线,则有黄色三角形,命题也成立,若$B2$,$B3$,$B4$,之间无黄线,则 $△B2,B3,B4$,必为蓝色三角形,命题仍然成立。 ------------ ## 例题4: **以($x,y,z$)表示有序三元数组,其中$x,y,z$为整数,试证:在任意七个三元整数组中,至少有两个三元数组,它们的$x,y,z$元中都是奇数或都是偶数。**( **思路1:** 此类题我们可以“逐个击破”,一步步的证明。如先考虑$x$的情况,再考虑$y$,最后是$z$。(注意$x,y,z$顺序) **证明1:**($0$为偶数,$1$为奇数) 如($x1,y1,z1$)$010$ ——同奇偶 和($x2,y2,z2$)$101$ ——不符合 故我们先考虑x,根据第二抽屉原理,至少有$4$个$x$同奇偶,在这里我们就设为偶($0$)。如: $A1$($0,y1,z1$) $A2$($0,y2,z2$) $A3$($0,y3,z3$) $A4$($0,y4,z4$) 我们再来考虑y,根据第二抽屉原理,至少有$2$个$y$同奇偶,若为偶,则满足条件,则我们让$y$为奇。(至少有$3$个奇数)则: $A1$($0,1,z1$) $A2$($0,1,z2$) $A3$($0,1,z3$) 最后来考虑$z$,根据第二抽屉原理,至少有$2$个$z$同奇偶,此时若为奇或偶都成立。 $A1$($0,1,0$)或($0,1,1$) $A2$($0,1,0$)或($0,1,1$) $A3$($0,1,1$)或($0,1,0$)都成立 **思路2:** 此类题我们还可以“整体考虑”,将所有的可能性算出来,再去证明。 **证明2:**我们可以显而易见地想出($x,y,z$)共有$8$种奇偶排列方式。 $A1$($1,1,1$) $A2$($1,1,0$) $A3$($1,0,0$) $A4$($0,0,0$) $A5$($1,0,1$) $A6$($0,1,0$) $A7$($0,0,1$) $A8$($0,1,1$) 若同时选择了两次相同的奇偶形式,命题成立。(如$A1,A1$成立) 同理,得证! ------------ ## 小试牛刀: ### CF1305C Kuroni and Impossible Calculation #### 题意: 给定 $a1,a2,...,an$ 和 $m$($1≤m≤1000$),求 $\prod_{1\le i<j\le n}\left|a_i-a_j\right|\%m$。 #### 思路: 读题可知,当 $n<m$ 时,必有两项 $ai,aj$ 模 $m$ 同余,由此可知,$Ans=0$,否则暴力跑一遍 $O(nm)$ . #### 代码: ```cpp #include<bits/stdc++.h> using namespace std; inline long long read() { long long x = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') { if(c == '-') { f = -1; } c = getchar(); } while (c <= '9' && c >= '0') { x = (x << 1) + (x << 3) + (c ^ 48), c = getchar(); } return x * f; } const int Maxn = 2e5 + 5; int n, m; long long ans = 1, a[Maxn]; int main() { n = read(), m = read(); if(n > m) { puts("0"); return 0; } for(register int i = 1; i <= n; ++i) { a[i] = read(); } for(register int i = 1; i <= n; ++i) { for(register int j = i + 1; j <= n; ++j) { ans = ans * abs(a[i] - a[j]) % m; } } printf("%lld\n", ans); return 0; } ``` ------------ ### POJ2356 Find a multiple #### 题意: 给你长为 $n$ 的一个序列,要求在序列中找到连续的一些数,使他们的和是 $n$ 的倍数,输出抽多少个,并分别输出他们。 #### 思路: 若使用前缀和暴力枚举子串,时间复杂度为 $O(n ^ 2)$ ,会超时。 令每一个前缀和对 $n$ 的模数设为 $x$ ,若 $i = k$ 的时候 $x = 0$ 那意味着 $1$ 到 $i$ 是一个符合的序列。 若 $n$ 个前缀和的模数都在 $1$ 和 $n - 1$ 之间,根据抽屉原理,定有两个模数相同,设其下标分别为 $l$ 和 $r$, $sum[l]$ 或 $sum[r]$ $% n = x$, 那么 $sum[l] - sum[r]$ 这一部分的和 $% n$ 等于零,故我们只要找到 $l$ 和 $r$ 并输出 $l + 1$ 到 $r$ 序列即可。 #### 代码: ```cpp #include<bits/stdc++.h> using namespace std; inline long long read() { long long x = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') { if(c == '-') { f = -1; } c = getchar(); } while (c <= '9' && c >= '0') { x = (x << 1) + (x << 3) + (c ^ 48), c = getchar(); } return x * f; } const int Maxn = 2e4 + 4; int n, vis[Maxn]; long long a[Maxn], sum[Maxn], num[Maxn]; int main() { while(cin >> n) { Mem(vis, 0); for(register int i = 1; i <= n; ++i) { a[i] = read(); sum[i] = sum[i - 1] + a[i]; num[i] = sum[i] % n; } int l = 1, r = 0; for(register int i = 1; i <= n; ++i) { if(num[i] == 0) { l = 1, r = i; break; } if(vis[num[i]] == 0){ vis[num[i]] = i; } else { l = vis[num[i]] + 1, r = i; break; } } printf("%d\n", r - l + 1); for(register int i = l; i <= r; ++i) { printf("%lld\n", a[i]); } } return 0; } ``` ------------