鸽巢原理又名抽屉原理

一种简单的表述法为:

  • 若有n个笼子和n+1只鸽子,所有的鸽子都被关在鸽笼里,那么至少有一个笼子有至少2只鸽子

另一种为:

  • 若有n个笼子和kn+1只鸽子,所有的鸽子都被关在鸽笼里,那么至少有一个笼子有至少k+1只鸽子

例子:

  • 盒子里有10只黑袜子、12只蓝袜子,你需要拿一对同色的出来。假设你总共只能拿一次,只要3只就可以拿到相同颜色的袜子,因为颜色只有两种(鸽巢只有两个),而三只袜子(三只鸽子),从而得到“拿3只袜子出来,就能保证有一双同色”的结论。
  • 有n个人(至少2人)互相握手(随意找人握),必有两人握手次数相同。

一种表达是这样的:如果要把n个物件分配到m个容器中,必有至少一个容器容纳至少⌈n / m⌉个物件。(⌈x⌉大于等于x的最小的整数)

 

容斥原理又称排容原理

(1)两个集合容斥关系

鸽巢原理和容斥原理

(2)三个集合容斥关系

鸽巢原理和容斥原理

(3)n个集合的容斥关系

鸽巢原理和容斥原理

即1个集合的并-2个集合的并+3个集合的并-4个集合的并+5个集合的并......

 

鸽巢:

pku2365 Find a multiple

 题目意思是给n个数,选择其中一些数,使他们的和是n的k倍,k是自然数。只要输出其中正确的解就行

分析:

这n个数有n个前缀和,s[0],s[1],s[2]...s[n],并且对n取余

如果有s[i]==0,则输出0-i之间的数

如果不存在s[i]==0, 则s[i]一定在[1,n-1]之间 ,

根据鸽巢原理,n个物体放入n-1个盒子,至少有一个盒子有两个及以上的物体,所以题目一定有解

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 10010
int n;
int arr[maxn],s[maxn],h[maxn];
int main()
{
    while(~scanf("%d",&n))
    {
        memset(h,-1,sizeof(h));
        int x;
        for(int i=0;i<n;i++){
            scanf("%d",&arr[i]);
            s[i]=(s[i-1]+arr[i])%n;
        }
        int a,b;
        for(int i=0;i<n;i++)
        {
            if(s[i]==0)
            {
                a=0;
                b=i;
                break;
            }
            else{
                if(h[s[i]]!=-1)
                {
                    a=h[s[i]]+1;
                    b=i;
                    break;
                }
                else h[s[i]]=i;
            }
        }
        printf("%d\n",b-a+1);
        for(int i=a;i<=b;i++)printf("%d\n",arr[i]);
    }
    return 0;
}
View Code

相关文章: