【2015暑假】鸽巢原理总结 【算法思路+组合数学】

组合数学之鸽巢原理

如果要把n+1物体放进n个盒子里,那么至少会有一个盒子包含2个或2个以上的物体。

现在问题来了:给你n个数,从中选出若干个数使得它们的和为n的倍数。

鸽巢原理表示:一定存在若干个连续的数,它们的和是n的倍数。

有的情况下,不光要知道一定存在,而且还要找出是哪些数,算法如下:

n = 4;

a[]:3  2  1  9

s[]:3  5  6  15   (注:)

先检查s[]中有没有某个s[i]%n==0,如果存在,那么这些数字它们加起来就可以整除n。如果不存在,那么由基本定理可知:必然会存在两个不同的和它们对n取余的余数相同,故部分和-= +  +…+  是n的倍数。

对于上面的例子一次求出s[]对n的余数:

yu[]:3  1  2  3

可知:和对4取余的余数均为3,故可以得到:2 + 1 + 9=12的和可以整除n。

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <algorithm>
 5 #define N 100000
 6
 7 using namespace std;
 8
 9
10 int main()
11 {
12     int n;
13     int a[N];
14     int s[N];
15     int yu[N];
16
17     while(scanf("%d", &n)!=EOF)
18     {
19         for(int i=0; i<n; i++){
20             scanf("%d", &a[i]);
21         }
22
23         bool flag=false;
24         int left=0, right;
25         s[0]=a[0];
26         for(int i=1; i<n; i++){
27             s[i]=s[i-1]+a[i];
28             if(s[i]%n == 0){
29                 flag=true;
30                 right=i; break;
31             }
32         }
33         if(flag){
34             printf("YES\n");
35             for(int i=0; i<=right; i++)
36             {
37                 printf("%d ", a[i]);
38             }
39         }else{
40             for(int i=0; i<n; i++){
41                 yu[i]=s[i]%n;
42             }
43             //查找yu[]里面哪两个数相等
44             for(int i=0; i<n; i++)
45             {
46                 left=i;
47                 for(int j=i+1; j<n; j++){
48                     if(yu[i]==yu[j]){
49                         right=j; break;
50                     }
51                 }
52             }
53             printf("YES\n");
54             for(int i=left+1; i<=right; i++)
55             {
56                 printf("%d ", a[i]);
57             }
58         }
59     }
60     return 0;
61 }

时间: 2024-11-17 08:09:21

【2015暑假】鸽巢原理总结 【算法思路+组合数学】的相关文章

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

骚操作之鸽巢原理

桌上有十个苹果,要把这十个苹果放到九个抽屉里,无论怎样放,我们会发现至少会有一个抽屉里面至少放两个苹果.这一现象就是我们所说的"抽屉原理". 抽屉原理的一般含义为:"如果每个抽屉代表一个集合,每一个苹果就可以代表一个元素,假如有n+1个元素放到n个集合中去,其中必定有一个集合里至少有两个元素." 抽屉原理有时也被称为鸽巢原理.它是组合数学中一个重要的原理. 在acm中也是会遇到的,比如两个人对打的得分问题 110个人参加一个国际象棋单循环比赛,每两人都进行一局比赛,

抽屉原理(鸽巢原理)

转至:https://blog.csdn.net/sand8o8time/article/details/77009749 一.抽屉原理初介绍: 桌上有十个苹果,要把这十个苹果放到九个抽屉里,无论怎样放,我们会发现至少会有一个抽屉里面至少放两个苹果.这一现象就是我们所说的“抽屉原理”. 抽屉原理的一般含义为:“如果每个抽屉代表一个集合,每一个苹果就可以代表一个元素,假如有n+1个元素放到n个集合中去,其中必定有一个集合里至少有两个元素.” 抽屉原理有时也被称为鸽巢原理.它是组合数学中一个重要的原

数组问题(鸽巢原理、数字交换、链表寻环)

287. 寻找重复数 不能更改原数组(假设数组是只读的). 只能使用额外的 O(1) 的空间. 时间复杂度小于 O(n2) . 数组中只有一个重复的数字,但它可能不止重复出现一次. 因为不能能改原来的数组,并且只能使用额外O1的空间,所以我们不能使用map记录,也不能维护一个新的数组 因为时间复杂度要在n2以内,所以暴力查找也是不可取的 因为数据范围在1~n-1,所以可以保证不会数组越界,因此使用链表中快慢指针寻找环算法 https://www.cnblogs.com/fankongkong/p

HDU 1205.吃糖果【鸽巢原理】【8月1】

吃糖果 Problem Description HOHO,终于从Speakless手上赢走了所有的糖果,是Gardon吃糖果时有个特殊的癖好,就是不喜欢将一样的糖果放在一起吃,喜欢先吃一种,下一次吃另一种,这样:可是Gardon不知道是否存在一种吃糖果的顺序使得他能把所有糖果都吃完?请你写个程序帮忙计算一下. Input 第一行有一个整数T,接下来T组数据,每组数据占2行,第一行是一个整数N(0<N<=1000000),第二行是N个数,表示N种糖果的数目Mi(0<Mi<=10000

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

鸽巢原理

鸽巢原理: n+1个鸽子放入n个窝中,至少有一个窝含有两只鸽子  Find a multiple Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5590   Accepted: 2434   Special Judge Description The input contains N natural (i.e. positive integer) numbers ( N <= 10000 ). Each of that

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

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

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