题目链接
题意
有
个二次函数
现在他想在
且
为正整数的条件下求
的最小值
请求出这个最小值。
数据范围
思路
我们观察这个数据范围,
的值是
的
从我们学过的二次函数知识来看,这是一个开口向上的函数
我们可以考虑一个函数的
增加一的情况
增加的就是
而因为
是大于
的,所以我们分析这个
一定随着
的增加而增加
故而我们可以用一个优先队列,来存储每一个函数当前情况
的增加结果
挑选m次,就可以了
推荐先每个函数初始值给
,因为
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cctype>
#include <map>
#include <set>
#include <queue>
#include <vector>
#include <iostream>
#include <cmath>
#define pk putchar(' ')
#define ph puts("")
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
template <class T>
void rd(T &x)
{
x = 0;
ll f = 1;
char c = getchar();
while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
x *= f;
}
template <class T>
void pt(T x)
{
if (x < 0)
putchar('-'), x = (~x) + 1;
if (x > 9)
pt(x / 10);
putchar(x % 10 ^ 48);
}
template <class T>
T Max(T a, T b)
{
return a > b ? a : b;
}
template <class T>
T Min(T a, T b)
{
return a < b ? a : b;
}
template <class T>
T Fabs(T x)
{
return x < 0 ? -x : x;
}
const int N = 1e5 + 5;
const ll INF = (1ll << 60);
int n, m, k;
ll ans;
// 选到第i个,总和为k的最小值
struct node
{
ll a, b, c, val, cha, x;
// sy是对称轴
bool operator < (const node &x)
const{
return cha > x.cha;
}
void update()
{
val = a * x * x + b * x + c;
cha = 2 * a * x + a + b;
}
};
priority_queue<node> Que;
// 从对称轴往两边走,x与对称轴差越大,其增长越快
// 在a都为整数的情况下,a越大的其增大速度越快
int main()
{
freopen("function.in", "r", stdin);
freopen("function.out", "w", stdout);
rd(n), rd(m);
m -= n;
for (int i = 1;i <= n; i++)
{
node t;
rd(t.a), rd(t.b), rd(t.c);
t.x = 1;
t.update();
Que.push(t);
}
while (m)
{
m--;
node t = Que.top();
Que.pop();
t.x++;
t.update();
Que.push(t);
}
while (!Que.empty())
{
node t = Que.top();
Que.pop();
ans += t.val;
}
pt(ans);
return 0;
}