POJ2356 Find a multiple【鸽巢原理】

来源:互联网 发布:霸气 知乎 编辑:程序博客网 时间:2024/05/18 15:56

题目链接:

http://poj.org/problem?id=2356


题目大意:

给你N个正数的序列,从中找到连续的若干数,使得其和刚好是N的倍数。


解题思路:

典型的抽屉原理。

Sum[i]为序列中前i项的和。则有两种可能:

1.若有Sum[i]是N的倍数,则直接输出前i项。

2.如果没有任何的Sum[i]是N的倍数,则计算ri = Sum[i] % N。根据鸽巢原理,

定有Sum[i] % N == Sum[j] % N,i != j。则第 j 到第 i 项数的和即为N的倍数。


AC代码:

//未优化的代码,172ms#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;int Sum[10010],A[10010];int main(){    int N;    while(~scanf("%d",&N))    {        memset(Sum,0,sizeof(Sum));        for(int i = 1; i <= N; ++i)        {            scanf("%d",&A[i]);            Sum[i] = (Sum[i-1] + A[i]) % N;        }        int Flag = 0;        for(int i = 1; i <= N; ++i)        {            if(Sum[i] % N == 0)            {                printf("%d\n",i);                for(int j = 1; j <= i; ++j)                    printf("%d\n",A[j]);                Flag = 1;            }            else            {                for(int j = 1; j < i; ++j)                {                    if(Sum[i] == Sum[j])                    {                        printf("%d\n",i-j);                        for(int k = j+1; k <= i; ++k)                            printf("%d\n",A[k]);                        Flag = 1;                        break;                    }                }            }            if(Flag)                break;        }    }    return 0;}

//优化后代码,0ms#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;int Sum[10010],A[10010],Mod[10010];int main(){    int N,Left,Right;    while(~scanf("%d",&N))    {        memset(Mod,-1,sizeof(Mod));        memset(Sum,0,sizeof(Sum));        Mod[0] = 0;        for(int i = 1; i <= N; ++i)        {            scanf("%d",&A[i]);            Sum[i] = (Sum[i-1] + A[i]) % N;            if(Mod[Sum[i]] == -1)            {                Mod[Sum[i]] = i;            }            else            {                Left = Mod[Sum[i]];                Right = i;            }        }        printf("%d\n",Right-Left);        for(int i = Left + 1; i <= Right; ++i)            printf("%d\n",A[i]);    }    return 0;}


0 0
原创粉丝点击