Function

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 219    Accepted Submission(s): 85



Problem Description

wls 有 n 个二次函数 Fi (x ) = ai x2 + bi x + ci (1 ≤ i ≤ n ).
现在他想在∑ni=1 xi = m 且 x 为正整数的条件下求∑ni=1 Fi (xi )的最小值。
请求出这个最小值。


Input

第一行两个正整数 n , m 。
下面 n 行,每行三个整数 a , b , c 分别代表二次函数的二次项,一次项,常数项系数。
1 ≤ n ≤ m ≤ 100, 000
1 ≤ a ≤ 1, 000
− 1, 000 ≤ b , c ≤ 1, 000


Output

一行一个整数表示答案。


Sample Input

2 3 1 1 1 2 2 2


Sample Output

13




【题解】

对f(x)求导,发现是导函数为递增函数,则每次把f(x+1)-f(x)的值放入优先队列,x为当前分配量。类似差分贪心

由于x必须为正整数,所以所有的x初始值为1

【代码】

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 1e5+10;

struct Node
{
int a, b, c;
int x;
ll sum, sub;
bool operator < (const Node& that) const
{
return this->sub > that.sub;
}
void Update()
{
sum = a*x*x+b*x+c;
sub = a*(x+1)*(x+1)+b*(x+1)+c-sum;
}
Node(int aa, int bb, int cc, int xx):a(aa), b(bb), c(cc),x(xx){}
};
int n, m;

int main()
{
scanf("%d %d", &n, &m);
int a, b, c;
priority_queue<Node> que;
for (int i = 1;i <= n;i++)
{
scanf("%d %d %d", &a, &b, &c);
Node node(a, b, c, 1);
node.Update();
que.push(node);
}
ll res = 0;
m -= n;
while (m--)
{
Node now = que.top();
que.pop();
now.x++;
now.Update();
que.push(now);
}
while (!que.empty())
{
res += que.top().sum;
que.pop();
}
printf("%lld\n", res);

return 0;
}