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;
    }
  • 相关阅读:
    高清摄像头MIPI接口与ARM处理器的连接
    How to make apq8084
    DBI接口和DPI接口的区别
    MIPI DSI协议介绍
    LCD显示的一些基本概念以及DSI的一些clock解释
    AXI总线
    SPI,UART,I2C都有什么区别,及其各自的特点
    图像滤镜处理算法:灰度、黑白、底片、浮雕
    用到的一些算法收集
    实用Linux命令,不求最全但求实用-------iptables命令实战
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4900960.html
Copyright © 2011-2022 走看看