链接http://codeforces.com/problemset/problem/731/F
思路
筛思想+分块
对这俩理解都不是很透彻,看大牛的码吧。
1:这种方法不是很理解
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#define ll long long
using namespace std;
const int N = 2e5+10;
ll a[N];
bool vis[N];
int main(){
int n;
cin >> n;
for(int i = 0; i < n; i++)
cin >> a[i];
sort(a, a+n);
ll ans = a[n-1];
for(int i = 0; i < n; i++)
if(!vis[ a[i] ]){
ll tmp = 0;
for(ll j = a[i]; j <= a[n-1]; j += a[i])
vis[j] = true,
tmp += j*(lower_bound(a, a+n, j+a[i])-lower_bound(a, a+n, j));
if(tmp > ans)
ans = tmp;
}
cout << ans << endl;
return 0;
}
2,这种方法比较好理解
#include<bits/stdc++.h>
#define N 400001
#define ll long long
using namespace std;
int n,x,a[N],f[N];
ll ans;
int main()
{
cin>>n;
//桶排输入
while(n--)
scanf("%d",&x),a[x]++;
//f[i]表示大于等于i的数的个数
for(int i=200000;i;i--)
f[i]=f[i+1]+a[i];
for(int i=1;i<=200000;i++)
if(a[i])
{
ll sum=0;
for(int j=i;j<=200000;j+=i) //[ i , 2i) 之间的数按 i 来算
sum+=(ll)(f[j]-f[j+i])*j; //[ 2i , 3i)之间的数按2i 来算
ans=max(ans,sum); //... ....
}
cout<<ans;
}