Description
给定两个长度为 N 的非负整数序列 A,B。你需要通过 0 至 N 次以下的操作,使 A 变成 B(如果不行,报告无解;否则给出相应构造方案,注意你并不需要最小化操作次数):
- 选择两个整数 x,y (0≤x<y≤1018),对于所有 1≤i≤N,使 Ai←(Ai+x)mody。
Solution
容易发现无解的条件是存在 i,j,满足 ai=aj,bi=bj。
先按照 A 的大小对数组进行排序,考虑此时 B 递增时怎么做。
我们想要通过取模让最终的数组可以自由控制。注意到先操作小的再操作大的会对后面的产生影响,这是我们不想看到的,所以倒着做。
具体的,从大到小枚举 i,每次做 (xi,ai+xi) 操作,可以让当前最大的清零。做完一轮后 ai=∑j=1i−1xj,通过最终的数组解出 x 再做一遍 (b1,+∞) 操作即可做到 n+1 次。
考虑优化。注意到最后一次操作是没有意义的,因为只做前 n−1 次操作,数组是:
x2+x3+…+xn,0,x2,x2+x3,…,x2+x3+…+xn−1
显然同样可以通过 b 数组解出 x。
对于 b 不递增的情况可以让 bi←bi+∞×(i−1)。
时间复杂度:O(n)。
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
| #include <bits/stdc++.h>
#define int int64_t
const int kMaxN = 1e3 + 5, kInf = 1e12;
int n; int a[kMaxN], _a[kMaxN], b[kMaxN], x[kMaxN]; std::vector<std::pair<int, int>> res;
void work(int x, int y) { if (!y) return; x = (x % y + y) % y; res.emplace_back(x, y); for(int i = 1; i <= n; ++i) _a[i] = (_a[i] + x) % y; }
void dickdreamer() { std::cin >> n; std::vector<std::pair<int, int>> vec(n); for (auto &[x, y] : vec) std::cin >> x; for (auto &[x, y] : vec) std::cin >> y; std::sort(vec.begin(), vec.end()); for (int i = 1; i <= n; ++i) a[i] = _a[i] = vec[i - 1].first, b[i] = vec[i - 1].second;
for (int i = 1; i <= n; ++i) for (int j = i + 1; j <= n; ++j) if (a[i] == a[j] && b[i] != b[j]) return void(std::cout << "No\n"); if (n == 1) { std::cout << "Yes\n1\n" << (b[1] - a[1] + kInf) % kInf << ' ' << kInf << '\n'; return; } b[1] += (n - 1) * kInf; for (int i = 2; i <= n; ++i) b[i] += (i - 2) * kInf; x[n] = b[1] - a[1] - b[n]; for (int i = n; i > 2; --i) x[i - 1] = b[i] - b[i - 1]; int sum = 0; for (int i = n; i >= 2; --i) { work(x[i], a[i] + sum + x[i]); sum += x[i]; } work(b[2], kInf); std::cout << "Yes\n"; std::cout << (int)res.size() << '\n'; for (auto [x, y] : res) std::cout << x << ' ' << y << '\n'; }
int32_t main() { #ifdef ORZXKR freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0); int T = 1; while (T--) dickdreamer(); return 0; }
|