zoukankan      html  css  js  c++  java
  • 【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
    ");
    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
    ");
    54             for(int i=left+1; i<=right; i++)
    55             {
    56                 printf("%d ", a[i]);
    57             }
    58         }
    59     }
    60     return 0;
    61 }
    View Code
  • 相关阅读:
    Jenkins使用msbuild编译问题记录
    mui的l label下radio问题
    JavaScript {} 和[]的区别 post提交数据
    闭包
    自我介绍
    激活码
    Excel的Xlsb格式的优点及缺点,与xlsx xlsm格式的区别
    oracle 数据类型 number
    iOS 14 更新后微信等应用 发送图片只能选择最近的项目
    plsql 恢复文件
  • 原文地址:https://www.cnblogs.com/yspworld/p/4663264.html
Copyright © 2011-2022 走看看