You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Python中以更低时间复杂度求解两数间所有数字的各位之和?

你的代码在小范围测试用例上能正常工作,但当处理跨度接近1e9的数值范围时,直接遍历每个数字再拆分各位的做法会因为时间复杂度太高(O((b-a+1)*位数))而超时——毕竟要循环1e9次,这在任何编程竞赛的时间限制里都是不可能完成的。

解决这个问题的核心思路是用数学方法直接计算从0到n的所有数字的各位之和,然后通过sum_up_to(b) - sum_up_to(a-1)得到a到b之间的结果。这种方法的时间复杂度只和数字的位数有关(最多10次循环,因为1e9是10位数),完全能应对题目中的最大约束。

具体实现思路

我们逐位处理数字n的每一位(个位、十位、百位……),计算每一位在0到n的所有数字中贡献的总和:

  1. 把当前位对应的数字拆成三个部分:
    • high:当前位左边的所有数字
    • curr:当前位的数字
    • low:当前位右边的所有数字
    • pow10:当前位的位权(比如十位的位权是10)
  2. 先计算高位从0到high-1时的贡献:此时当前位可以取0-9的所有数字,每个数字出现pow10次,总和是high * 45 * pow10(45是0到9的数字和)
  3. 再计算高位等于high时的贡献:
    • 如果curr > 0:先算当前位取0到curr-1的总和,再算当前位取curr时的总和(共出现low+1次)
    • 如果curr == 0:当前位只能取0,贡献为0,无需额外计算

完整代码

def sum_digits_up_to(n):
    if n < 0:
        return 0
    total = 0
    pow10 = 1
    while pow10 <= n:
        divisor = pow10 * 10
        high = n // divisor
        curr = (n // pow10) % 10
        low = n % pow10
        
        # 高位从0到high-1时的贡献
        total += high * 45 * pow10
        
        # 高位等于high时的贡献
        if curr > 0:
            # 当前位取0到curr-1的总和
            total += (curr * (curr - 1) // 2) * pow10
            # 当前位取curr的总和
            total += curr * (low + 1)
        
        pow10 *= 10
    return total

# 处理输入:一行输入两个数字
a, b = map(int, input().split())
result = sum_digits_up_to(b) - sum_digits_up_to(a - 1)
print(result)

关键说明

  • 输入处理:原代码用了两次input(),但题目要求是依次输入两个数字(通常是一行输入),所以改用map(int, input().split())更符合题目要求,也避免了输入格式错误
  • 边界处理:当a=0时,sum_digits_up_to(a-1)sum_digits_up_to(-1)会返回0,结果就是sum_digits_up_to(b),完全正确
  • 测试示例:输入8 13时,sum_digits_up_to(13)=55sum_digits_up_to(7)=2855-28=27,和示例输出一致

这种方法不管数值多大,都能在极短时间内完成计算,轻松通过所有测试用例。

内容的提问来源于stack exchange,提问作者Jana M

火山引擎 最新活动