POJ 2356 && POJ 3370 鸽巢原理

POJ 2356:

题目大意:

给定n个数,希望在这n个数中找到一些数的和是n的倍数,输出任意一种数的序列,找不到则输出0

这里首先要确定这道题的解是必然存在的

利用一个 sum[i]保存前 i 个数的和对n的取模

sum[0] = 0;

那么sum[0] ~ sum[n]有n+1个数据,这些数据的范围都是 0~n , 要是存在 sum[i] = 0,那么输出前 i 个数据即可

要是不存在那根据鸽巢原理可以说明必然能找到一个 sum[i] = sum[j]  ,那么说明 (sum[i+1] + sum[i+2] ...+sum[j])%n = 0的,把这j-i个数输出即可

那么说明我们总是能找到一段连续的数据使其和是n的倍数

 1 #include <cstdio>
 2 #include <cstring>
 3
 4 using namespace std;
 5 const int N = 10005;
 6
 7 bool vis[N];
 8 int sum[N] , a[N] , pos[N];
 9
10 int main()
11 {
12    // freopen("a.in" , "r" , stdin);
13     int n;
14     while(scanf("%d" , &n) != EOF)
15     {
16         for(int i=1 ; i<=n ; i++){
17             scanf("%d" , a+i);
18         }
19         memset(vis , 0 , sizeof(vis));
20         vis[0] = 1 , pos[0] = 0;
21         for(int i=1 ; i<=n ; i++){
22             sum[i] = (sum[i-1]+a[i])%n;
23             if(vis[sum[i]]){
24                 int l = pos[sum[i]];
25                 printf("%d\n" , i-l);
26                 for(int j = l+1 ; j<=i ; j++){
27                     printf("%d\n" , a[j]);
28                 }
29                 break;
30             }
31             pos[sum[i]] = i;
32             vis[sum[i]] = 1;
33         }
34     }
35     return 0;
36 }

POJ3370:

 1 #include <cstdio>
 2 #include <cstring>
 3
 4 using namespace std;
 5 #define N 100005
 6 bool vis[N];
 7 int sum[N] , a[N] , pos[N];
 8
 9 int main()
10 {
11    // freopen("a.in" , "r" , stdin);
12     int c , n;
13     while(scanf("%d%d" , &c , &n) , c||n)
14     {
15         for(int i=1 ; i<=n ; i++)
16             scanf("%d" , a+i);
17         memset(vis , 0 ,sizeof(vis));
18         sum[0] = 0 , vis[0] = 1 , pos[0] = 0;
19         for(int i=1 ; i<=n ; i++){
20             sum[i] = (sum[i-1] + a[i])%c;
21             if(vis[sum[i]]){
22                 int l = pos[sum[i]];
23                 for(int j=l+1 ; j<=i ; j++){
24                     if(j == l+1) printf("%d" , j);
25                     else printf(" %d" , j);
26                 }
27                 printf("\n");
28                 break;
29             }
30             vis[sum[i]] = 1;
31             pos[sum[i]] = i;
32         }
33     }
34     return 0;
35 }
时间: 2024-10-10 10:19:45

POJ 2356 && POJ 3370 鸽巢原理的相关文章

POJ 2356 find multiple 鸽巢原理

我们在浏览一些网站,尤其是一些小说网站的时候,都会有修改页面背景颜色的地方,这个功能使用jquery很容易实现. 效果图: show you code: <!doctype html> <html> <head> <meta charset="utf-8"> <title>jquery test</title> <script src="jquery-1.11.1.min.js">&

Find a multiple POJ - 2356 容斥原理(鸠巢原理)

1 /* 2 这道题用到了鸠巢原理又名容斥原理,我的参考链接:https://blog.csdn.net/guoyangfan_/article/details/102559097 3 4 题意: 5 这道题给你了n个数,让你找这n个数中有没有几个数的和是n的倍数 6 7 题解: 8 你循环遍历一遍这n个数,如果某个数是n的倍数,那就输出一个1再输出这个数 9 如果没有的话,那就对这n个数求一下求前缀和. 10 1.在循环遍历一遍这个前缀和,如果某个数是n的倍数,那就输出i,再循环打印出1到i的

poj 2356 Find a multiple 鸽巢原理的简单应用

题目要求任选几个自然数,使得他们的和是n的倍数. 由鸽巢原理如果我们只选连续的数,一定能得到解. 首先预处理前缀和模n下的sum,如果发现sum[i]==sum[j] 那么(sum[j]-sum[i])%n一定为0,直接输出i+1~j就够了. 为什么一定会有解,因为sum从1~n有n个数,而模n下的数只有0~n-1,把n个数放入0~n-1个数里,怎么也会有重复,所以这种构造方法一定没问题. 其实可以O(n)实现,嫌麻烦,就二重循环无脑了. #include <iostream> #includ

POJ 2356 Find a multiple 鸽巢原理

题目来源:POJ 2356 Find a multiple 题意:n个数 选出任意个数 使得这些数的和是n的倍数 思路:肯定有解 并且解是连续的一段数 证明: 假设有m个数 a1,a2,a3...am    s1 s2 s3...sm为前缀和 s1 = a1 s2 = a1+a2 s3 = a1+a2+a3... sm = a1+a2+a3+...+am 1.如果某个前缀和si%m == 0 那么得到解 2.设x1=s1%m x2 = s2%m x3 = s3%m xm = sm%m 因为1不成

POJ 2356. Find a multiple 抽屉/鸽巢原理

Find a multiple Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7192   Accepted: 3138   Special Judge Description The input contains N natural (i.e. positive integer) numbers ( N <= 10000 ). Each of that numbers is not greater than 15000

POJ 3370. Halloween treats 抽屉原理 / 鸽巢原理

Halloween treats Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7644   Accepted: 2798   Special Judge Description Every year there is the same problem at Halloween: Each neighbour is only willing to give a certain total number of sweets

poj 2356 Find a multiple(鸽巢原理)

Description The input contains N natural (i.e. positive integer) numbers ( N <= 10000 ). Each of that numbers is not greater than 15000. This numbers are not necessarily different (so it may happen that two or more of them will be equal). Your task i

POJ 3370 Halloween treats - 鸽巢原理

Description Every year there is the same problem at Halloween: Each neighbour is only willing to give a certain total number of sweets on that day, no matter how many children call on him, so it may happen that a child will get nothing if it is too l

POJ 3370 Halloween treats 鸽巢原理 解题

Halloween treats 和POJ2356差点儿相同. 事实上这种数列能够有非常多,也能够有不连续的,只是利用鸽巢原理就是方便找到了连续的数列.并且有这种数列也必然能够找到. #include <cstdio> #include <cstdlib> #include <xutility> int main() { int c, n; while (scanf("%d %d", &c, &n) && c) { i