鸽巢原理入门
题目传送门:点击打开链接
Find a multiple
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 7055 | Accepted: 3086 | Special Judge |
Description
The input contains N natural (i.e. positive integer) numbers ( N <= 10000 ). Each of that numbers is not greater than 15000. This numbers are not necessarily different (so it may happen that two or more of them will be equal). Your task is to choose a few of
given numbers ( 1 <= few <= N ) so that the sum of chosen numbers is multiple for N (i.e. N * k = (sum of chosen numbers) for some natural number k).
Input
The first line of the input contains the single number N. Each of next N lines contains one number from the given set.
Output
In case your program decides that the target set of numbers can not be found it should print to the output the single number 0. Otherwise it should print the number of the chosen numbers in the first line followed by the chosen numbers themselves (on a separate
line each) in arbitrary order.
If there are more than one set of numbers with required properties you should print to the output only one (preferably your favorite) of them.
If there are more than one set of numbers with required properties you should print to the output only one (preferably your favorite) of them.
Sample Input
5 1 2 3 4 1
Sample Output
2 2 3
Source
先引入鸽巢原理概念:
鸽巢原理,又名狄利克雷抽屉原理、鸽巢原理。
其中一种简单的表述法为:若有n个笼子和n+1只鸽子,所有的鸽子都被关在鸽笼里,那么至少有一个笼子有至少2只鸽子。
百度鸽巢原理视频,竟然所有的都是为了小学生准备的,真是欲哭无泪!
本题的意思很简单,给n个数,从中任意选出若干个数,求和,要求其满足是n的倍数。这里说明一下,任意n个数是必然能够找的到若干个数求其和满足整除n。证明:从第一个数开始依次求和保存于Sk中,那么S1到Sn mod n在1-n之间,根据鸽巢原理得知必然有两个Si、Sj mod n的结果相同,则(Sj%n)==(Si%n)==>(Sj-Si)%n == 0即可求出题中所述结果。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <algorithm> #include <stack> #include <set> using namespace std; typedef long long int LL ; int a[10010]; LL s[10010]; //求和数组结果 int b[10010]; //保存其和余数 int c[10010]; //标记数组 int main() { int n; cin >> n; memset(a, 0, sizeof(a)); for (int i = 1; i<=n; i++) cin >> a[i]; memset(s, 0, sizeof(s)); for (int i = 1; i<=n; i++) { //扫描求和,若遇到满足答案则结束 s[i] = s[i-1] + a[i]; if (s[i] %n == 0) { cout << i<< endl; for (int j = 1; j<=i; j++) cout << a[j]<< endl; return 0; } //cout << s[i]<< endl; } //cout << endl; memset(b, 0, sizeof(b)); memset(c, 0, sizeof(c)); int flag = 1; int i; for (i = 1; i<=n && flag; i++) { //求和取余保存 b[i] = s[i] %n; c[b[i]] ++ ; //cout << b[i]<< endl; if (c[b[i]] > 1) { break; flag = 0; ; } } //cout << i<< endl; int j; for (j = 1; j<=n; j++) { if (b[j] == b[i]) break; } //cout << j<< endl; cout << i-j<< endl; for (int k = j+1; k<=i; k++) cout << a[k] << endl; return 0 ; }
积累!!积累、思考、总结、坚持