您的位置:首页 > 其它

poj 3370(抽屉原理)

2016-02-28 09:25 429 查看
【题目大意】:给出n个数,叫你从中选出任意个数,使得这些数的和是c的倍数。

【解题思路】:下午这道题被拿去当了选拔赛的题目。做的时候总觉得貌似在哪里见过,然后再那里没事%c搞啊搞啊,越搞越觉得像抽屉原理。。。。。然后,没错,就是你了。。。抽屉原理。

【抽屉原理】:原理1 把多于n个的物体放到n个抽屉里,则至少有一个抽屉里的东西不少于两件;

原理2 把多于mn(m乘以n)个的物体放到n个抽屉里,则至少有一个抽屉里有不少于m+1的物体。

原理3 把无穷多件物体放入n个抽屉,则至少有一个抽屉里 有无穷个物体。.

原理 4 把(mn-1)个物体放入n个抽屉中,其中必有一个抽屉中至多有(m—1)个物体。

整数问题:把所有整数按照除以某个自然数m的余数分为m类,叫做m的剩余类或同余类,用[0],[1],[2],…,[m-1]表示.每一个类含有无穷多个数,例如[1]中含有1,m+1,2m+1,3m+1,….在研究与整除有关的问题时,常用剩余类作为抽屉.根据抽屉原理,可以证明:任意n+1个自然数中,总有两个自然数的差是n的倍数。(证明:n+1个自然数被n整除余数至少有两个相等(抽屉原理),不妨记为m=a1*n+b
n=a2*n+b,则m-n整除n)。

所以,对于这道题而言。c<=n的,我们求出数字的前n项和之后,对于每一个和%c,则有根据抽屉原理必有两个数的余数相等。也就是说一定有两个的和是相等的。也就是说,在这中间的数的和是可以被c整除的。。。。。。

下午做的时候,没想到这样O(n)在G++一直TLE...还要开输入挂才过!!!

[cpp] view
plain copy

print?

#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <vector>

#include <queue>

#include <cmath>

#include <string>

#include <cctype>

#include <map>

#include <iomanip>

using namespace std;

#define eps 1e-8

#define pi acos(-1.0)

#define inf 1<<30

#define pb push_back

#define lc(x) (x << 1)

#define rc(x) (x << 1 | 1)

#define lowbit(x) (x & (-x))

#define ll long long

int a[100500];

int sum[100500],cnt[100500];

int n, c;

int getint(){

char c=getchar();

int t=0;

while (c<'0' || c>'9') {

c=getchar();

}

while (c>='0' && c<='9') {

t=t*10+c-'0';

c=getchar();

}

return t;

}

int main() {

while(~scanf("%d%d",&c,&n)) {

if(c==0 && n==0) break;

sum[0]=0;

int l,r;

memset(cnt,-1,sizeof(cnt));

for(int i=1; i<=n; i++) {

a[i]=getint();

sum[i]=(sum[i-1]+a[i])%c;

}

for (int i=1; i<=n; i++){

if(cnt[sum[i]]==-1) cnt[sum[i]]=i;

else {

l=cnt[sum[i]];

r=i;

break;

}

}

if(cnt[0]!=-1){

for(int i=1; i<=cnt[0]; i++)

printf("%d ",i);

printf("\n");

} else if(l!=-1) {

for(int i=l+1; i<=r; i++)

printf("%d ",i);

printf("\n");

} else printf("no sweets\n");

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: