从poj2356来体会 抽屉原理 的妙用
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 3089 | Accepted: 1370 | Special Judge |
Description
Input
Output
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
题目大意就是先给出一个数N,接着再给出N个数,要你从这N个数中任意选择1个或多个数,使得其和是N的倍数
如果找不到这样的答案 则输出0
答案可能有多个,但智勇任意输出一个解就行。
输出的第一行是选择元素的个数M,接着M行分别是选择的元素的值
刚开始的时候并不同为什么这一题回事抽屉原理,分析后才明白,昨晚后更有体会
实际上此题一定有解,不存在输出0的结果
证明如下
我们可以依次求出a[0],a[0]+a[1],a[0]+a[1]+a[2],......,a[0]+a[1]+a[2]...+a[n];
假设分别是sum[0],sum[1],sum[2],......,sum[n]
如果在某一项存在是N的倍数,则很好解,即可直接从第一项开始直接输出答案
但如果不存在,则sum[i]%N的值必定在[1,N-1]之间,又由于有n项sum,有抽屉原理:
把多于n个的物体放到n个抽屉里,则至少有一个抽屉里有2个或2个以上的物体。
则必定有一对i,j,使得sum[i]=sum[j],其中i!=j,不妨设j>i
则(sum[j]-sum[i])%N=0,故sum[j]-sum[i]是N的倍数
则只要输出从i+1~j的所有的a的值就是答案
然后就利用这个思路就可以直接的解出该题的答案
刚开始时是因为第一次做这题,代码写的过长,实际上第一种情况和第二种情况可以算一种情况考虑,关于简化后的的代码可以参考
http://www.cnblogs.com/ACShiryu/archive/2011/08/09/poj3370.html
参考代码:
1 #include<iostream>
2 #include<cstdlib>
3 #include<cstdio>
4 #include<cstring>
5 #include<algorithm>
6 #include<cmath>
7 using namespace std;
8 int a[10000] ;
9 int mod[10000] ;//mod存储判断sum%n是否出现过,如果没出现时-1,如果出现,则是此时sum对应的k值,即前k项和
10 int sum [10001];//sum存储的与描述略有不同,sum[k]=a[0]+a[1]+...+a[k-1];
11 int main()
12 {
13 int n ;
14 int i ;
15 while ( cin >> n )
16 {
17 memset ( mod , -1 , sizeof ( mod ) ) ;
18 sum[0]=0;
19 for ( i = 0 ; i < n ; i ++ )
20 {
21 cin >> a[i] ;
22 }
23 for ( i = 0 ; i < n ; i ++ )
24 {
25 sum[i+1]=sum[i]+a[i];
26
27 if ( sum [i+1] % n == 0 )
28 {//如果是N的倍数,则输出
29 int j ;
30 cout<<i+1<<endl;
31 for ( j = 0 ; j <= i ; j ++ )
32 cout<<a[j]<<endl;
33 break;
34 }
35 if ( mod[sum [i+1] % n]!=-1)
36 {//如果找到两个数的余数相同,则依次输出
37 int j ;
38 cout<<i-mod[sum [i+1] % n]<<endl;
39 for ( j = mod[sum [i+1] % n]+1 ; j <= i ; j ++ )
40 cout<<a[j]<<endl;
41 break;
42 }
43 mod[sum [i+1] % n]=i;//将此时对应的余数存到mod中,值为此时的i
44 }
45 }
46 return 0;
47 }
作者:ACShiryu
出处:http://www.cnblogs.com/ACShiryu/
若非注明,本博客文章均为原创,版权归作者和博客园共有,欢迎转载,但必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。
该文章也同步发布在我的新浪微博中-ACShiryu's weibo,欢迎收听。