鸽巢定理(21.9.26)

一、鸽巢定理(抽屉定理)

把n+1个物体放进n个盒子,至少一个盒子包含两个或更多的物体。

进一步考虑,把n个物体放进m个盒子,至少有一个盒子包含 [(n-1)/m]+1 个或更多的物体。

举个例子:任取8个自然数,必有两个数的差是7的倍数。

我们知道,如果两个整数a、b,它们除以自然数m的余数相同,那么它们的差a-b是m的倍数。所以,题目就变成了任取8个自然数,其中有两个自然数除以7的余数相同。这样就可以根据余数的不同分成7个盒子,即余数是0,1,2,3,4,5,6,7。任取八个自然数放进7个盒子,至少一个盒子中有两个数余数一样。

二、例题

Problem - 1205

题意:Gardon吃糖,不喜欢将一样的糖果放在一起吃,喜欢先吃一种,下一次吃另一种,是否存在一种吃糖果的顺序使得他能把所有糖果都吃完?

分析:可以考虑隔板法,把数量最多的一种糖果做为隔板,比如最多的糖果数为n,则可以分成n+1个空间,因为其余种类的糖果数一定小于n,所以可以把同种糖果放入不同的空间,但是,如果剩余的糖果数小于n-1,(这里只考虑隔板围起来的部分,不考虑两头),必然有空间没有放糖果,造成最多数量的那种糖果有相邻的情况,不符合题意。记糖果总数为sum,只有sum-n>=n-1时,才符合题意。

#include<iostream>
#include<algorithm>
using namespace std;

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        long long int n,sum=0,maxx=-1,a;
        cin>>n;
        for(int i=0; i<n; i++)
        {
            cin>>a;
            sum+=a;
            maxx=max(maxx,a);
        }
        if(sum-maxx>=maxx-1)
            cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
}

Problem - B - Codeforces

题意:已知字符a,b,c的数量,是否可以组成一个字符串,仅有m对相邻的字符相同。

分析:已知n个相同的字符组成的字符串有n-1对相邻的字符相同,如果字符a,b,c不随机组合,同a同b同c的相邻,则m最大为(a-1+b-1+c-1)对,即a+b+c-3对。

求m的最小值,考虑抽屉定理,找最多的字符,比如a为最多的字符,a做隔板,如果(a-1)-(b+c)>0则一定有相邻的a(如上题吃糖),并且(a-1)-(b+c)就是最小的m,因为m大于等于0,所以m的最小值应该为max(0,a-1-b-c)。不难理解,求m的最小值,就是尽可能让字符组合,多出来的部分放在两头(隔板中间为空)。

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int a[3],m;
    int t;
    cin>>t;
    while(t--)
    {
        cin>>a[0]>>a[1]>>a[2]>>m;
        sort(a,a+3);
        int sum=a[0]+a[1]+a[2],maxx,minn;
        maxx=sum-3;
        minn=max(0,a[2]-1-(a[0]+a[1]));
        if(m>=minn&&m<=maxx)
            cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_51443397/article/details/120483239