这题用抽屉原理写起来真的很简单,从中也明白数学的重要性。
几个抽屉原理如下:
原理1 把多于n个的物体放到n个抽屉里,则至少有一个抽屉里的东西不少于两件;
原理2 把多于mn(m乘以n)个的物体放到n个抽屉里,则至少有一个抽屉里有不少于m+1的物体。
原理3 把无穷多件物体放入n个抽屉,则至少有一个抽屉里 有无穷个物体。.
原理 4 把(mn-1)个物体放入n个抽屉中,其中必有一个抽屉中至多有(m—1)个物体。
这题的题意很简单,就是求出哪些数加起来能够被某个数整除。我们知道一个整数n有n个同余类,这n个同余类就可以看做n个抽屉,而题目中给出c<=n,再加上0,那么就有n+1个数,大于c,由原理1可以知道一定存在这样的整数,满足题意。因为至少有两个数的余数相同,那么两者相减之后一定能被c整除。
因此我们可以用一个mod[i]数组来记录从0到i所有整数的和%c的值,这样,当mod[i]=0或者mod[i]=a之前出现过,那么就可以得出,从之前出现的那个数开始的下一个数到i为止的数加起来一定能被c整除,例如:如果mod[2]=1,并且mod[5]=1,那么从3到5这三个数加起来一定能够被c整除。
#include<cstdio>
#include<cstring>
const int N=100005;
int sweet[N],mod[N];
bool isok[N];
int main()
{
int c,n;
while(scanf("%d%d",&c,&n))
{
if(c==0&&n==0)
break;
memset(isok,false,sizeof(isok));
sweet[0]=0,mod[0]=0;
long long sum=0;//这里要注意,不能用int。
for(int i=1;i<=n;i++)
{
scanf("%d",&sweet[i]);
sum+=sweet[i];
mod[i]=sum%c;
}
int start=0;
for(int i=n;i>=0;i--)
{
if(isok[mod[i]])
{
start=i;
break;
}
isok[mod[i]]=true;
}
//printf("start=%d\n",start);
int e=start+1;
while(true)
{
printf("%d ",e);
e++;
if(mod[start]==mod[e])
break;
}
printf("%d\n",e);
}
return 0;
}