Halloween treats - 鸽巢定理

题意

输入 cc 和 nn,代表有 cc 个孩子和 nn 户邻居。

接着一行输入 nn 个数字,代表万圣节时每户邻居会给孩子们的糖果数量。

孩子们想要去若干个邻居访问,然后拿到糖果。他们想要糖果能够平分,输出访问的邻居编号。

思路

题目规定了c<=n,从这里我们可以尝试找关系。由于是求最后能平分,我们直接在读入时就可以取模。然后发现得到的数列 0 <= ai <= c-1, 下一步我们怎么想都只能尝试对其求前缀和并取模,0 <= sumi <= c-1,这一步出现了sumi == 0,直接意味着这一段前缀是可以取得。然后看这个前缀和的范围,一共有c种可能性,而一旦有两个sum相等,意味着中间区间的和可以整除c,所以最极端的情况是sum取满了c-1种情况(因为不算0),而这是不可能的
因为: 1 < = ∀ s u m i < = c − 1 1<=\forall sum_i<=c-1 1<=sumi<=c1, s u m i ! = s u m j sum_i != sum_j sumi!=sumj 推出 1 < = i < = c − 1 1<=i<=c-1 1<=i<=c1,与题意 1 < = i < = n , n > = c 1<=i<=n,n>=c 1<=i<=n,n>=c不符,故必定存在一段连续区间使得 ∑ i = l r a i m o d c = 0 \sum_{i=l}^{r}a_i modc =0 i=lraimodc=0.

#include "bits/stdc++.h"

#define int long long
const int mod = 1e9 + 7;
const int maxn = 1e5+10;
using namespace std;
int sum[maxn];
int vis[maxn];
signed main() {
    ios ::sync_with_stdio(0);
    int t;
    int n,c;
    while (cin >> c >> n,!(c == 0 && n == 0)){
        memset(vis,0,sizeof vis);
        memset(sum,0,sizeof sum);
        int end = 0;
        for (int i = 1; i <= n; ++i) {
            int tmp;
            cin >> tmp;
            sum[i] = (sum[i- 1] + tmp) % c;
            if (!sum[i]) end = i;
        }
        if (end) {
            for (int i = 1; i <= end; ++i) {
                cout << i <<( (end == i)?'\n':' ');
            }
            continue;
        }
        for (int i = 1; i <=  n; ++i) {
            if (vis[sum[i]])
            {
                for (int j = vis[sum[i]]+1; j <= i; ++j) {
                    cout << j <<( (j == i)?'\n':' ');
                }
                break;
            } else
                vis[sum[i]] = i;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值