[51NOD1103] N的倍数(鸽笼原理)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1103

这题一脸组合数学鸽笼原理例题的样子。

这个问题自己其实YY过很久了,结果今天看到又给忘了。大概是因为没有手写过,希望下次不再忘了。

求前缀和,再对n取模。假如有模为0的,那么就直接拿出来前1~i个数。

如果没有0,那么模数只有n-1个,相对与一共有n个前缀和,根据鸽笼原理,必然有一个模数出现了两次,那这出现了两次的模数位置找出来,把这些数输出就行了。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 typedef long long LL;
 5 const int maxn = 500500;
 6 int n;
 7 LL a[maxn], s[maxn];
 8 int vis[maxn];
 9
10 void gao() {
11     for(int i = 1; i <= n; i++) {
12         if(!s[i]) {
13             printf("%d\n", i);
14             for(int j = 1; j <= i; j++) {
15                 printf("%lld\n", a[j]);
16             }
17             return;
18         }
19     }
20     memset(vis, 0, sizeof(vis));
21     for(int i = 1; i <= n; i++) {
22         if(vis[s[i]]) {
23             printf("%d\n", i - vis[s[i]]);
24             for(int j = vis[s[i]] + 1; j <= i; j++) {
25                 printf("%lld\n", a[j]);
26             }
27             return;
28         }
29         vis[s[i]] = i;
30     }
31 }
32
33 int main() {
34     // freopen("in", "r", stdin);
35     while(~scanf("%d", &n)) {
36         memset(s, 0, sizeof(s));
37         for(int i = 1; i <= n; i++) {
38             scanf("%lld", &a[i]);
39             s[i] = (s[i-1] + a[i]) % (LL)n;
40         }
41         gao();
42     }
43     return 0;
44 }
时间: 2024-08-28 02:47:46

[51NOD1103] N的倍数(鸽笼原理)的相关文章

POJ 2356 Find a multiple (dp + 鸽笼原理)

OJ题目:click here~~ 题目分析:n个数,从中取若干个数,和为n的倍数.给出一种取法. 因为只要给出其中一种方案就行,鸽笼原理可以求出取出的数为连续的方案. 关于鸽笼原理,点这里~ 直接贴过来: 有n+1件或n+1件以上的物品要放到n个抽屉中,那么至少有一个抽屉里有两个或两个以上物品. 如果你知道这个结论: a1,a2,a3...am是正整数序列,至少存在整数k和r,1<=k<r<=m,使得ak+a(k+1)+...+a(r)是m的倍数. 证明比较简单: Sk表示前k个数之和

poj3370Halloween treats(鸽笼原理)

题目链接: 传送门 思路: 这个是鸽笼原理的题目...看了一下这个原理,对此的理解是分为三点.. c代表人的数目,n代表家庭的数目.. [1]首先要求前缀和,然后对此取余,首先如果出现余数为0的情况,那么说明前n项就已经满足了条件,那么这就是其中的一组可行解... [2]但是如果没有出现0呢??那么就看同余了..如果在两个点处出现同余,说明什么??说明从上一个出现同余的后一个数到这个数的和为c的倍数,那么就得到了一组可行解.. [3]题目说没有情况则输出"no sweetws",但是说

UVA 10620 - A Flea on a Chessboard(鸽笼原理)

UVA 10620 - A Flea on a Chessboard 题目链接 题意:给定一个跳蚤位置和移动方向,现在在一个国际象棋棋盘上,左下角为黑格,一个格子为s*s,判断能否移动到白格子,问要移动多少次才能到白格,边界不算白格. 思路:利用鸽笼原理落在黑格子和边界上的一共有(s + 1)^2个点,也就是说,如果形成循环,周期肯定在这之内,所以可以不断去模拟跳格子,直到踩到白格,或者踩到之前落到过的黑格就结束 不过其实还有更优的方法,因为跳蚤跳跃路径为直线,观察下可以发现如果可以到白格,最多

HDU 5762 Teacher Bo (鸽笼原理) 2016杭电多校联合第三场

题目:传送门. 题意:平面上有n个点,问是否存在四个点 (A,B,C,D)(A<B,C<D,A≠CorB≠D)使得AB的横纵坐标差的绝对值的和等于CD的横纵坐标差的绝对值的和,n<10^5,点的坐标值m<10^5. 题解:表面上这道题复杂度是O(n^2)会超时的,而实际上这些坐标差绝对值的和最大是2*10^5,所以复杂度不是O(n^2),而是O(min(n^2,m)),这就是著名的鸽笼原理. #include <iostream> #include <cstdio

UVA 11237 - Halloween treats(鸽笼原理)

11237 - Halloween treats 题目链接 题意:有c个小伙伴,n个房子(c <= n),每个房子会给ai个糖果,要求选一些房子,使得得到的糖果能平均分给小伙伴,输出方案 思路:c <= n 这个条件很关键,如果有这个条件,那么就可以开一个sum[i]记录0 - i的前缀和%c的值,这样一来在长度n的数组中,必然会出现重复的两个值,用sum[i] - sum[j] == 0这个区间就必然是所求的答案 代码: #include <cstdio> #include &l

poj2356Find a multiple(鸽笼原理)

题目链接: huangjing 思路: 详见传送门 题目: Find a multiple Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6015   Accepted: 2609   Special Judge Description The input contains N natural (i.e. positive integer) numbers ( N <= 10000 ). Each of that num

hdu1205 吃糖果(鸽笼原理)

题目链接: huangjing 思路: 这个题我是这样想的,把其他颜色的糖果当成挡板,必过有n个,那么就可以形成n+1个位置,那么如果n+1大于最大堆糖果树,那么就可以吃到所有不同的糖果,但是有可能会说,万一其他颜色的糖果冲突呢????但是因为其他每种颜色的糖果的数目必然小于最大的,那么可以把这些插入到最大堆的糖果和其他颜色中,相当于加大板子的厚度.... 题目: 吃糖果 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/

51NOD 1103 N的倍数(抽屉原理)

传送门 一个长度为N的数组A,从A中选出若干个数,使得这些数的和是N的倍数. 例如:N = 8,数组A包括:2 5 6 3 18 7 11 19,可以选2 6,因为2 + 6 = 8,是8的倍数. Input 第1行:1个数N,N为数组的长度,同时也是要求的倍数.(2 <= N <= 50000) 第2 - N + 1行:数组A的元素.(0 < A[i] <= 10^9) Output 如果没有符合条件的组合,输出No Solution. 第1行:1个数S表示你所选择的数的数量.

1103 N的倍数 (抽屉原理)

题意:一个长度为N的数组A,从A中选出若干个数,使得这些数的和是N的倍数. 例如:N = 8,数组A包括:2 5 6 3 18 7 11 19,可以选2 6,因为2 + 6 = 8,是8的倍数.(2 <= N <= 50000,0 < A[i] <= 10^9) 分析:在modN意义下求A的前缀和,若有为0的前缀和,前k个即为所求;若没有,有抽屉原理,必然存在两个值相等的前缀和,两者相减即为所求. 1 #include<iostream> 2 #include<c