标签:print 扑克 res ++ 一点 efi else for code
你有\(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\),你的任务是组成尽量多的套牌。每张牌最多只能用在一副套牌里(可以有牌不使用)。
转化一下题意就很好做了。
现在有\(n\)竹子(每根竹子有\(c_i\)节,每节竹子高度为 \(1\)),可以通过消耗一点法力值使某一根竹子的某两节之间再长出特殊的一节,现在有\(m\)点法力值,我需要在保证同一高度只能有不超过 \(1\)节特殊的竹节的情况下,使最矮的那根竹子高度尽可能的高。
所以直接二分答案就好了。
\(check\)里面就直接算出最短竹子长\(x\)时,要消耗的法力值\(sum\)。注意\(sum\)除了要\(\le{m}\),还要\(\le{x}\),因为同一高度只能有不超过 \(1\)节特殊的竹节。
#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;
}
标签:print 扑克 res ++ 一点 efi else for code
原文地址:https://www.cnblogs.com/andysj/p/13972423.html