[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

题目大意:给定一个含有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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值