http://www.fjutacm.com/Contest.jsp?cid=705#P4
其实想清楚了就很简单,之前想了很多种方法,以为是二分什么的,看起来就像是一个单峰函数。但是发现直接暴力一波就行了。
不知道有没有人会来搜到我的题解?ID是Yinku2017。
题意:求(x)使得(sumlimits_{i=1}^{n}[a_i/x]+a_i\%x)
首先把取余运算换成减法。提公因式。
(sumlimits_{i=1}^{n}[a_i/x]+a_i\%x=sumlimits_{i=1}^{n}{[a_i/x]+a_i-x[a_i/x]}=sumlimits_{i=1}^{n}a_i+sumlimits_{i=1}^{n}{(1-x)[a_i/x]})
发现什么?枚举x,根据某个n/1+n/2+n/3+...+n/n=nlogn的式子,前缀和计算出后半部分的值。恰好a_i最大就是1e6,可以这么搞,估计这道题已经设计好a_i就是1e6的。
小心溢出就可以了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
int a[1000005]={};
int pa[2000005]={};
int maxa=0;
ll sum=0;
ll minans=0;
int main() {
#ifdef Yinku
freopen("Yinku.in","r",stdin);
#endif // Yinku
scanf("%d",&n);
for(int i=1;i<=n;i++){
int t;
scanf("%d",&t);
if(t>maxa)
maxa=t;
sum+=t;
a[t]++;
}
for(int i=1;i<=maxa*2;i++){
pa[i]=pa[i-1]+a[i];
}
for(int d=2;d<=maxa;d++){
ll tminans=0;
int c=(maxa+d-1)/d;
for(int j=1;j<=c;j++){
if(j*d>maxa)
break;
tminans+=1ll*(pa[(j+1)*d-1]-pa[j*d-1])*j;
}
tminans*=(1ll-d);
if(minans>tminans)
minans=tminans;
}
printf("%lld
",sum+minans);
}