B4007 [GESP202406 二级] 计数

· · 题解

欢迎报名洛谷网校,期待和大家一起进步!

:::align{center} :::

这道题目的目标很明确:在一个从 1 到 n 的数字范围里,找出小杨的幸运数字 k 一共出现了多少次。我们需要注意的是,一个数字里如果多次出现 k,比如数字 22 里有两个 2,那么每一次都要被计算在内。

要解决这个问题,最直接、最容易理解的方法就是对从 1 到 n 的每一个整数进行彻底的“检查”。我们可以设计一个程序,用一个循环从 1 开始,依次遍历到 n。对于每一个正在被检查的数字,我们需要想办法把它拆分成一个个独立的数位,然后判断这些数位中有没有我们正在寻找的幸运数字 k

那么,如何拆分一个数字呢?这里有一个非常经典的数学小技巧。我们可以对这个数字反复进行“取余”和“整除”操作。例如,对于数字 123,我们用它对 10 取余(123 % 10),就能得到它的个位数 3。然后,我们再用它整除以 10123 / 10),数字就变成了 12。我们继续对 12 进行同样的操作,取余得到 2,整除后剩下 1。最后对 1 操作,得到 1,整除后变为 0。当数字变为 0 时,我们就成功地把它的每一位都分离出来了。在拆分的过程中,每当我们分离出一个数位,就将它与幸运数字 k 进行比较。如果它们相等,我们就让一个专门的计数器加一。这一部分的代码是:

int cur = i;
while (cur > 0) {
    int d = cur % 10;
    if (d == k)
        ans++;
    cur = cur / 10;
}

我们将这个拆分过程应用到从 1 到 n 的每一个数上。当外层循环遍历完从 1 到 n 的所有数字后,这个计数器里记录的总数,就是我们最终要找的答案。