poj3370 抽屜原理

poj3370:http://poj.org/problem?id=3370

題意:給出兩個數c和n,還有n個數,從n個數中找出任意一個組合,使得該組合數的和是c的倍數。

思想:抽屜原理(http://baike.baidu.com/view/8899.htm#5),創建c個抽屜,每個抽屜分別對應任意數除以c的餘數(即模)0~c-1。從第一個組合數開始求和,分別對c求餘。

比如

4    5

1   2  3  7  5

 

求和爲1  3  6  13   18

和對c求餘爲1  3  2  1  2

當出現兩個相同的數字時,就存在答案,答案爲第一個重複數後面開始,到第二個重複數結束(3  2  1)。或者當出現的數字爲0時,答案也存在。由於c<=n,c的餘數有c個(包括0),n個和求餘數的答案最少也有c個,所以必定存在0或者重複數。

 

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct aa
{
	int x;
	int ind;
}res[100200];
int num[100200];
int check[100200];
int no[100200];

int cmp(const void *a,const void *b)
{
	struct aa *c=(aa *)a,*d=(aa *)b;
	if(c->x==d->x)
		return c->ind-d->ind;
	return c->x-d->x;
}
int main()
{
	int i,j,n,c,t;
	__int64 m;
	while(scanf("%d%d",&c,&n)>0)
	{
		if(c==0&&n==0)
			break;
		memset(res,0,sizeof(res));
		memset(check,0,sizeof(check));
		memset(no,-1,sizeof(no));

		for(i=1,m=0;i<=n;i++)
		{
			scanf("%d",&num[i]);
			m+=num[i];
			res[i].x=m%c;
			res[i].ind=i;
		}
		for(i=1;i<=n;i++)
			if(res[i].x==0)
			{
				for(j=1;j<=res[i].ind;j++)
					printf("%d ",j);
				printf("\n");
				break;
			}
			else
				if(check[res[i].x]==1)
				{
					for(j=no[res[i].x]+1;j<=res[i].ind;j++)
						printf("%d ",j);
					printf("\n");
					break;
				}
				else
				{check[res[i].x]=1;no[res[i].x]=i;}
		
	}
	return 0;
}


 

發佈了12 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章