https://codeforces.com/problemset/problem/731/F
【题意】
有n个数,从里面选出来一个作为第一个,然后剩下的数要满足是这个数的倍数,如果不是,只能减小为他的倍数,否则就舍弃掉,然后把没有舍弃的数的值加起来,求和的最大值;
【思路】
计数一下每个值的个数,然后维护一个前缀
遍历每一个数作为最小的数,枚举它的倍数i,i+1,记录之间的数的个数,记录贡献
【代码】
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll maxn = 5e5 + 5;
ll a[maxn], c[maxn], b[maxn], cnt;
void f() {
for (ll i = 1; i < maxn; i++) {
if (c[i]) {
b[++cnt] = i;
}
c[i] += c[i - 1];
}
}
int main() {
ll n;
while (~scanf("%lld", &n)) {
for (ll i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
c[a[i]]++;
}
f();
ll ans = 0;
for (ll i = 1; i <= cnt; i++) {
ll res = 0;
ll x = b[i];
for (ll j = x + x; j <= b[cnt] + x; j += x) {
ll l = j - x;
ll r = j -1;
res += (c[r] - c[l - 1])*(j - x);
}
ans = max(ans, res);
}
printf("%lld\n", ans);
}
}