1 条题解

  • 0
    @ 2026-5-19 17:09:14

    题意理解

    我们有一个正整数 nn10n10910 \le n \le 10^9),每次操作可以给 nn 加上一个十进制表示全为 99 的数(例如 9,99,999,9, 99, 999, \dots 等)。

    目标是让 nn 的十进制表示中至少出现一次数字 77。问最少需要多少次操作。


    关键观察

    1. 每次操作只能加一个全是 99 的数。
      99 数有一个重要性质:它等于 10k110^k - 1

    2. 题目中的一次操作可以加任意长度(位数)的 99 序列,不限制为 9,99,999,9, 99, 999, \dots 中的具体哪一个,只要它全是 99 就行。
      因此,实际上相当于可以自由选择加一个形如 10k110^k - 1 的数,并且 k1k \ge 1

    3. 假设我们进行了 xx 次操作(x0x \ge 0),记每次操作增加的数分别为 a1,a2,,axa_1, a_2, \dots, a_x,每个 aia_i 都是 10ki110^{k_i} - 1

      最终数值为:

      $$N = n + \sum_{i=1}^{x} (10^{k_i} - 1) = n - x + \sum_{i=1}^{x} 10^{k_i}. $$

      其中 i=1x10ki\sum_{i=1}^{x} 10^{k_i} 是一个十进制表示中只包含 0011 的数(每个 10ki10^{k_i} 对应的数位上是 11)。

    4. 关键转化:
      S=i=1x10kiS = \sum_{i=1}^{x} 10^{k_i},那么 SS 是一个 0/10/1 串(十进制)。
      最终结果 N=(nx)+SN = (n - x) + S

      注意到 SS 的十进制表示中,每个 11 可以位于任意位(由 kik_i 决定)。


    进一步简化

    我们换个角度:

    • 执行 xx 次操作等价于:从 nn 开始,在任意位上加 11,且可以多次在同一数位上加 11
      因为每次加 9,99,9, 99, \dots 等价于在个位加 99(产生进位),十位加 99(产生进位),等等。
      但更精确的等价是:
      9999 = 十位加 99 并进位,个位加 99 并进位,其实就是在十位和个位各加 99,但因为进位,实际效果类似在十位加 11(并可能继续进位),个位加 11(并可能进位)?
      我们仔细推一下。

    等效模型(更简洁)

    实际上,原题有一个更直观的等价模型:

    因为 10k110^k - 1 加到 nn 上,相当于先在 nnkk 个最低位各加 99,然后处理进位。
    991010 进制下的效果是:加 99 在某位上等价于该位减 11,并向高位进 11

    但这样推较麻烦。我们直接看标程思路


    标程分析

    标程如下:

    for(int x=0;x<10;x++){
        int res=7;
        string s=to_string(n-x);
        for(int i=0;i<s.length();i++)
            if(s[i]>='0'&&s[i]<='7') res=min(res,'7'-s[i]);
        if(res<=x){
            cout<<x<<endl;
            break;
        }
    }
    

    它枚举 xx0099(因为答案不会超过 99?原因后面会讲)。
    对于每个 xx,先计算 nxn - x,把它转成字符串 ss
    对于 ss 的每一位,如果该位数字 7\le 7,计算它变成 77 需要的增加量('7' - s[i])。
    取所有位的最小增加量作为 res
    如果 res <= x,说明我们可以在 xx 步内完成,输出 xx 并结束。


    为什么这样是对的?

    我们考虑最终结果 NN 满足:N=n+若干个全是9的数N = n + \text{若干个全是9的数}

    注意到:

    • 如果我们在某一位上需要增加 dd1d91 \le d \le 9),我们可以通过加一次适当的 9,99,9, 99, \dots 来实现吗?
      不行,因为一次加 9,999, 99 等会同时影响多位。

    但标程的思路是:
    先令 m=nxm = n - x(为什么是减 xx?因为每次加的数全是 99,总和是 9×9 \times(操作次数)?不对,因为 99=91199=9*11,不是直接 9x9x
    所以这里减 xx 其实是一个技巧。)

    我们换个解释:

    设我们进行 xx 次操作,每次加的数是 10ki110^{k_i} - 1
    最终 $N = n + \sum (10^{k_i} - 1) = n - x + \sum 10^{k_i}$。

    M=10kiM = \sum 10^{k_i}MM 的十进制表示中每位是 0011

    那么 N=(nx)+MN = (n - x) + M

    目标:让 NN 的十进制中包含数字 77

    nxn - x 的十进制数的每一位,如果我们想让这一位在 NN 中变成 77,可以通过 MM 的对应位给它加一个数(0011)来实现。
    如果 nxn-x 的这一位原本是 dd,那么需要加 7d7-d 才能变成 77,但 MM 的对应位只能加 0011,因此必须 7d17-d \le 1,即 d6d \ge 6 才行。
    但这里 MM 的多位可以配合进位?实际进位会让问题复杂。


    其实更简单理解

    标程实际是暴力枚举 xx,并判断是否可能在 xx 步内完成,基于一个贪心/直接构造:

    我们看 nxn-x 的每一位,如果某一位 7\le 7,记需要加 t=7该位t = 7 - \text{该位} 才能到 77
    但是一次操作(加 9,99,9,99,\dots)可以在多个位上同时产生进位和加法,所以不能简单加一位。
    标程的检查方式是:
    取所有位上需要加的最小量 tmint_{\min},如果 tminxt_{\min} \le x,那么就可以用 xx 次操作完成,方法是让 MM 对应位为 11,从而在一位上增加 11,配合进位可能让这一位变成 77

    实际上更准确的解释是:
    nxn-x 的某一位 dd,想通过加一些 10ki10^{k_i}(即 MM 的对应位)变成 77,并且这些 10ki10^{k_i} 是加在整个数上的,但不同的 kik_i 对应不同的位。
    标程强行假设:我们只看最低的 tmint_{\min} 需求,如果 tminxt_{\min} \le x,就认为可以构造出来。这在实际数学上并不显然严谨,但题目保证这样枚举 xx0099 能找到正确答案,并且 xx 不会超过 99

    为什么 x9x \le 9?因为只要 nn 的个位是 77,我们就已经完成。如果个位不是 77,我们可以连续加 99 直到个位变成 77,最坏情况:个位从 00 变到 77 需加 7799?但加 99 可能影响高位,因此实际最大操作次数很可能小于等于 99(经验观察或题设保证)。


    算法复杂度

    • 枚举 xx0099(常数次)
    • nxn-x 转字符串并扫描每一位,长度最多 1010(因为 n109n \le 10^9
    • 总体 O(t×10×10)=O(100t)O(t \times 10 \times 10) = O(100t)t104t \le 10^4 时完全可行。

    结论

    这道题的核心是:

    1. 理解加 9,99,9999, 99, 999 等于在若干位上各加 99(通过进位等价于每个对应位加 11 或减 11 等)。
    2. nxn-x 表示为了构造最终包含 77 的数,我们允许 xx 次操作,并检查 nxn-x 中是否存在某一位可以通过加不超过 xx 次的一位上的 11(通过 MM 的某位 11)变成 77
    3. 实际实现中用了一个巧妙的枚举加判断方法,并且 xx 最大不超过 99

    最终代码复杂度很低,能在题目限制内高效求解。

    • 1

    信息

    ID
    7255
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者