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