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的值(这个i是我们假设的一个下标)
11 2、如果没有n的倍数的话,那就肯定至少有两个数取余于n的结果一样
12 是不是想问为什么?嘿嘿
13 你想一共有n个数,而且这里面没有n的倍数,那么都取余于n之后是没有0的
14 但是1——n这才一共n-1个数不相同,而你有n个数,那么我们上面的话就得以证明了^_^
15 
16 我们接着说,有了两个数取余于n结果一样,比如是1——i的前缀和 和 1——j的前缀和 取余于n的结果一样
17 那么i+1——j这一段所有数的和不久正是n的倍数嘛。
18 */
19 #include<stdio.h>
20 #include<string.h>
21 #include<iostream>
22 #include<algorithm>
23 using namespace std;
24 typedef long long ll;
25 const int maxn=10005;
26 int v[maxn],sum[maxn],p[15005];
27 int main()
28 {
29     
30     int n,flag=0;
31     scanf("%d",&n);
32     for(int i=1;i<=n;++i)
33     {
34         scanf("%d",&v[i]);
35         if(v[i]%n==0)
36         {
37             flag=i;
38         }
39         sum[i]=(v[i]+sum[i-1])%n;
40     }
41     if(flag)
42     {
43         printf("1\n%d\n",v[flag]);
44     }
45     else
46     {
47         for(int i=1;i<=n;++i)
48         {
49             if(p[sum[i]])
50             {
51                 printf("%d\n",i-p[sum[i]]);
52                 for(int j=p[sum[i]]+1;j<=i;++j)
53                     printf("%d\n",v[j]);
54                 flag=0;
55                 break;
56             }
57             else p[sum[i]]=i;
58             if(sum[i]==0)
59             {
60                 flag=i;
61                 break;
62             }
63         }
64         if(flag)
65         {
66             printf("%d\n",flag);
67             for(int i=1;i<=flag;++i)
68                 printf("%d\n",v[i]);
69         }
70     }
71     return 0;
72 }

 

posted @ 2020-03-31 13:54  kongbursi  阅读(214)  评论(0编辑  收藏  举报