鸽巢原理入门

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

下面有两个入门题目:

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;
}
原文地址:https://www.cnblogs.com/Howe-Young/p/4900960.html