[POJ2356]Find a multiple 题解(鸽巢原理)

[POJ2356]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.

Solution

1.题目大意即为求n个数中区间和被n整除的第一个区间[l,r];

2.由鸽巢原理知,n个不同的数会造成n个不同的前缀和,那么至少有两个前缀和关于n是同余的,我们只需找出第一个出现两次的模后前缀和即可;

3.打一个地址标记,记录模值的第一次出现地址,当第二次出现同一模后前缀和时,使l=第一次出现地址,r=第二次出现地址,区间[l,r]即为所求;

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int main(){
    int i,j,l=0,r,n,t[10001]={},a[10001]={},sum[10001]={};
    scanf("%d",&n);
    memset(t,-1,sizeof(t));
    t[0]=0;
    for(i=1;i<=n;++i){
        scanf("%d",&a[i]);
        sum[i]=(sum[i-1]+a[i])%n;
        if(t[sum[i]]!=-1){
            l=t[sum[i]];
            r=i;
            break;
        }
        else t[sum[i]]=i;//zzh大佬的计数方法;
    }
    printf("%d\n",r-l);
    for(i=l+1;i<=r;++i)printf("%d\n",a[i]);
    return 0;
}

有关鸽巢原理可以参考我的博客:http://www.cnblogs.com/COLIN-LIGHTNING/p/8439555.html

原文地址:https://www.cnblogs.com/COLIN-LIGHTNING/p/8481478.html

时间: 2024-08-30 03:58:21

[POJ2356]Find a multiple 题解(鸽巢原理)的相关文章

POJ2356 Find a multiple【鸽巢原理】

题目链接: http://poj.org/problem?id=2356 题目大意: 给你N个正数的序列,从中找到连续的若干数,使得其和刚好是N的倍数. 解题思路: 典型的抽屉原理. Sum[i]为序列中前i项的和.则有两种可能: 1.若有Sum[i]是N的倍数,则直接输出前i项. 2.如果没有任何的Sum[i]是N的倍数,则计算ri = Sum[i] % N.根据鸽巢原理,肯 定有Sum[i] % N == Sum[j] % N,i != j.则第 j 到第 i 项数的和即为N的倍数. AC代

POJ 2356. Find a multiple 抽屉/鸽巢原理

Find a multiple Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7192   Accepted: 3138   Special Judge Description The input contains N natural (i.e. positive integer) numbers ( N <= 10000 ). Each of that numbers is not greater than 15000

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 i

poj 2356 Find a multiple【鸽巢原理 模板应用】

Find a multiple Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6651   Accepted: 2910   Special Judge Description The input contains N natural (i.e. positive integer) numbers ( N <= 10000 ). Each of that numbers is not greater than 15000

poj2356 Find a multiple(抽屉原理|鸽巢原理)

/* 引用过来的 题意: 给出N个数,问其中是否存在M个数使其满足M个数的和是N的倍数,如果有多组解, 随意输出一组即可.若不存在,输出 0. 题解: 首先必须声明的一点是本题是一定是有解的.原理根据抽屉原理: 因为有n个数,对n个数取余,如果余数中没有出现0,根据鸽巢原理,一定有两个数的余数相同, 如果余数出现0,自然就是n的倍数.也就是说,n个数中一定存在一些数的和是n的倍数. 本题的思路是从第一个数开始一次求得前 i(i <= N)项的和关于N的余数sum,并依次记录相应余数的存在状态,

[POJ2356] Find a multiple 鸽巢原理

Find a multiple Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8776   Accepted: 3791   Special Judge Description The input contains N natural (i.e. positive integer) numbers ( N <= 10000 ). Each of that numbers is not greater than 15000

[POJ3370]&amp;[HDU1808]Halloween treats 题解(鸽巢原理)

[POJ3370]&[HDU1808]Halloween treats Description -Every year there is the same problem at Halloween: Each neighbour is only willing to give a certain total number of sweets on that day, no matter how many children call on him, so it may happen that a

poj 2356 Find a multiple 鸽巢原理的简单应用

题目要求任选几个自然数,使得他们的和是n的倍数. 由鸽巢原理如果我们只选连续的数,一定能得到解. 首先预处理前缀和模n下的sum,如果发现sum[i]==sum[j] 那么(sum[j]-sum[i])%n一定为0,直接输出i+1~j就够了. 为什么一定会有解,因为sum从1~n有n个数,而模n下的数只有0~n-1,把n个数放入0~n-1个数里,怎么也会有重复,所以这种构造方法一定没问题. 其实可以O(n)实现,嫌麻烦,就二重循环无脑了. #include <iostream> #includ

POJ 2356 Find a multiple 鸽巢原理

题目来源:POJ 2356 Find a multiple 题意:n个数 选出任意个数 使得这些数的和是n的倍数 思路:肯定有解 并且解是连续的一段数 证明: 假设有m个数 a1,a2,a3...am    s1 s2 s3...sm为前缀和 s1 = a1 s2 = a1+a2 s3 = a1+a2+a3... sm = a1+a2+a3+...+am 1.如果某个前缀和si%m == 0 那么得到解 2.设x1=s1%m x2 = s2%m x3 = s3%m xm = sm%m 因为1不成