HDU6546 Function题解

题目链接



\color{orange}{实测可以通过!}

题意

w l s wls 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)

现在他想在 i = 1 n x i = m \sum_{i=1}^{n} x_i=m x x 为正整数的条件下求 i = 1 n f i ( x i ) \sum_{i=1}^{n}f_i(x_i) 的最小值

请求出这个最小值。

数据范围

1 n , m 1 e 5 1\le n, m\le 1e5

1 a 1000 1\le a\le 1000

1000 b , c 1000 -1000\le b, c\le 1000

思路

我们观察这个数据范围, a a 的值是 0 \ge0

从我们学过的二次函数知识来看,这是一个开口向上的函数

我们可以考虑一个函数的 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 a 是大于 0 0 的,所以我们分析这个 2 a x + a + b 2ax+a+b 一定随着 x x 的增加而增加

故而我们可以用一个优先队列,来存储每一个函数当前情况 + 1 +1 的增加结果

挑选m次,就可以了

推荐先每个函数初始值给 1 1 ,因为 x 1 x\ge 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;
}

Thanks!

原创文章 23 获赞 41 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43537070/article/details/103325683