【备战蓝桥杯国赛-国赛真题】最大数字

文章讨论了一种优化策略,通过有限次的加1和减1操作(每个位有次数限制),使一个大整数(最大1e17)的值尽可能大。关键在于从高位到低位考虑,加1操作尽量让数字到9,减1操作目的是同样达到9。通过爆搜实现解决方案,2^17的复杂度是可行的。在最优解中,两种操作不会对同一位置执行超过0次。
摘要由CSDN通过智能技术生成

题目链接:https://www.dotcpp.com/oj/problem2694.html

在这里插入图片描述

思路

我们的目标通过若干次的两类操作(有次数限制),使得最终的数字尽可能大,而数字的大小与数的位数有关,并且处于高位的数字需要尽可能的高。本题的数据范围是1e17,看起来很大,但是分析之后我们只需要考虑其中的每一位,也只有20不到的数据量,接着我们来分析这两类操作(从高位到低位考虑):

  1. 加1操作:应该尽可能将数字增加到9,如果已经是9,那么我们贪心考虑的结果是,不需要对当前位进行操作,如果该操作的次数不足以让数字增加到9,那么我们全部操作完即可。
  2. 减1操作:该操作的目的其实只有一个,就是把该位的数字减到9,因为如果减少不到9,那么数的值将会变小,如果减少到8,那说明一定可以减少到9,并且减少到8或者更小都不如减少到9更优,因此,如果该位减少不到9,那么我们不对该位进行减1操作。
  3. 说明:可以证明,在最优方案中,这两种操作不会对同一位进行大于0次的操作,为了方便,我们称之为合操作。一个直观的解释是这样的,这两种的操作是互相抵消的,如果合操作存在,那么另任意一种操作数为0后,结果一定也能达到,并且增加了另一种操作的可操作次数,这样不会使得最终结果更糟糕。

接下来就是代码部分了,使用爆搜就可以,2^17的复杂度很友好,如果对下面中的代码有不理解的地方,欢迎大家交流。

代码(C++)

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

LL n, res = 0;
int a, b;
string s;

void dfs(int u, LL v) {
    if(u == (int)s.size()) {
        res = max(res, v);
        return ;
    }

    LL x = s[u] - '0';
    LL t = min((LL)a, 9 - x);
    a -= t;
    dfs(u + 1, v * 10ll + x + t);
    a += t;

    if(b >= x + 1) {
        b -= x + 1;
        dfs(u + 1, v * 10ll + 9ll);
        b += x + 1;
    }
}

int main() {
    cin >> n >> a >> b;
    s = to_string(n);

    dfs(0, 0ll);

    cout << res << "\n";
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值