[POJ 2356]Find a multiple(抽屉原理)

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

Source

Ural Collegiate Programming Contest 1999

题目大意:给定一个含有N个数字的序列x1...xN,要找其中一个连续子序列xi...xj,使得Σxt%N=0,t∈[i,j]

搞过高中数学竞赛的应该这题都有思路,一个典型的抽屉原理问题,将前i个数之和mod N的结果记作sum[i],然后以sum数组构造抽屉drawer数组,drawer数组保存的是最先出现的sum[i]的下标i,当sum的一个元素第二次放入重复的抽屉时,输出结果,需要注意的是输出的一点小小问题,刚开始drawer应全部重置为-1,drawer[0]=0,这样的话若碰到所有的数中任何子序列之和mod N均不等于0,而所有数之和mod N恰好等于0,这样不会出现一个抽屉重复放入元素,如果处理不当可能WA

//抽屉原理
//以余数构造抽屉
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

#define MAXN 10100

using namespace std;

int in[MAXN],sum[MAXN],N;
int drawer[MAXN]; //drawer[i]>0表示已经存在了一个sum[x],sum[x]%N=i,drawer[i]=那个最早的x编号

int main()
{
    memset(drawer,-1,sizeof(drawer));
    in[0]=0,sum[0]=0,drawer[0]=0;
    cin>>N;
    for(int i=1;i<=N;i++)
    {
        cin>>in[i];
        sum[i]=(sum[i-1]+in[i])%N;
    }
    for(int i=1;i<=N;i++)
    {
        if(drawer[sum[i]]==-1) drawer[sum[i]]=i;
        else //找到了一段符合题意的连续的序列[x,y],|sum[x]-sum[y]|%N=0
        {
            cout<<(i-drawer[sum[i]])<<endl;
            for(int j=drawer[sum[i]]+1;j<=i;j++)
                cout<<in[j]<<endl;
            return 0;
        }
    }
    return 0;
}



你可能感兴趣的:([POJ 2356]Find a multiple(抽屉原理))