E. Carrots for Rabbits
链接:https://codeforces.com/contest/1428/problem/E
题目:
有n个数,把n个数分成k份,使得这k个数的平方和最小
思路:
首先发现一个数分的越多,那么这个平方和越小
设函数fi(x)表示将a[i]分成y份的平方和,我们发现一开始都是fi(1),这样我就分了n个数了,然后,每个fi函数都有一个减少率fi(x+1)-fi(x),用优先队列保存,从n+1到k开始,每次分都去找最大的减少率的fi函数,让它的x+1。
吐槽:
函数,贪心,优先队列。
出题人前几天是不是刚打完atcoder?
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e5+7;
int a[maxn];
struct Fun{
int all, div, dy;
bool operator < (const Fun &f1) const {
return dy < f1.dy;
}
};
int f(int all, int x) {
int tmp = all % x;
return (x - tmp)*(all/x)*(all/x) + tmp*(all/x + 1)*(all/x + 1);
}
priority_queue<Fun> q;
signed main()
{
int n, k;
cin >> n >> k;
for(int i = 1; i <= n; i++) {
cin >> a[i];
}
int ans = 0;
for(int i = 1; i <= n; i++) {
ans = ans + 1ll*a[i]*a[i];
Fun tmp;
tmp.all = a[i];
tmp.div = 1;
tmp.dy = f(tmp.all, tmp.div) - f(tmp.all, tmp.div+1);
if(tmp.div + 1 > tmp.all) continue;
q.push(tmp);
}
for(int i = n+1; i <= k; i++) {
Fun tp = q.top();
q.pop();
ans = ans - tp.dy;
tp.div = tp.div + 1;
tp.dy = f(tp.all, tp.div) - f(tp.all, tp.div + 1);
if(tp.div + 1 > tp.all) continue;
q.push(tp);
}
cout << ans << '\n';
}