2019CCPC 女生赛C 二次函数思维(水?)题(贪心)

2019CCPC 女生赛C 二次函数思维(水?)题(贪心)

题目:
Function
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 0 Accepted Submission(s): 0

Problem Description
wls 有 n 个二次函数 Fi(x) = aix2 + bix + ci (1 ≤ i ≤ n).
现在他想在∑ni=1xi = m 且 x 为正整数的条件下求∑ni=1Fi(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

根据题意,因为每个 x i x_{i} xi都是正整数,且 n < m n<m n<m,所以很自然的想到,将 x i x_{i} xi先赋一个1,存入ans中。那么接下来,我们应该维护一个 x i x_{i} xi 从1~2的增量。每次挑选这个增量最小的,加到ans中,在把该增量的下一个增量放进去。这个思路很明显了,用优先队列去维护即可。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#include <stack>
using namespace std;
typedef long long LL;
const int N = 100007;
const int mod = 1000000007;
const double pi = acos(-1);
const double db = 1;
const int INF = 0x3f3f3f3f;
#define  endl  '\n';
const double EPS = 1e-6;
LL read()
{
	LL x = 0, w = 1;
	char ch = 0;
	while (ch < '0' || ch>'9')
	{
		if (ch == '-')
		{
			w = -1;
		}
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9')
	{
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return w * x;
}

struct nod
{
	LL a, b, c;
}F[N];
struct vv
{
	int id;
	LL x, val;
	bool operator < (const vv& b)const
	{
		return val > b.val;
	}
};
LL solve(int i,LL x)
{
	LL ans = F[i].a * x * x + F[i].b * x + F[i].c;
	return ans;
}
priority_queue < vv > q;
int main()
{
	std::ios::sync_with_stdio(0);
	std::cin.tie(0);
	std::cout.tie(0);
	LL n, m;
	cin >> n >> m;
	LL ans = 0;
	for (int i = 1; i <= n; ++i)
	{
		int a, b, c;
		cin >> a >> b >> c;
		F[i].a = a;
		F[i].b = b;
		F[i].c = c;
		vv tmp;
		tmp.id = i;
		tmp.x = 1;
		tmp.val = solve(i, 1);
		ans += tmp.val;
		tmp.x = 2;
		tmp.val = solve(i, 2) - solve(i, 1);
		q.push(tmp);
	}
	m -= n;
	for (int i = 1; i <= m; ++i)
	{
		vv tmp = q.top();
		q.pop();
		ans += tmp.val;
		tmp.val = solve(tmp.id, tmp.x + 1) - solve(tmp.id, tmp.x);
		tmp.x++;
		q.push(tmp);
	}
	cout << ans << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值