Description
给定长度为 N 的正整数序列 {Ai},满足 Ai 单调升。
问是否能将 {Ai} 重排为序列 {xi},满足:
令 yi=LCM(x1,…,xi),∀1≤i<N,yi<yi+1(即 yi 单调升)。
$ 1\ \leq\ N\ \leq\ 100,2\ \leq\ A_1\ <\ A_2\ \cdots\ <\ A_N\ \leq\ 10^{18} $
Solution
直接构造显然很难,但是注意到一件事情,就是如果一个序列 B1,…,BN 合法,那么如果把 Bi 放到最后能使得 yN−1<yN,则整个序列依然合法。
所以每次从后往前确定数,找到能够满足 yN−1<yN 的 Ai 放到最后面,只要每次都能找到就一定合法。
时间复杂度:O(N3logV)。
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
| #include <bits/stdc++.h>
#define int int64_t
const int kMaxN = 105;
int n; int a[kMaxN], res[kMaxN];
void dickdreamer() { std::cin >> n; for (int i = 1; i <= n; ++i) std::cin >> a[i]; for (int i = n; i; --i) { for (int j = i; j; --j) { std::swap(a[i], a[j]); int lcm = 1; bool fl = 1; for (int k = 1; k < i; ++k) { int val = std::__gcd(a[k], a[i]); lcm = lcm / std::__gcd(lcm, val) * val; if (lcm % a[i] == 0) { fl = 0; break; } } if (fl) break; else if (j == 1) return void(std::cout << "No\n"); std::swap(a[i], a[j]); } } std::cout << "Yes\n"; for (int i = 1; i <= n; ++i) std::cout << a[i] << ' '; }
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; }
|