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)序列的和尽量大
[1leq nleq3 imes10^5\
1leq 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) = 3cdot 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 << '
';
}