题目链接
实
测
可
以
通
过
!
\color{orange}{实测可以通过!}
实测可以通过!
题意
w
l
s
wls
wls有
n
n
n个二次函数
f
i
(
x
)
=
a
i
x
2
+
b
i
x
+
c
i
(
1
≤
i
≤
n
)
f_i(x)=a_ix^2+b_ix+c_i\ (1\le i\le n)
fi(x)=aix2+bix+ci (1≤i≤n)
现在他想在
∑
i
=
1
n
x
i
=
m
\sum_{i=1}^{n} x_i=m
∑i=1nxi=m 且
x
x
x为正整数的条件下求
∑
i
=
1
n
f
i
(
x
i
)
\sum_{i=1}^{n}f_i(x_i)
∑i=1nfi(xi)的最小值
请求出这个最小值。
数据范围
1
≤
n
,
m
≤
1
e
5
1\le n, m\le 1e5
1≤n,m≤1e5
1
≤
a
≤
1000
1\le a\le 1000
1≤a≤1000
−
1000
≤
b
,
c
≤
1000
-1000\le b, c\le 1000
−1000≤b,c≤1000
思路
我们观察这个数据范围,
a
a
a的值是
≥
0
\ge0
≥0的
从我们学过的二次函数知识来看,这是一个开口向上的函数
我们可以考虑一个函数的
x
x
x增加一的情况
增加的就是
a
(
x
+
1
)
2
+
b
(
x
+
1
)
+
c
−
(
a
x
2
+
b
x
+
c
)
=
2
a
x
+
a
+
b
a(x+1)^2+b(x+1)+c-(ax^2+bx+c)=2ax+a+b
a(x+1)2+b(x+1)+c−(ax2+bx+c)=2ax+a+b
而因为
a
a
a是大于
0
0
0的,所以我们分析这个
2
a
x
+
a
+
b
2ax+a+b
2ax+a+b一定随着
x
x
x的增加而增加
故而我们可以用一个优先队列,来存储每一个函数当前情况
+
1
+1
+1的增加结果
挑选m次,就可以了
推荐先每个函数初始值给
1
1
1,因为
x
≥
1
x\ge 1
x≥1
代码
#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;
}