题目传送门: http://codeforces.com/contest/731/problem/F
题意: 给n个数(n<=20W),从中找一个数,然后在数组中将值为该数倍数的数全部加起来,如果不是该数的倍数,则减去一定的数使其变为该数的倍数。然后找最大的和
思路:先排个序,从第一个数开始遍历,从k=1开始找在[a*k,a*k+1)之间的数目j,a*k*j即为该段数的和,查找时可以用二分
代码如下:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <stdio.h>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <vector>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
#define ull unsigned long long
#define mem(n,v) memset(n,v,sizeof(n))
#define MAX 200005
#define MAXN 1000005
#define PI 3.1415926
#define E 2.718281828459
#define opnin freopen("text.in.txt","r",stdin)
#define opnout freopen("text.out.txt","w",stdout)
#define clsin fclose(stdin)
#define clsout fclose(stdout)
#define haha1 cout << "haha1"<< endl
#define haha2 cout << "haha2"<< endl
#define haha3 cout << "haha3"<< endl
const int INF = 0x3f3f3f3f;
const ll INFF = 0x3f3f3f3f3f3f3f3f;
const double pi = 3.141592653589793;
const double inf = 1e18;
const double eps = 1e-8;
const ll mod = 1e9+7;
const ull mx = 133333331;
ll a[MAX];
int vis[MAX];
int main()
{
mem(a,0);
mem(vis,0);
int n;
cin >> n;
for(int i=1;i<=n;i++){
scanf("%I64d",&a[i]);
}
sort(a+1,a+n+1);
ll sum = 0,sum1;
for(int i=1;i<=n;i++){
if(vis[a[i]]) continue;
vis[a[i]] = 1;
sum1 = 0;
int x = 0,y = 1;
for(ll j=a[i];j<=a[n];j+=a[i]){
x = lower_bound(a+y,a+n+1,j) - a;
y = lower_bound(a+y,a+n+1,j+a[i]) - a;
// cout << j << ' ' << x << ' ' << y << endl;
sum1 += j * (y-x);
// cout << sum1 << endl;
}
// cout << endl;
sum = max(sum,sum1);
}
cout << sum << endl;
}