P6786 GCDs & LCMs 数学推导
P6786 GCDs & LCMs 数学推导
题意
给定一段序列\(a\),要求从中找出一些数组成序列\(b\)满足:
\(b_i\)是\(b\)中最大值或者存在一个位置\(j\),使得\(b_j > b_i\),且\(b_i + b_j + gcd(b_i,b_j) = lcm(b_i,b_j)\)
并且希望这个\(b\)序列的和尽量大
\[1\leq n\leq3\times10^5\\
1\leq a_i \leq 10^9
\]
分析
一开始不太想得到
不妨设\(x < y\)
有
\[x + y + gcd(x,y) < x + y + y = x + 2 \cdot y < 3 \cdot y\\
显然x + y + gcd(x,y) > y\\
又y|lcm(x,y) \\于是有x + y + gcd(x,y) = 2y
于是lcm(x,y) = 3\cdot y\\
代入原式即
y = 3 / 2 \cdot x
\]
于是只需要用\(map\)for一遍枚举最小值即可
代码
map<int, int> mp;
int a[300005];
int main() {
ll res = 0;
int n = readint();
for (int i = 1; i <= n; i++)
a[i] = readint(), mp[a[i]]++;
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i++) {
ll tmp = a[i];
ll cnt = 0;
while (mp[tmp]) {
cnt += tmp * mp[tmp], mp[tmp] = 0;
if (tmp % 2 == 0) tmp = tmp / 2 * 3;
else break;
}
res = max(res, cnt);
}
cout << res << '\n';
}