19050 牛牛打气球
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: 不限定
Description
贝壳找房2021届校招算法卷3
有n个气球,每个气球都有一个坚韧度,牛牛有一把全屏武器,可以使每一个气球的坚韧度都下降b(坚韧度不会为负数),特别的:每次释放武器的时候,牛牛可以选择一个气球,使得这个气球多承受a点伤害。
牛牛想知道,最少释放几次武器,可以使得所有气球的坚韧度都变成0呢?
输入格式
第一行三个整数n,a,b。
第二行n个空格隔开的整数,第个数表示第i个气球的坚韧度。
n<=500000,其余所有整数都在[1,10^9]范围内。
输出格式
一个整数表示答案。
输入样例
3 1 2
1 4 5
输出样例
2
提示
第一次释放选择对第三个气球多承受1点伤害,三个气球的坚韧度变成:0 2 2 。第二次释放后所有气球的坚韧度都为0。
注意观察数据范围,这类问题在进行计算时,很容易会超过int范围,所以尽量采用long long类型来存储和计算。
思路:
1.二分法找到合适的释放武器次数x(下称攻击次数)
2.看在该攻击次数下,每个气球所需的特殊攻击数,即先判断x次b攻击减少的坚韧度是否大于气球坚韧度,否则的话,判断需要几次特殊攻击。
代码:
#include<iostream>
using namespace std;
long long A[500005];
long long n, a, b;
long long check(long long x)
{
long long specialsum = 0;//记录需要几次特殊攻击
for (int i = 1;i <= n;i++)
{
if (A[i] > x * b)specialsum = specialsum + (A[i] - x * b) / a + 1;//普通攻击不能使气球坚韧度降为0,计算需要的特殊攻击数,由于除以a之后取整了,故结果需加1
if ((A[i] > x * b)&&(A[i] - x * b) % a == 0)specialsum = specialsum - 1;//刚好整除的情况,减去多加的1
}
return specialsum <= x;
}
int main()
{
cin >> n >> a>>b ;//a是特殊攻击,b是普通攻击
for (long long i = 1;i <= n;i++)cin >> A[i];
//二分法
long long l = 1, r = 1e9, mid, best;
while (l <= r)
{
mid = (l + r) / 2;
// cout<<mid<<endl;
if (check(mid))best = mid, r = mid - 1;
else l = mid + 1;
}cout << best << endl;
return 0;
}