Codeforces 731 F. Video Cards
题目大意:给一组数,从中选一个数作lead,要求其他所有数减少为其倍数,再求和。问所求和的最大值。
思路:统计每个数字出现的个数,再做前缀和,用于之后快速求和。将原数组排序后去重,枚举每一个数做lead的情况下,其余数减少后再求和的结果。不断维护最大值即可。
PS:这里用到了一个方便的函数unique()来去重,使用前需要先将数组排序,参数为数组的首地址和尾后地址,返回新的尾后地址。(该函数没有将重复的元素删除,只是放到了尾地址后面)可以用len=unique(a,a+n)-a得到去重后数组的长度。
附上代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
int a[maxn];
int cnt[maxn*2+5];
int main()
{
int n,i,j;
cin>>n;
for (i=0;i<n;++i)
{
scanf("%d",&a[i]);
cnt[a[i]]++;
}
for (i=1;i<maxn*2;++i)
{
cnt[i]+=cnt[i-1];
}
sort(a,a+n);
int len=unique(a,a+n)-a; //去重
ll ans=0;
for (i=0;i<len;++i)
{
ll sum=0;
for (j=2;(j-1)*a[i]<=a[len-1];++j)
{
int num=cnt[j*a[i]-1]-cnt[(j-1)*a[i]-1];
sum+=ll(num)*a[i]*(j-1);
}
ans=max(sum,ans);
}
cout<<ans;
return 0;
}