题目链接:
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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-30 10:24:52