https://codeforces.ml/contest/1428/problem/E
优先队列题,需要维护的东西是将一个萝卜拆成t份的获得值:
假设当前它被均分为t - 1份,则拆分为t份只需要多一次操作,也即上帝视角可以反悔。
这个获得值就是拆成t份与拆成t - 1份之后的二者平方和的差。
参考:https://blog.csdn.net/I_have_a_world/article/details/109151018
1 #include<bits/stdc++.h>
2 #define ll long long
3 using namespace std;
4
5 const ll N = 1e5 + 10;
6
7 struct node{
8 ll val, b, c;//val是多切一份的获得值,b是算作一份的总和,c是下一步即将分成的份数
9 bool operator < (const node &i)const{
10 return val < i.val;
11 }
12 };
13 priority_queue<node> q;
14
15 ll gv(ll a, ll x)
16 {//将a切成x份的结果
17 ll m = a / x, t = a % x;
18 return t * (m + 1) * (m + 1) + (x - t) * m * m;
19 }
20
21 int main(){
22 ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
23 ll n, k; cin >> n >> k;
24 ll ans = 0;
25 for(int i = 1 ; i <= n ; i++){
26 ll x; cin >> x;
27 q.push({gv(x, 1) - gv(x, 2), x, 2});
28 ans += x * x;
29 }
30 for(int i = 1 ; i <= k - n ; i++){
31 node now = q.top();
32 q.pop();
33 ll val = now.val, b = now.b, c = now.c;
34 ans -= val;
35 q.push({gv(b, c) - gv(b, c + 1), b, c + 1});
36 }
37 cout << ans << endl;
38
39 return 0;
40 }