[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
", i);
14             for(int j = 1; j <= i; j++) {
15                 printf("%lld
", 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
", i - vis[s[i]]);
24             for(int j = vis[s[i]] + 1; j <= i; j++) {
25                 printf("%lld
", 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 }
原文地址:https://www.cnblogs.com/kirai/p/6862764.html