1. 程式人生 > 實用技巧 >題解 P6786 【「SWTR-6」GCDs & LCMs】

題解 P6786 【「SWTR-6」GCDs & LCMs】

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\)

變為\(a + b + 1 = ab\)

然後這樣變: \(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;
}