CodeForces-731F Video Cards 数论,分块
CodeForces-731F Video Cards 数论,分块
题意
给出一个长度为\(n\)的数组\(a\) ,在数组中选择一个元素作为\(leading\) 。
其他元素可以减去任意大小。
问最大的【改变后的数组和】是多少。
数组要求满足:除了\(leading\) 外的元素都是\(leading\) 的倍数
\[1\leq n \leq 200000
\\
1\leq a_i \leq 200000
\]
分析
一个数要减小肯定贪心的减小到恰好是\(d \times a_1\) ,其中$(d + 1) \times a_1 > a $
那么不妨对于枚举\(1 \cdot a_1 , 2 \cdot a_1 ....i \cdot a_1\) 相当于对倍数分块,计算每个块的数的大小。
而快速计算每一块的大小只需计算一遍前缀和就好了,我们考虑最坏情况,\(a_{min} = 1,a_{max} = 200000\) 也只需要\(O(n)\) 的复杂度。
最坏复杂度显然是\(O(nlogn)\) 的。
代码
int vis[maxn];
ll a[maxn];
int main() {
ll Max = -1;
ll res = 0;
int n = readint();
for (int i = 0; i < n; i++) {
ll tmp = readll();
vis[tmp]++;
Max = max(Max, tmp);
}
for (int i = 1; i < maxn; i++)
a[i] = a[i - 1] + vis[i];
for (int i = 1; i <= Max; i++) {
if (!vis[i]) continue;
ll tmp = 0;
for (int j = i; j <= Max; j += i)
if (j + i - 1 < maxn)
tmp += (a[j + i - 1] - a[j - 1]) * j;
res = max(res, tmp);
}
Put(res);
}