HDU 1205:吃糖果 ← 鸽巢原理

【题目来源】
http://acm.hdu.edu.cn/showproblem.php?pid=1205

【题目描述】
HOHO,终于从Speakless手上赢走了所有的糖果,是Gardon吃糖果时有个特殊的癖好,就是不喜欢将一样的糖果放在一起吃,喜欢先吃一种,下一次吃另一种,这样;可是Gardon不知道是否存在一种吃糖果的顺序使得他能把所有糖果都吃完?请你写个程序帮忙计算一下。

【输入格式】
第一行有一个整数T,接下来T组数据,每组数据占2行,第一行是一个整数N(0<N<=1000000),第二行是N个数,表示N种糖果的数目Mi(0<Mi<=1000000)。

【输出格式】
对于每组数据,输出一行,包含一个"Yes"或者"No"。

【输入样例】
2
3
4 1 1
5
5 4 3 2 1

【输出样例】
No
Yes

【算法分析】

鸽巢原理(Pigeonhole Principle),或称抽屉原理(Drawer Principle)。
鸽巢原理常见的两种表述如下所述:
● 将 n+1 个物体,划分为 n 组,那么有至少一组有两个(或以上)的物体。
● 将 n 个物体,划分为 k 组,那么至少存在一个分组,含有大于或等于 \left \lceil \frac{n}{k} \right \rceil 个物品。

本题是鸽巢原理的典型应用:若设数量最多的某种糖果数为 N,其他糖果总数为 S。若视 N 个糖果为 N 个隔板,并把每个隔板的右边看成一个空间,则可隔成 N 个空间。

S<N-1(也即,N>S+1),则至少有两个隔板之间没有糖果,而隔板代表同一种糖果,故无解。
S>=N-1(也即,N<=S+1),肯定有解。

依据一种取巧的方法,“若整数位数超过10位,就选择用
long long 型”。故本题中的若干变量不定义为 int 型,而定义为 long long 型,因为计算过程中,极大可能会超过 10 位数。

【算法代码】

#include <iostream>
using namespace std;

typedef long long LL;
LL imax,sum;
LL n,x;

int main() {
    LL T;
    scanf("%lld",&T);
    while(T--) {
        imax=0;
        sum=0;
        scanf("%lld",&n);
        while(n--) {
            scanf("%lld",&x);
            if(imax<x) imax=x;
            sum+=x;
        }
        sum-=imax;
        if(imax<=sum+1) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}


/*
in:
2
3
4 1 1
5
5 4 3 2 1

out:
No
Yes
*/






【参考文献】
https://blog.csdn.net/blue_skyrim/article/details/46126049
https://blog.csdn.net/weixin_45696704/article/details/114483453

https://zhuanlan.zhihu.com/p/661206530







 

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值