鸽巢原理又称抽屉原理
基本原理: n+1只鸽子飞回n个鸽笼,至少有一个鸽笼含有2只
他的数学描述语言为:
m个元素分成n组,那么总有一组至少含有元素个数为 [m/n]
设a1,a2,a3,....am是正整数的序列,试证明至少存在整数k,l, (1=<k<l<=m)
使得和 a(k+1)+a(k+2)+...+a(l)是m的倍数
证明略,但是可以从构造和数列入手,两个余数相同的数相减可以被除数整除
万圣节恶作剧:
在万圣节这天每个小孩都会挨家挨户要糖果,但是邻居们只想给出一定数量的糖果,如果你去的很晚
可能要不到糖果,所以孩子们决定把所有要来的糖放在一起,然后平均分摊,按以往的经验孩子们知道每个用户
会给出多少糖,由于他们更关心要来的糖能否平分,所以他们只选择了一部分住户,这样糖会被平分
又不会有糖果剩下。
输进c和n,c是小孩的个数,n是住户的个数(1<=n<=100 000)
接下来有n个数,分别为住户给出的糖果数ai(1=<ai<=100 000)。
以0 0为标志结束。
对于每组数据,输出孩子们选择的住户的编号,如果有多组,只输出一组即可
否则,输出"no sweets"
#include<iostream> #include<algorithm> using namespace std; int main(){ int c,n,sum,k,l,m; int a[100001],S[100001]; while(cin>>c>>n){ if(c==0&&n==0) break; memset(a,0,sizeof(a)); memset(S,0,sizeof(S)); sum=0; m=-1; for(int i=1;i<=n;i++){ cin>>a[i]; sum+=a[i]; if(sum%c==0&&m==-1) m=i; } if(m==-1){ S[n]=sum; //寻找两个mod n相等的Si for(int i=n-1;i>=1;i--) S[i]=S[i+1]-a[i+1]; for(int i=1;i<=n;i++) S[i]%=c; for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ if(S[i]==S[j]){ k=i; l=j; break; } } } for(int i=k+1;i<=l;i++) cout<<i<<" "; } else{ //在累加和的时候就找到啦 for(int i=1;i<=k;i++) cout<<i<<" "; cout<<endl; } } return 0; }