UVA11237 Halloween treats (鸽巢原理)

题目链接: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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值