1. 程式人生 > >抽屜原理的妙用

抽屜原理的妙用

Find a multiple
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 3089 Accepted: 1370 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.

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

剛開始時是因為第一次做這題,程式碼寫的過長,實際上第一種情況和第二種情況可以算一種情況考慮,關於簡化後的的程式碼可以參考

參考程式碼:

複製程式碼
 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中,值為此時的i44         }
45     }
46     return 0;
47 }
複製程式碼