Dual (Hard Version) Created by LXC on Fri Apr 12 09:48:37 2024
https://codeforces.com/problemset/problem/1854/A2
ranting: 1900
tag: constructive algorithms, math
problem 有 $t$($1\le t\le 500$)组数据,对于每组数据给出一个长度为 $n$($1\le n\le 20$)的序列 $a$($-20\le a_i\le 20$)。
可以进行 $k$($0\le k\le 31$)次操作,每次操作任选一组 $i,j$($1\le i,j\le n$),把 $a_i\leftarrow a_i+a_j$,最后使得整个序列单调不减。
对于每组数据,第一行输出 $k$,之后 $k$ 行输出执行操作的 $i,j$。
solution 对于全是正数或负数的情况,只需要n-1次操作,可以使得非降序。
存在正数或负数,我们尝试转化为全正数或负数。
找到最大值mx和最小值mn
如果$|mx| > |mn|$,我们现在考虑最糟糕的情况,有20个数,然后最后需要19次操作变为非降序。现在还剩下31-20=12次操作。也就是说,负数最多只能有12个。我们就可以每一次操作用最大的正整数加到负数上使得一个负数变非负数。如果负数超过12个,那么正数个数就不超过7个,对于任意负数其必小于等于-1,而-1只需5次倍增可以达到-32,($-1,-2,-4,-8,-16,-32$),$|-32|>mx$。于是剩余的至少7次操作可以将至多7个正数变为非正数。
对于$|mx| \le |mn|$同理。
code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 #include <bits/stdc++.h> #define ll long long #define ull unsigned long long #define N 500005 #define MOD 998244353 using namespace std;random_device seed; ranlux48 engine (seed()) ;int random (int l, int r) { uniform_int_distribution<> distrib (l, r); return distrib (engine); } template <class t ,class u > ostream& operator <<(ostream& os,const pair<t,u>& p) { return os<<'[' <<p.first<<", " <<p.second<<']' ; } template <class t > ostream& operator <<(ostream& os,const vector<t>& v) { os<<'[' ; int s = 1 ; for (auto e:v) { if (s) s = 0 ; else os << ", " ; os << e; } return os<<']' ; } template <class t ,class u > ostream& operator <<(ostream& os,const map<t,u>& mp){ os<<'{' ; int s = 1 ; for (auto [x,y]:mp) { if (s) s = 0 ; else os << ", " ; os<<x<<": " <<y; } return os<<'}' ; } void sol () { int n; cin >> n; vector<int > a (n) ; int neg = 0 , pos = 0 , mx = 0 , mn = 0 ; for (auto & i:a) { cin >> i; if (i<0 ) neg++; if (i>0 ) pos++; } for (int i=0 ; i<n; i++) { if (a[mx] < a[i]) mx = i; if (a[mn] > a[i]) mn = i; } vector<pair<int ,int >> ans; if (pos == 0 ) { for (int i=n-2 ; i>=0 ; i--) { ans.emplace_back (i, i+1 ); } } else if (neg == 0 ) { for (int i=1 ; i<n; i++) { ans.emplace_back (i, i-1 ); } } else if (a[mx] + a[mn] < 0 ) { if (pos <= 12 ) { for (int i=0 ; i<n; i++) { if (a[i] > 0 ) { ans.emplace_back (i, mn); } } for (int i=n-2 ; i>=0 ; i--) { ans.emplace_back (i, i+1 ); } } else { for (int i=0 ; i<5 ; i++) { ans.emplace_back (mx, mx); } for (int i=0 ; i<n; i++) { if (a[i] < 0 ) { ans.emplace_back (i, mx); } } for (int i=1 ; i<n; i++) { ans.emplace_back (i, i-1 ); } } } else { if (neg <= 12 ) { for (int i=0 ; i<n; i++) { if (a[i] < 0 ) { ans.emplace_back (i, mx); } } for (int i=1 ; i<n; i++) { ans.emplace_back (i, i-1 ); } } else { for (int i=0 ; i<5 ; i++) { ans.emplace_back (mn, mn); } for (int i=0 ; i<n; i++) { if (a[i] > 0 ) { ans.emplace_back (i, mn); } } for (int i=n-2 ; i>=0 ; i--) { ans.emplace_back (i, i+1 ); } } } cout << ans.size () << "\n" ; for (auto [x,y]:ans) { cout << x+1 << " " << y+1 << "\n" ; a[x] += a[y]; } } int main () { cout << setprecision (15 ) << fixed; ios::sync_with_stdio (false ); cin.tie (0 ); cout.tie (0 ); #ifndef SINGLE_INPUT int t; cin >> t; while (t--) { sol (); } #else sol (); #endif return 0 ; }