Solution
显然,题目要让我们最小化:
∑ i = 1 n ⌊ a i k ⌋ + ∑ i = 1 n a i m o d k \sum_{i=1}^n \lfloor \frac {a_i} k \rfloor+\sum_{i=1}^n a_i\ mod\ k ∑i=1n⌊kai⌋+∑i=1nai mod k
= ∑ i = 1 n ⌊ a i k ⌋ + ∑ i = 1 n ( a i − k ( ⌊ a i k ⌋ ) ) =\sum_{i=1}^n \lfloor \frac {a_i} k \rfloor+\sum_{i=1}^n (a_i-k(\lfloor \frac {a_i} k \rfloor)) =∑i=1n⌊kai⌋+∑i=1n(ai−k(⌊kai⌋))
= ∑ i = 1 n ⌊ a i k ⌋ + ∑ i = 1 n a i − k ∑ i = 1 n ( ⌊ a i k ⌋ ) =\sum_{i=1}^n \lfloor \frac {a_i} k \rfloor+\sum_{i=1}^n a_i-k\sum_{i=1}^n(\lfloor \frac {a_i} k \rfloor) =∑i=1n⌊kai⌋+∑i=1nai−k∑i=1n(⌊kai⌋)
= ∑ i = 1 n a i − ( k − 1 ) ∑ i = 1 n ⌊ a i k ⌋ =\sum_{i=1}^n a_i-(k-1) \sum_{i=1}^n \lfloor \frac {a_i} k \rfloor =∑i=1nai−(k−1)∑i=1n⌊kai⌋
即,我们要让 ( k − 1 ) ∑ i = 1 n ⌊ a i k ⌋ (k-1) \sum_{i=1}^n \lfloor \frac {a_i} k \rfloor (k−1)∑i=1n⌊kai⌋越小越好。于是,我们可以暴力枚举 k k k,然后对这个式子用整除分块优化。
故时间复杂度为 O ( ∑ i = 1 n ⌊ n i ⌋ ) O(\sum_{i=1}^n \lfloor \frac n i \rfloor) O(∑i=1n⌊in⌋),即 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)。
注意本题轻微卡常,强制使用快读。
Code
#include <bits/stdc++.h>
#define int long long
#define rg register
using namespace std;
const int maxlen=1000000;
int n,tot=0,ans=1e15+7,maxv;
int a[2*maxlen+5],v[2*maxlen+5],pre[2*maxlen+5];
inline int read()
{
int s=0,w=1;
char ch=getchar();
while (ch<'0'||ch>'9')
{
if (ch=='-') w=-w;
ch=getchar();
}
while (ch>='0'&&ch<='9')
{
s=(s<<1)+(s<<3)+(ch^'0');
ch=getchar();
}
return s*w;
}
signed main()
{
cin>>n;
for (int i=1;i<=n;i++)
{
a[i]=read();
v[a[i]]++;
maxv=max(maxv,a[i]);
}
for (int i=1;i<=2*maxv;i++) pre[i]=pre[i-1]+v[i];
for (int i=1;i<=n;i++) tot+=a[i];
for (rg int k=1;k<=maxv;k++)
{
int now=0;
for (rg int j=k;j<=maxv;j+=k) now+=(pre[j+k-1]-pre[j-1])*(j/k);
ans=min(ans,tot-(k-1)*now);
}
cout<<ans<<endl;
return 0;
}