传送门:F. Video Cards
描述:
给一个n长度的序列,问从序列中找一个数,把不小于它的数变成它或者它的倍数,并使得这些数的和最大
思路:
序列中的数最大为200000 ,我们可以枚举i(1<=i<=200000)作为base,然后枚举i的倍数j分段去累加就好了,类似于素数筛的思想,再加上前缀和处理一下
复杂度:
O(nlogn)
代码:
#include <bits/stdc++.h>
#define ll __int64
#define rep(i,k,n) for(int i=k;i<=n;i++)
using namespace std;
template<class T> void read(T&num) {
char CH; bool F=false;
for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p) {
if(!p) { puts("0"); return; }
while(p) stk[++ tp] = p%10, p/=10;
while(tp) putchar(stk[tp--] + '0');
putchar('\n');
}
const int N=2e5+10;
int cnt[N],n, m=2e5;
ll ans, tmp;
int main(){
read(n);
int x;
rep(i, 1, n)read(x), cnt[x]++;
rep(i, 1, m)cnt[i] += cnt[i-1];
rep(i, 1, m){
if(cnt[i]-cnt[i-1]){
tmp=0;
for(int j=0; j<=m; j+=i)tmp += (ll)j*(cnt[min(j+i-1, m)] - cnt[j-1]);
ans = max(ans, tmp);
}
}
print(ans);
return 0;
}