选数(鸽巢原理)
作者:互联网
#456. 选数
给定$n$个正整数$a_1, a_2, \dots, a_n$ 。 要求从其中选出若干数字, 使得这些数字的和$\bmod n = 0$ (对于每个下标最多只能选择一次)。
输入格式
第一行一个数字$n$, 表示数字个数。
接下来一行 $n$ 个整数 $a_1, a_2, \dots, a_n$ , 表示这$n$个数。
输出格式
第一行输出$M$, 表示选择的数的个数。
第二行输出$M$个正整数, 用空格隔开, 表示这些数字的下标。
如果有多种方案满足要求, 输出任意一种。
如果没有满足要求的方案 输出 $-1$。
样例输入
4
1 3 2 5
样例输出
2
2 4
样例解释
$3 + 5 = 8$, $8 \ \bmod \ 4 = 0$。
数据规模
所有数据保证 $1\leq n \leq 100000, 1 \leq a_i \leq 10^9$。
对序列求一次前缀和, 并且对n取模。
可以得知,任意数%n的结果有$0 \sim n - 1$,设$pre[0] = 0$。
那么$pre[0] \sim pre[n]$这n + 1个数一定有存在相同数(鸽巢原理)。
如果$pre[l] == pre[r] (l < r) $那么$[l + 1, r]$这个区间里面的所有数的和一定为n的倍数。(想一想为什么)
于是我们只需要输出区间里面的数就好了。
1 #include <iostream> 2 #include <vector> 3 #include <map> 4 #include <set> 5 #include <cmath> 6 #include <queue> 7 #include <stack> 8 #include <string> 9 #include <vector> 10 #include <cstring> 11 #include <iterator> 12 #include <algorithm> 13 using ll = long long; 14 using namespace std; 15 using PII = pair<int, int>; 16 const int MAXN = 5e5 + 7, mod = 998244353; 17 #define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end))) 18 #define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); } 19 20 void err(istream_iterator<string> it) {} 21 template<typename T, typename... Args> 22 void err(istream_iterator<string> it, T a, Args... args) { 23 cerr << *it << " = " << a << endl; 24 err(++it, args...); 25 } 26 27 int a[MAXN], pre[MAXN], n; 28 map<int, int> m; 29 void solve(){ 30 cin >> n; 31 for(int i = 1; i <= n; ++ i){ 32 cin >> a[i]; 33 (pre[i] = pre[i - 1] + a[i]) %= n; 34 } 35 m[0] = 0; 36 for(int i = 1; i <= n; ++ i){ 37 if(m.count(pre[i])){ 38 cout << i - m[pre[i]] << '\n'; 39 for(int j = m[pre[i]] + 1; j <= i; ++ j) 40 cout << j << ' '; 41 cout << '\n'; 42 return; 43 } 44 45 m[pre[i]] = i; 46 } 47 48 } 49 int main(){ 50 51 int T; 52 ll x, y; 53 ios::sync_with_stdio(false); 54 cin.tie(nullptr); 55 cout.tie(nullptr); 56 57 solve(); 58 59 return 0; 60 }View Code
标签:pre,输出,begin,end,选数,args,鸽巢,原理,include 来源: https://www.cnblogs.com/daremo/p/16275461.html