思路不是特别难以想到,但是计算流程繁琐,指针的数量大、位置易混淆。
考验的主要是耐心和细心。
def foo(a):
"""计算从0到a(含0和a)的所有整数中,各个数码出现的次数。"""
k = len(str(a))
digs = list(map(int, list(str(a))))
cnt = [0 for _ in range(10)]
for i in range(k):
# a的左起第i+1位是dig。
# 这轮循环处理的数字是所有满足两个条件的数:1.前i位固定为a的前i位,2.第i位小于dig。
dig = digs[i]
# 对于前i位数,对应计数增加的量等于这一轮循环处理的数字总量,即dig * 10 ** (k - 1 - i)
for predigs in digs[:i]:
cnt[predigs] += dig * 10 ** (k - 1 - i)
# 对于第i+1位数,所有小于dig的数码都应增加10 ** (k - 1 - i)。
for j in range(dig):
cnt[j] += 10 ** (k - 1 - i)
# 对于第i+2位直到最后一位数共k-2-i位,每个位置都应当取遍0-9。
# 不要忘记第i+1位有dig种取法所以要乘dig。
for each in range(10):
cnt[each] += dig * (k - 1 - i) * 10 ** (k - 2 - i)
# 补上a对应的计数。由于python下标从0开始,所以没有办法在保持可读性的前提下化简算法。
for i in range(k):
cnt[digs[i]] += 1
# 上面计算的时候把所有数字都用0补齐到了k位,但这些0是要扣掉的。
# 这些0的数量是10+100+...+10**(k-1)。用等比数列求和公式代替了循环。
extra_zeros = int(10 * (10 ** (k - 1) - 1) / 9)
cnt[0] -= extra_zeros
return list(map(int, cnt)) # 不知道哪步出现了浮点数运算……
a, b = list(map(int, input().split()))
totala = foo(a - 1)
totalb = foo(b)
sub = [totalb[each] - totala[each] for each in range(10)]
print(" ".join([str(cnt) for cnt in sub]))