POJ 3370 鸽巢原理

这个题要知道一个定理。

给定m个数,a1,a2,a3,.....am,至少存在整数k,l,(1<=k<l<=m)使得ak+....+al是m的倍数。

构造前缀和:

s1=a1;

s2=a1+a2;

s3=a1+a2+a3;

...

sm=a1+a2+...+am;

(1)如果有一个sn是m的倍数,则定理得证。

(2) 如果在上面没有一个是m的倍数。令rh=Sh%m

其中,h=1,2,.....m,则所有rh均小于m,根据鸽巢定理可知至少存在一对rk,rh,满足rk==rh

即 Sk ≡ Sh % m

不过我写的G++TLE,C++AC

#include<cstdio>
#include<algorithm>

using namespace std;

const int maxn=1e5+10;

struct node{
	int r,h;
}p[maxn];

bool cmp(const node& a,const node& b){
	if(a.r==b.r) return a.h<b.h;
	return a.r<b.r;
}

int main(){
    int c,n;
    while(scanf("%d%d",&c,&n)!=EOF&&(c||n)){
        long long sum=0;
        int a;
        int k=-1;
        for(int i=1;i<=n;i++){
            scanf("%d",&a);
            sum+=a;
            p[i].r=sum%c;
            p[i].h=i;
            if(k==-1&&p[i].r==0) k=i;
        }
        int l,r;
        if(k==-1){
            sort(p+1,p+1+n,cmp);
            for(int i=1;i<n;i++){
                if(p[i].r==p[i+1].r){
                    l=p[i].h+1;
                    r=p[i+1].h;
                    k=l;
                    break;
                }
            }
        }else{
            l=1;r=k;
        }
        if(k==-1){
            printf("no sweets\n");
        }else{
            for(int i=l;i<=r;i++){
                if(i!=l) printf(" ");
                printf("%d",i);
            }
            puts("");
        }
    }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40679299/article/details/82794061