码迷,mamicode.com
首页 > 其他好文 > 详细

[Luogu] P5815 [CQOI2010]扑克牌

时间:2020-11-19 12:27:48      阅读:4      评论:0      收藏:0      [点我收藏+]

标签:print   扑克   res   ++   一点   efi   else   for   code   

Description

你有\(n\)种牌,第\(i\)种牌的数目为\(c_i\)?。另外有一种特殊的牌\(joker\),它的数目是\(m\)。你可以用每种牌各一张来组成一套牌,也可以用一张\(joker\)和除了某一种牌以外的其他牌各一张组成\(1\)套牌。比如,当\(n=3\)时,一共有\(4\)种合法的套牌:\(,,,\{1,2,3\},\{J,2,3\},\{1,J,3\},\{1,2,J\}\)

给出\(n\)\(m\)\(c_i\),你的任务是组成尽量多的套牌。每张牌最多只能用在一副套牌里(可以有牌不使用)。

Solution

转化一下题意就很好做了。

现在有\(n\)竹子(每根竹子有\(c_i\)节,每节竹子高度为 \(1\)),可以通过消耗一点法力值使某一根竹子的某两节之间再长出特殊的一节,现在有\(m\)点法力值,我需要在保证同一高度只能有不超过 \(1\)节特殊的竹节的情况下,使最矮的那根竹子高度尽可能的高。

所以直接二分答案就好了。

\(check\)里面就直接算出最短竹子长\(x\)时,要消耗的法力值\(sum\)。注意\(sum\)除了要\(\le{m}\),还要\(\le{x}\),因为同一高度只能有不超过 \(1\)节特殊的竹节。

Code

#include <bits/stdc++.h>

using namespace std;

#define ll long long

int n, m, res, l, r, mn = 2e9, c[55];

int read()
{
	int x = 0, fl = 1; char ch = getchar();
	while (ch < ‘0‘ || ch > ‘9‘) { if (ch == ‘-‘) fl = -1; ch = getchar();}
	while (ch >= ‘0‘ && ch <= ‘9‘) {x = (x << 1) + (x << 3) + ch - ‘0‘; ch = getchar();}
	return x * fl;
}

int check(int x)
{
	ll sum = 0ll;
	for (int i = 1; i <= n; i ++ )
		sum += max((x - c[i]), 0);
	return sum <= min(x, m);
}
 
int main()
{
	n = read(); m = read();
	for (int i = 1; i <= n; i ++ ) c[i] = read(), mn = min(mn, c[i]);
	l = 0; r = 2e9;
	while (l <= r)
	{
		int mid = (l + r) >> 1;
		if (check(mid)) res = mid, l = mid + 1;
		else r = mid - 1;
	}
	printf("%d\n", res);
	return 0;
}

[Luogu] P5815 [CQOI2010]扑克牌

标签:print   扑克   res   ++   一点   efi   else   for   code   

原文地址:https://www.cnblogs.com/andysj/p/13972423.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!