题目链接:点击这里
题意:给出n个数字,可以选中一个数字,然后把其他的数都减成这个数字的倍数。求所有数字的和最大值。
假设选中数字a,容易发现在区间 [a∗k,a∗(k+1)−1] 中的数字对答案的贡献是一样的。所以只需要维护一个统计数字的前缀和,每次暴力枚举选中的数字(注意不要重复枚举),然后暴力按照按照相同的区间网上跳即可。因为每次跳的步长等于a,容易证明复杂度是 Max1+Max2+⋯+MaxMax=O(Max∗lg(Max)) .
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
#define maxn 200005
long long sum[maxn];
long long a[maxn];
int n;
int main () {
ios::sync_with_stdio (0);
cin >> n;
memset (sum, 0, sizeof sum);
long long Max = 0;
for (int i = 1; i <= n; i++) cin >> a[i], sum[a[i]]++, Max = max (Max, a[i]);
sort (a+1, a+1+n);
for (int i = 1; i < maxn; i++) sum[i] += sum[i-1];
if (a[1] == 1) {
long long res = 0;
for (int i = 1; i <= n; i++) res += a[i];
cout << res << endl;
return 0;
}
long long ans = 0;
for (int i = 1; i <= n; i++) {
if (i > 1 && a[i] == a[i-1]) continue;
long long tmp = 0;
int jj;
for (int j = 1; j <= Max; j = jj+1) {
if (j == 1) jj = a[i]-1;
else jj = min (Max, j+a[i]-1);
tmp += 1LL*(j/a[i])*a[i]*(sum[jj]-sum[j-1]);
}
ans = max (ans, tmp);
}
cout << ans << endl;
return 0;
}