UVA11237 Halloween treats (鴿巢原理)

bigbigship發表於2014-08-18

題目連結:http://vjudge.net/vjudge/problem/viewProblem.action?id=34693

鴿巢原理:m(m>=1)個元素分成n組,那麼總有一個組至少含有元素個數為[m/n],  "[ ]"向上取整

引例:

設a1,a2,.....am是正整數的序列,試證明至少存在整數k,l   1<=k<l<=m使得和 ak+ak+1+.....al是m的倍數

證明:

構造一個序列S1=a1,S2=a1+a2,...Sm=a1+a2+......+am;

(1) 若有個Sn為m的倍數則一定存在

(2)若沒有一個Sn為m的倍數設Rh=S%m,h=1,2,3,4,......m,得到R的序列 R1,R2,,,,,,,Rm且都不為0且小於m,根據鴿巢原理,m個餘數在區間[1,m-1]裡取值至少存在一堆Rh,Rk相等,即Sk=Sh(mod m)

設 h>k

Sh-Sk=ak+1+ak+2+........+ah = 0(mod m);

此題程式碼如下:

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

const int maxn = 100001;

typedef long long LL;

int nei[maxn];

struct s{
    int h,r;
    bool operator <(const s &b) const{
        if(this->r==b.r)
            return this->h < b.h;
        return this->r<b.r;
    }
}R[maxn];

int main()
{
    int c,n;
    while(~scanf("%d%d",&c,&n)){
        if(n==0&&c==0)
        break;
        LL sum=0;
        int num=-1;
        for(int i=0;i<n;i++){
            scanf("%d",&nei[i]);
            sum+=nei[i];
            R[i].r=sum%c;
            R[i].h=i+1;
            if(num==-1&&R[i].r==0)
                num=i;
        }
        int e;
        if(num==-1){
            sort(R,R+n);
            for(int i=0;i<n-1;i++){
                if(num==-1&&R[i].r==R[i+1].r){
                    num=R[i].h;
                    e=R[i+1].h;
                    break;
                }
            }
            if(num==-1){
                puts("no sweets");
                continue;
            }
            for(int i=num+1;i<e;i++)
                printf("%d ",i);
            printf("%d\n",e);
        }
        else{
            for(int i=0;i<num;i++)
                printf("%d ",i+1);
            printf("%d\n",num+1);
        }
    }
    return 0;
}


相關文章