1 条题解
-
0
题意理解
我们有一个正整数 (),每次操作可以给 加上一个十进制表示全为 的数(例如 等)。
目标是让 的十进制表示中至少出现一次数字 。问最少需要多少次操作。
关键观察
-
每次操作只能加一个全是 的数。
全 数有一个重要性质:它等于 。 -
题目中的一次操作可以加任意长度(位数)的 序列,不限制为 中的具体哪一个,只要它全是 就行。
因此,实际上相当于可以自由选择加一个形如 的数,并且 。 -
假设我们进行了 次操作(),记每次操作增加的数分别为 ,每个 都是 。
最终数值为:
$$N = n + \sum_{i=1}^{x} (10^{k_i} - 1) = n - x + \sum_{i=1}^{x} 10^{k_i}. $$其中 是一个十进制表示中只包含 和 的数(每个 对应的数位上是 )。
-
关键转化:
设 ,那么 是一个 串(十进制)。
最终结果 。注意到 的十进制表示中,每个 可以位于任意位(由 决定)。
进一步简化
我们换个角度:
- 执行 次操作等价于:从 开始,在任意位上加 ,且可以多次在同一数位上加 。
因为每次加 等价于在个位加 (产生进位),十位加 (产生进位),等等。
但更精确的等价是:
加 = 十位加 并进位,个位加 并进位,其实就是在十位和个位各加 ,但因为进位,实际效果类似在十位加 (并可能继续进位),个位加 (并可能进位)?
我们仔细推一下。
等效模型(更简洁)
实际上,原题有一个更直观的等价模型:
因为 加到 上,相当于先在 的 个最低位各加 ,然后处理进位。
而 在 进制下的效果是:加 在某位上等价于该位减 ,并向高位进 。但这样推较麻烦。我们直接看标程思路。
标程分析
标程如下:
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; } }它枚举 从 到 (因为答案不会超过 ?原因后面会讲)。
对于每个 ,先计算 ,把它转成字符串 。
对于 的每一位,如果该位数字 ,计算它变成 需要的增加量('7' - s[i])。
取所有位的最小增加量作为res。
如果res <= x,说明我们可以在 步内完成,输出 并结束。
为什么这样是对的?
我们考虑最终结果 满足:。
注意到:
- 如果我们在某一位上需要增加 (),我们可以通过加一次适当的 来实现吗?
不行,因为一次加 等会同时影响多位。
但标程的思路是:
先令 (为什么是减 ?因为每次加的数全是 ,总和是 (操作次数)?不对,因为 ,不是直接 。
所以这里减 其实是一个技巧。)我们换个解释:
设我们进行 次操作,每次加的数是 。
最终 $N = n + \sum (10^{k_i} - 1) = n - x + \sum 10^{k_i}$。记 , 的十进制表示中每位是 或 。
那么 。
目标:让 的十进制中包含数字 。
对 的十进制数的每一位,如果我们想让这一位在 中变成 ,可以通过 的对应位给它加一个数( 或 )来实现。
如果 的这一位原本是 ,那么需要加 才能变成 ,但 的对应位只能加 或 ,因此必须 ,即 才行。
但这里 的多位可以配合进位?实际进位会让问题复杂。
其实更简单理解
标程实际是暴力枚举 ,并判断是否可能在 步内完成,基于一个贪心/直接构造:
我们看 的每一位,如果某一位 ,记需要加 才能到 。
但是一次操作(加 )可以在多个位上同时产生进位和加法,所以不能简单加一位。
标程的检查方式是:
取所有位上需要加的最小量 ,如果 ,那么就可以用 次操作完成,方法是让 对应位为 ,从而在一位上增加 ,配合进位可能让这一位变成 。实际上更准确的解释是:
的某一位 ,想通过加一些 (即 的对应位)变成 ,并且这些 是加在整个数上的,但不同的 对应不同的位。
标程强行假设:我们只看最低的 需求,如果 ,就认为可以构造出来。这在实际数学上并不显然严谨,但题目保证这样枚举 从 到 能找到正确答案,并且 不会超过 。为什么 ?因为只要 的个位是 ,我们就已经完成。如果个位不是 ,我们可以连续加 直到个位变成 ,最坏情况:个位从 变到 需加 次 ?但加 可能影响高位,因此实际最大操作次数很可能小于等于 (经验观察或题设保证)。
算法复杂度
- 枚举 从 到 (常数次)
- 对 转字符串并扫描每一位,长度最多 (因为 )
- 总体 , 时完全可行。
结论
这道题的核心是:
- 理解加 等于在若干位上各加 (通过进位等价于每个对应位加 或减 等)。
- 用 表示为了构造最终包含 的数,我们允许 次操作,并检查 中是否存在某一位可以通过加不超过 次的一位上的 (通过 的某位 )变成 。
- 实际实现中用了一个巧妙的枚举加判断方法,并且 最大不超过 。
最终代码复杂度很低,能在题目限制内高效求解。
-
- 1
信息
- ID
- 7255
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者