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'; }