題解 P6786 【「SWTR-6」GCDs & LCMs】
阿新 • • 發佈:2020-08-26
Part1: 題目分析
觀察資料範圍\(n \leq 3 * 10^5\),正解時間複雜度應該是\(O(n)\)或\(O(n log n)\)級別的。
然後觀察式子\(b_i + b_j + gcd(b_i, b_j) = lcm(b_i, b_j)\)
首先,令\(gcd(b_i, b_j) = x\)。根據\(gcd\)的定義,\(b_i = ax\), \(b_j = bx\)
同樣,\(lcm(b_i, b_j) = b_ib_j / gcd(b_i, b_j) = abx^2 / x = abx\)
所以式子可以變成這樣: \(ax + bx + x = abx\),兩邊同時消去\(x\)
然後這樣變: \(ab - a - b + 1 = 2\longrightarrow (a - 1)(b - 1) = 2\)。因為 a、b 均為整數,且\(2 = 2 * 1\),所以可以直接算出a、b!
這裡我強制\(a < b\),解得\(a = 2, b = 3\)。
再觀察樣例1,符合結論。
現在問題可以化為這樣: 求一條數鏈\(a_1, a_2, a_3...a_x\),滿足\(a_{i - 1} : a_i = 2 : 3(2 \leq i \leq x)\),使得\(\sum _i^x a_i\) 最大。
這可以使用 DP 解決。
設狀態\(f(i)\) 表示以\(i\)結尾的數鏈的最大值。為了實現方便,我使用了 map。時間複雜度為\(O(n log Size)\)?Size應該為\(a_i\)值域?(bou 懂哦~ by tiger)(逃
Part2: Code
#include <cstdio> #include <algorithm> #include <map> const int N = 3e5; int a[N + 5], n; std::map<int, int> Cnt; std::map<int, long long> F; long long Ans; int main() { scanf("%d", &n); for(int i = 1; i <= n; i ++) scanf("%d", &a[i]), ++Cnt[a[i]]; std::sort(a + 1, a + 1 + n); for(int i = 1; i <= n; i ++) { F[a[i]] = 1ll * Cnt[a[i]] * a[i]; //重複的數字當然都可以選 if(!(a[i] % 3)) F[a[i]] += F[a[i] / 3 * 2]; Ans = std::max(Ans, F[a[i]]); } printf("%lld", Ans); return 0; }