标签:鸽巢原理
http://poj.org/problem?id=2356
从n个数里面取出一些数,这些数的和是n的倍数。并输出这些数。
先预处理出前n个数的和用sum[i]表示前i个数的和。若某个sum[i]是n的倍数,直接输出前i个数即可。
否则说明n个数中对n取余的结果有n-1种,即余数为(1~n-1),根据鸽巢原理知必定至少存在两个sum[i]与sum[j]对n取余的结果相等。那么i+1 ~ j之间的数之和一定是n的倍数。
#include <stdio.h> #include <iostream> #include <map> #include <set> #include <list> #include <stack> #include <vector> #include <math.h> #include <string.h> #include <queue> #include <string> #include <stdlib.h> #include <algorithm> #define LL long long #define _LL __int64 #define eps 1e-12 #define PI acos(-1.0) using namespace std; const int maxn = 10010; int main() { int n; int a[maxn]; int sum[maxn]; int hash[maxn]; while(~scanf("%d",&n)) { for(int i = 1; i <= n; i++) scanf("%d",&a[i]); sum[0] = 0; int i,flag = 0; memset(hash,-1,sizeof(hash)); for(i = 1; i <= n; i++) { sum[i] = (sum[i-1]+a[i])%n; if(sum[i] == 0) { flag = 1; break; } } if(flag == 1) { printf("%d\n",i); for(int j = 1; j <= i; j++) printf("%d\n",a[j]); continue; } //for(int i = 1; i <= n; i++) //printf("sumi : %d\n",sum[i]); int s,t; for(int i = 1; i <= n; i++) { if(hash[sum[i]] == -1) hash[sum[i]] = i; else { s = hash[sum[i]]; t = i; break; } } printf("%d\n",t-s); for(int i = s+1; i <= t; i++) { printf("%d\n",a[i]); } } return 0; }
与上题类似。只不过是取若干个数的和是m的倍数。跑一遍循环刚好,边哈希sum[i],边判断sum[i]是否等于0,一旦为0就输出,否则直到找到两个相等的sum[i]和sum[j],输出i~j即可。
#include <stdio.h> #include <iostream> #include <map> #include <set> #include <list> #include <stack> #include <vector> #include <math.h> #include <string.h> #include <queue> #include <string> #include <stdlib.h> #include <algorithm> #define LL long long #define _LL __int64 #define eps 1e-12 #define PI acos(-1.0) using namespace std; const int maxn = 100010; int n,m; int a[maxn]; int sum[maxn]; int hash[maxn]; int flag; int s,t; int main() { while(~scanf("%d %d",&m,&n)) { if(m == 0 && n == 0) break; sum[0] = 0; flag = 0; memset(hash,-1,sizeof(hash)); for(int i = 1; i <= n; i++) { scanf("%d",&a[i]); if(flag) continue; sum[i] = (sum[i-1]+a[i])%m; if(sum[i] == 0) { flag = 1; for(int j = 1; j <= i; j++) { printf("%d",j); if(j == i) printf("\n"); else printf(" "); } } else { if(hash[sum[i]] == -1) hash[sum[i]] = i; else { for(int j = hash[sum[i]]+1; j <= i; j++) { printf("%d",j); if(j == i) printf("\n"); else printf(" "); } flag = 1; } } } } return 0; }
标签:鸽巢原理
原文地址:http://blog.csdn.net/u013081425/article/details/38520267