poj 2356 (抽屉原理)

题目链接:http://poj.org/problem?id=2356

题目大意:给你n个数,要你从n个数选出若干个数,要求这若干个数的和是n的倍数,输出选择数的个数,以及相应的数。

解题思路:

以下摘自博客:https://www.cnblogs.com/pengwill/p/7367031.html

二、鸽巢原理(抽屉原理)

基本描述

桌子上有是个苹果,把这十个苹果放到九个抽屉里,无论怎么放,我们会发现至少会有一个抽屉里面至少放两个苹果。这一现象就是所说的“抽屉原理”。
更一般的表述:如果每一个抽屉代表一个集合,每一个苹果就可以代表一个元素。加入有n+1个元素放到n个集合中去,其中必定有一个集合里至少有两个元素。

第一抽屉原理

原理1

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

原理2

把多余mn+1(n不为0)个物体放到n个抽屉里面,则至少有一个抽屉里面不少于(m+1)的物体。

第二抽屉原理

把(mn -1 )个物体放入n个抽屉中,其中必须有一个抽屉不多余(m-1)个物体。
如将3*5-1 = 14个物体放入5个抽屉中,则必定有一个抽屉中的物体数目少于3-1=2.

举例

属相问题

属相有12个,那么任意37个人中,至少有几个人属相相同?

上取整(37 / 12) = 4

招聘问题

有300人到招聘会求职,其中软件设计有100人,市场营销有80人,财务管理有70人,人力资源管理有50人。那么至少有多少人找到工作才能保证一定有70人找的工作专业相同?

考虑最差情况,即软件设计,市场营销,财务管理均招了69人,人力资源管理招了50人,此时再多招1人,就有70人找的工作专业相同了。
故答案为 69*3 + 50 + 1 = 258

衬衫问题

一个抽屉里有20件衬衫,其中4件是蓝的,7件是灰的,9件是红的,则应从中随意取出多少件才能保证有5件是同颜色的?

考虑最差情况,即已经取出了4件蓝色,4件灰色,4件红色,再多取出1件就满足条件。
故答案为 4 + 4 + 4 + 1 = 13

 

首先我们可以分别求出这n个数的前缀和,sum[1],sum[2],……,sum[n];如果当中有n的倍数,则直接输出就好了。

否则sum[1]%n,sum[2]%n,……,sum[n]%n,这n个数必定在区间[1,n-1]之间,这就相当于有n个物品和n-1个抽屉,根据第一抽屉原理可得,必定存在i,j,假设i<j,使得sum[i]%n=sum[j]%n,则(sum[j]-sum[i])%n=0。输出答案只要出j-i,和a[i+1],a[i+2]……a[j]就可以了。

代码:

#include<iostream>
using namespace std;
typedef long long ll;
ll n,a[100005],sum[100005],pos[100005];
//pos[i]记录sum[i]%n是否出现过,如果以出现,则标记为出现的初始位置
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum[i]=sum[i-1]+a[i];
    }
    for(int i=1;i<=n;i++){
        if(sum[i]%n==0){
            cout<<i<<endl;
            for(int j=1;j<=i;j++)cout<<a[j]<<endl;
            break;
        }
        if(pos[sum[i]%n]){
            cout<<i-pos[sum[i]%n]<<endl;
            for(int j=pos[sum[i]%n]+1;j<=i;j++)cout<<a[j]<<endl;
            break;
        }
        pos[sum[i]%n]=i;
    }
    return 0;
}

 

posted @ 2019-03-07 23:06  两点够吗  阅读(614)  评论(0编辑  收藏  举报