LQ0142 技能升级二分

Posted 海岛Blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LQ0142 技能升级二分相关的知识,希望对你有一定的参考价值。

题目来源:蓝桥杯2022初赛 C++ C组I题

题目描述
小蓝最近正在玩一款RPG 游戏。他的角色一共有N个可以加攻击力的技能。
其中第i个技能首次升级可以提升Ai点攻击力,以后每次升级增加的点数都会减少Bi。
⌈Ai/Bi⌉ (向上取整) 次之后,再升级该技能将不会改变攻击力。
现在小蓝可以总计升级M次技能,他可以任意选择升级的技能和次数。
请你计算小蓝最多可以提高多少点攻击力?

输入格式
输入第一行包含两个整数N和M。
以下N行每行包含两个整数Ai和Bi。
对于40% 的评测用例,1 ≤ N, M ≤ 1000;
对于60% 的评测用例,1 ≤ N ≤ 10^4; 1 ≤ M ≤ 10^7;
对于所有评测用例,1 ≤ N ≤ 10^5,1 ≤ M ≤ 2 × 10^9,1 ≤ Ai; Bi ≤ 10^6。

输出格式
输出一行包含一个整数表示答案。

输入样例
3 6
10 5
9 2
8 1

输出样例
47

问题分析
用二分法来解决。

AC的C++语言程序如下:

/* LQ0142 技能升级 */

#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

const int N = 100000;
int n, m;
long long a[N], b[N], t[N];

bool judge(long long x)

    long long cnt = 0;
    for (int i = 0; i < n; i++)
        if (a[i] >= x) 
            cnt += (a[i] - x) / b[i] + 1;
            if (cnt >= m) return true;
        
    return false;


int main()

    long long tcnt = 0;
    cin >>n >> m;
    for (int i = 0; i < n; i++) 
        cin >> a[i] >> b[i];
        tcnt += a[i] / b[i] + (a[i] % b[i] ? 1 : 0);
    

    m = tcnt < m ? tcnt : m;

    int l = 0, r = *max_element(a, a + n) + 1;
    while (l < r) 
        int mid = (l + r + 1) / 2;
        if (judge(mid)) l = mid;
        else r = mid - 1;
    

    long long ans = 0;
    for (int i = 0; i < n; i++)
        if (a[i] >= l) 
            int cnt = (a[i] - l) / b[i] + 1;
            int last = a[i] - (cnt - 1) * b[i];
            if (last == l) 
                cnt--;
                last += b[i];
            
            ans += (a[i] + last) * cnt / 2;
            m -= cnt;
        

    cout << ans + m * l << endl;

    return 0;

以上是关于LQ0142 技能升级二分的主要内容,如果未能解决你的问题,请参考以下文章

第十三届蓝桥杯省赛 C++ C 组 I 题Python B 组 H题——技能升级(AC)

LQ0101 扫地机器人二分

LQ0058 递增三元组二分

LQ0138 分巧克力二分法

面向对象 之 炮塔游戏(继承,对象存储到列表)

LeetCode 0142.环形链表 II