您的位置:首页 > 其它

Find a multiple (POJ - 2356 )(鸽巢原理)

2017-05-08 13:06 447 查看
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+1个物体被放进n个盒子,那么至少有一个盒子包含两个或更多的物体。

  例1:在13个人中存在两个人,他们的生日在同一月份里。

  例2:设有n对已婚夫妇。为保证有一对夫妇被选出,至少要从这2n个人中选出多少人?(n+1)(引自百度)

关键是起初在实战中很少或者说想不到运用。以这道题为引子。

分析:我们可以在设置一个sum数组,在记录各个值的同事,把1到i(1<=i<=n)的和一并求出

假设在这场情况下 存在有sum[i]%n==0,我们输出即可

如果所有的sum[i]取模都没有等于0的,这里就用上这个原理,

我们把所有的sum[i]都取模,若存在两个i和j 使得sum[i]==sum[j](此时sum中存的是模数)

那么(sum[j]-sum[i])%n==0,这样就找到了一个答案,那么会不会存在两个相等的sum呢,答案是肯定有。

所以的余数情况是1到n-1,我们可以看做是箱子,而n个sum则是鸽子,也就是说,必然存在两个模相等的sum。

代码

import java.util.Scanner;

public class Main
{
public static void main(String[]args)
{
Scanner sc=new Scanner(System.in);
while(sc.hasNext())
{
int n=sc.nextInt();
int a[]=new int[n+1];//保存各个数,输出需要
int sum[]=new int[n+1];//和值
boolean  sign=false;//在前期用来判断有没有找到是n的倍数的值
for(int i=1;i<=n;i++)
{
a[i]=sc.nextInt();
sum[i]+=sum[i-1]+a[i];
if(!sign)
{
if(sum[i]%n==0)
{
System.out.println(i);
for(int j=1;j<=i;j++)
System.out.println(a[j]);
sign=true;//如果找到就置为true
}
}
}
if(!sign)//没有找到就使用鸽巢原理
{
for(int i=1;i<=n;i++)
sum[i]%=n;//去n的模
int v[]=new int
;//这个就相当于是箱子
for(int i=1;i<=n;i++)
{
if(v[sum[i]]==0)
v[sum[i]]=i;//在箱子里村的是编号数
else//如果不为说明之前已经有鸽子进入这个箱子,也就是说找到两个值了
{
int l=v[sum[i]];
System.out.println(i-l);
for(int j=l+1;j<=i;j++)
System.out.println(a[j]);//输出即可
break;
}
}
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  鸽巢原理