poj 2356 & poj 3370 鸽笼原理

题意:有n个数,从中取连续的一段,使其和为n的倍数。 3370求的是部分和为c的倍数(c<=n)。

分析:设前k个数的和 S(k)=a1+a2+...+ak,若S(k)为n的倍数,输出前k个数即可。否则 n 个 S(k) 除以 n 的余数只能有1,2,3...n-1,这(n-1)种情况,由鸽笼原理知,必有两个不同的和S(i)和S(j)   (i<j)除以n的余数相同 ,故部分和S(j)-S(i) = ai+1+...+aj是n的倍数。

 

 poj 2356

const int M = 10005;
int n, s;
int a[M], b[M];

int main(){
    #ifndef ONLINE_JUDGE
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    #endif

    scanf("%d", &n);
    FOE(i, 1, n) scanf("%d", &a[i]);
    s = 0;
    b[0]=0;
    FOE(i, 1, n) {
        s = (s+a[i]) % n;
        if(s && b[s]==0) b[s]=i;
        else {
            printf("%d\n", i-b[s]);
            FOE(j, b[s]+1, i) printf("%d\n", a[j]);
            break;
        }
    }

    return 0;
}

 

poj 3370

const int M = 100005;
int n, c, s;
int a[M], b[M];

int main(){
    #ifndef ONLINE_JUDGE
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    #endif
    
    while(scanf("%d%d", &c, &n), c){
        //memset(b, 0, sizeof b);
        FOE(i, 1, n) {scanf("%d", &a[i]); b[i]=0;}
        s = 0; b[0]=0;
        FOE(i, 1, n) {
            s = (s+a[i]) % c;
            if(s && b[s]==0) b[s]=i;
            else {
                FOE(j, b[s]+1, i) printf("%d ", j); 
                printf("\n");
                break;
            }
        }
    }
    
    return 0;
}

 

 

posted @ 2013-05-23 20:49  心向往之  阅读(135)  评论(0编辑  收藏  举报