hdu 1808 抽屉原理

抽屉原理

说的简单一点就是,n+1个物品放n个箱子,必定有一个箱子有两个物品(无空箱)

题意

m个小孩在万圣节去n家住户要糖,每个住户有一定数量的糖,并且如果有小孩来要,就会全部给出去。
先要要求m个小孩最后要到的糖的数量能不能均分,求任意一组方案

分析

由于 n > = m n>=m ,故肯定有解
我们设 s u m [ i ] sum[i] 为住户的糖的前缀和
由上面知, s u m sum 数组最后肯定大于等于m
所以存在 s u m [ i ] s u m [ j ] ( m o d m ) ( i j ) sum[i]\equiv sum[j] \pmod m \quad(i \neq j)
所以存在 ( s u m [ j ] s u m [ i ] ) % m = 0 (sum[j]-sum[i]) \% m = 0
故存在一段区间糖果数量之和为m的倍数

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template <typename T>
void out(T x) { cout << x << endl; }
ll fast_pow(ll a, ll b, ll p) {ll c = 1; while(b) { if(b & 1) c = c * a % p; a = a * a % p; b >>= 1;} return c;}
ll exgcd(ll a, ll b, ll &x, ll &y) { if(!b) {x = 1; y = 0; return a; } ll gcd = exgcd(b, a % b, y, x); y-= a / b * x; return gcd; }
const int N = 1e5 + 100;
int sum[N], Mo[N];
int main()
{
    ios::sync_with_stdio(false);
    int c, n;
    while(cin >> c >> n, c + n)
    {
        memset(Mo, -1, sizeof(Mo));
        sum[0] = 0;
        Mo[0] = 0;
        int l = -1, r = -1;
        for(int i = 1; i <= n; i ++)
        {
            int x;
            cin >> x;
            sum[i] = (sum[i - 1] + x) % c;
            if(Mo[sum[i]] == -1)
                Mo[sum[i]] = i;
            else 
            {
                l = Mo[sum[i]];
                r = i;
            }
        }
        for(int i = l + 1; i <= r; i ++)
            cout << i << (i != r ? " " : "\n");
    }
}

原创文章 83 获赞 6 访问量 2753

猜你喜欢

转载自blog.csdn.net/qq_43101466/article/details/102710285