【蓝桥杯每日一题】技能升级

技能升级

2024-12-10 蓝桥杯每日一题 技能升级 二分

题目大意

一个角色有 N 种可以增加攻击力的技能,对于第 i 个技能首次升级可以提升 A i A_i Ai 点攻击力,随后的每次升级增加的攻击力都会减少 B i B_i Bi 。升级 ⌈ A i B i ⌉ \lceil \frac{A_i}{B_i} \rceil ⌈BiAi⌉ (向上取整)的次数之后就不会再升级。

最终小蓝可以总计升级 M 次技能,计算这个角色最后可以体高多少攻击力?

解题思路

以下分为两点来讲解,一个 40 分,一个100分。

40 分

对于蓝桥杯来说,暴力拿分是一定要会的。

对于这个题来说,每一个技能的提升都是一个递减的等差数列,然后想要在M次升级中让这个角色的攻击力得到最大的提升,必须要找到前 M 个大的升级点即可。那么可以通过将这些攻击力的提升点进行一个总的排序,然后去前 M 个的总和即可。

但是随着数据量的增加这个排序就会超时。

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

vector<int> a;

bool cmp(int a,int b) {
    return a > b;
}

int main()
{
    int n,m;
    cin>>n>>m;
    for(int i = 1;i <= n;i++) {
        int aa,bb;
        cin>>aa>>bb;
        int k = (aa+bb-1)/bb;
        while(k--) {
            a.push_back(aa);
            aa -= bb;
        }
    }
    sort(a.begin(),a.end(),cmp);
    ll res = 0;
    for(int i = 0;i < m;i++) {
        res += a[i];
    }
    cout<<res<<endl;
    return 0;
}
Accepted

继续延续之前的一个思路,取前 M 个大的数。那么我们就需要找到第 M 个大的数然后分别找到每一个技能可以升级多少次即可。

那么最关键的就是找到这个第 M 个大的数,这时候就引入二分查找来找到这个数,这个二分查找类似二分答案的一种,但是还要进行一个修改。因为是等差数列,所以对于每个数列来说可以通过 O(1) 的时间找到 大于 那个第 M 个大的数的一个数量。

在计算的时候,会存在一个边界取值的一个情况,我们的处理就是找到所有大于等于 X 的值的一个数量,最后会处理多于或者少于 M 次 的边界值个数。

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;
const int N = 100010;
typedef long long ll;
ll A[N],B[N],n,m;

bool check(ll x) {
    ll cnt = 0;
    for(int i = 1;i <= n;i++) {
        if(A[i] < x) continue;
        ll t = (A[i] - x) / B[i];
        cnt += t+1;
    }
    
    if(cnt >=  m) return true;
    else return false;
}

int main()
{
    cin>>n>>m;
    for(int i = 1;i <= n;i++) cin>>A[i]>>B[i];

    ll l = 0, r = 1e6+10;
    while(l < r) {
        ll mid = (l + r + 1) >> 1;
        if(check(mid)) {
            l = mid;
        } else r = mid - 1;
    }

    ll x = l;
    ll cnt = 0,sum = 0;
    for(int i = 1;i <= n;i++) {
        if(A[i] < x) continue;
        ll t = (A[i] - x)/B[i];
        if(t*B[i] <= A[i]-x) t++;
        cnt += t;
        sum += (A[i] + (A[i] - (B[i]*(t-1))))*t/2;
    }
    sum += (m-cnt)*x;
    cout<<sum<<endl;
    return 0;
}
备注

想要一起备赛的小伙伴可以看评论区添加讨论群!

相关推荐
JCBP_1 小时前
QT(1)
开发语言·汇编·c++·qt
郝学胜-神的一滴2 小时前
C++ Core Guidelines 核心理念
开发语言·c++·设计模式·代码规范
YLCHUP2 小时前
【联通分量】题解:P13823 「Diligent-OI R2 C」所谓伊人_连通分量_最短路_01bfs_图论_C++算法竞赛
c语言·数据结构·c++·算法·图论·广度优先·图搜索算法
minji...3 小时前
C++ string自定义类的实现
开发语言·c++
汤永红3 小时前
week4-[二维数组]平面上的点
c++·算法·平面·信睡奥赛
特立独行的猫a4 小时前
C/C++三方库移植到HarmonyOS平台详细教程
c语言·c++·harmonyos·napi·三方库·aki
谱写秋天4 小时前
VSCode+Qt+CMake详细地讲解
c++·ide·vscode·qt·编辑器
A7bert7775 小时前
【YOLOv5部署至RK3588】模型训练→转换RKNN→开发板部署
c++·人工智能·python·深度学习·yolo·目标检测·机器学习
oioihoii5 小时前
现代C++工具链实战:CMake + Conan + vcpkg依赖管理
开发语言·c++
黑客影儿6 小时前
使用UE5开发2.5D开放世界战略养成类游戏的硬件配置指南
开发语言·c++·人工智能·游戏·智能手机·ue5·游戏引擎