zoukankan      html  css  js  c++  java
  • 鸽巢原理入门

    鸽巢原理又叫抽屉原理,百度百科的定义是:桌上有十个苹果,要把这十个苹果放到九个抽屉里,无论怎样放,我们会发现至少会有一个抽屉里面至少放两个苹果。这一现象就是我们所说的“抽屉原理”。

    下面有两个入门题目:

    POJ2356

    题意:从n个数中选出几个数的和是n的倍数。

    因为给定的是n个数,所以结论是一定存在。证明如下:

    用sum[k]表示前k个数的和,假设不存在,那么sum[k] % n一定在1到(n-1)之间,其中k为(1~n),那么它的余数至少有两个数是相等的。因为鸽巢原理n个苹果放到n-1个抽屉里,假设sum[i] % n == sum[j] % n, 那么sum[j] - sum[i]就一定可以被n整除。与假设矛盾。所以一定存在。

    这个题的具体做法就是,先找sum[1]~sum[n]有没有能被n整除的,如果有的话,直接找到了。没有的话继续把没个数的余数保存下来,那么下次碰见和这个数余数相同的话,那么一定可以被n整除。代码如下:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 10010;
    int sum[maxn];
    int b[maxn];
    int main()
    {
        int n;
        while (~scanf("%d", &n))
        {
            int a;
            for (int i = 1; i <= n; i++) { 
                scanf("%d", &a);
                sum[i] = sum[i - 1] + a;
            }
            for (int i = 1; i <= n; i++)
            {
                if (sum[i] % n == 0)
                {
                    printf("%d
    ", i);
                    for (int j = 1; j <= i; j++) printf("%d
    ", sum[j] - sum[j - 1]);
                    break;
                }
                if (b[sum[i] % n] != 0)
                {
                    printf("%d
    ", i - b[sum[i] % n]);
                    for (int j = b[sum[i] % n] + 1; j <= i; j++) printf("%d
    ", sum[j] - sum[j - 1]);
                    break;
                }
                else
                    b[sum[i] % n] = i;
            }
        }
        return 0;
    }

    POJ3370

    这个题和上一个题基本上一样,就是模c而已,正好c又是小于等于n的,所以满足鸽巢定理,wa了好久,,,发现用long long

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 100010;
    typedef long long ll;
    ll sum[maxn] = {0};
    int b[maxn];
    int main()
    {
        int n, c;
        while (~scanf("%d %d", &c, &n) && (n + c))
        {
            int a;
            for (int i = 1; i <= n; i++)
            {
                scanf("%d", &a);
                sum[i] = sum[i - 1] + a;
            }
            memset(b, 0, sizeof(b));
            for (int i = 1; i <= n; i++)
            {
                if (sum[i] % c == 0)
                {
                    for (int j = 1; j < i; j++) 
                        printf("%d ", j);
                    printf("%d
    ", i);
                    break;
                }
                else if (b[sum[i] % c] != 0)
                {
                    for (int j = b[sum[i] % c] + 1; j < i; j++)
                        printf("%d ", j);
                    printf("%d
    ", i);
                    break;
                }
                else
                    b[sum[i] % c] = i;
            }
        }
        return 0;
    }
  • 相关阅读:
    微信:JSSDK开发
    JSSDK图像接口多张图片上传下载并将图片流写入本地
    微信JSSDK上传多张图片
    laravel自定义公共函数的引入
    php把数据转换为json格式
    laravel控制器方法中,用函数作为变量进行传递时的处理方法
    ckeditor富文本编辑器的基本配置设置:
    laravel处理菜单保持的方法:
    laravel基于Bootstrap的成功和失败的提示信息和验证提示信息
    laravel Eloquent 查询数据库判断获取的内容是否为空
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4900960.html
Copyright © 2011-2022 走看看