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代码:

//未优化的代码,172ms
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

int Sum[10010],A[10010];

int main()
{
    int N;
    while(~scanf("%d",&N))
    {
        memset(Sum,0,sizeof(Sum));
        for(int i = 1; i <= N; ++i)
        {
            scanf("%d",&A[i]);
            Sum[i] = (Sum[i-1] + A[i]) % N;
        }
        int Flag = 0;
        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]);
                Flag = 1;
            }
            else
            {
                for(int j = 1; j < i; ++j)
                {
                    if(Sum[i] == Sum[j])
                    {
                        printf("%d\n",i-j);
                        for(int k = j+1; k <= i; ++k)
                            printf("%d\n",A[k]);
                        Flag = 1;
                        break;
                    }
                }
            }
            if(Flag)
                break;
        }

    }

    return 0;
}
//优化后代码,0ms
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

int Sum[10010],A[10010],Mod[10010];

int main()
{
    int N,Left,Right;
    while(~scanf("%d",&N))
    {
        memset(Mod,-1,sizeof(Mod));
        memset(Sum,0,sizeof(Sum));
        Mod[0] = 0;
        for(int i = 1; i <= N; ++i)
        {
            scanf("%d",&A[i]);
            Sum[i] = (Sum[i-1] + A[i]) % N;
            if(Mod[Sum[i]] == -1)
            {
                Mod[Sum[i]] = i;
            }
            else
            {
                Left = Mod[Sum[i]];
                Right = i;
            }
        }
        printf("%d\n",Right-Left);

        for(int i = Left + 1; i <= Right; ++i)
            printf("%d\n",A[i]);

    }

    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-28 15:57:09

POJ2356 Find a multiple【鸽巢原理】的相关文章

[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

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不成

POJ 2356 find multiple 鸽巢原理

我们在浏览一些网站,尤其是一些小说网站的时候,都会有修改页面背景颜色的地方,这个功能使用jquery很容易实现. 效果图: show you code: <!doctype html> <html> <head> <meta charset="utf-8"> <title>jquery test</title> <script src="jquery-1.11.1.min.js">&

poj 2356 Find a multiple (鸽巢原理妙用)

题目链接:http://poj.org/problem?id=2356 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

Poj2356Find a multiple鸽巢原理

一定存在连续的k个数,使得他们的和能被n整除.设a[i]为前缀和 a[1]%n  ,a[2]%n,...,a[n]%n的值的范围<n,所以有n个数小与n,肯定会出现两个一样的数,表明了,第二个数比第一个数多出来的一部分一定能被n整除. 要注意处理 前缀和中出现0的情况. #include<iostream> #include<cstdio> #include<cstring> #include<map> #include<vector> #

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 题解(鸽巢原理)

[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 w

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