POJ2356 Find a multiple(抽屉原理和暴力解法)

Find a multiple
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 8590 Accepted: 3724 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个数能不能组成组成n倍,能的话输出有几个数可以组成,然后输出他们。不能就输出0;

这道题暴力就能过,两个for跑完所有情况就行,或者是抽屉原理做。

抽屉原理大家可以自行百度,把多于n+1个的物体放到n个抽屉里,则至少有一个抽屉里的东西不少于两件。我们可以用一个sum[i]数组来记录a[1]到a[i]的和,如果发现sum[i]%n==0的话那么从a[1]至a[i]就是答案。如果没有没有能除尽的话就使sum[i]%n,而sum[i]%n的值都肯定在1~n-1,那么这个就符合抽屉原理了,现在有n个数,而抽屉最多有n-1个,这样一来肯定会存在至少一个sum[i]%n==sum[j]%n,i<=j。那么我们只要找到i和j就可以了,sum[i]是n的倍数加上一个余数,而sum[j]是n的倍数加一个余数,那么sum[j]-sum[i]的话剩下的就是n的倍数,那么我们只要输出i+1到j的数就可以了

暴力代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int main()
{
    int n;
    int a[10005];
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
        }
        int sum,flag=0,x,y;
        for(int i=0;i<n;i++)
        {
            sum=0;
            for(int j=i;j<n;j++)
            {
                sum+=a[j];
                if(sum%n==0)
                {
                    flag=1;
                    x=i;
                    y=j;
                    break;
                }
            }
            if(flag==1)
                break;
        }
        if(flag==1)
            {
                printf("%d\n",y-x+1);
                for(int i=x;i<=y;i++)
                {
                    printf("%d\n",a[i]);
                }
            }
        else
            printf("0\n");
    }
}

抽屉

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int main()
{
    int n;
    while(~scanf("%d",&n))
    {

        int a[10005],sum[10005],aa[15005];
        memset(a,0,sizeof(a));
        memset(sum,0,sizeof(sum));
        memset(aa,-1,sizeof(aa));
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            sum[i]+=sum[i-1]+a[i];
        }
        for(int i=1; i<=n; i++)
        {
            if(sum[i]%n==0)
            {
                printf("%d\n",i);
                for(int j=1; j<=i; j++)
                    printf("%d\n",a[j]);
                    break;
            }
            if(aa[sum[i]%n]!=-1)//只要能找到一个就符合条件
            {
                printf("%d\n",i-aa[sum[i]%n]);
                for(int j=aa[sum[i]%n]+1; j<=i; j++)
                    printf("%d\n",a[j]);
                break;
            }
            aa[sum[i]%n]=i;//每次记录的是aa中的sum[i]%n是否出现过,出现的话就记录他的i
        }
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值