You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求高效Python算法:统计1到n中数位和≤x的整数个数

高效统计数位和≤x的整数个数优化方案

你的原始方法通过遍历每个数字计算数位和,在n达到1012时会执行万亿次操作,完全无法在合理时间内完成。解决这类大范围数位统计问题,**数位动态规划(数位DP)**是最优方案,它通过按数位递归+记忆化的方式,把时间复杂度降到O(位数×x),对于1012这种最多12位的数字,计算量仅在千级以内。

实现思路

  1. 将数字n转换为字符串形式的数位列表,方便逐位处理;
  2. 用递归函数统计符合条件的数:
    • 记录当前处理到第几位、已累计的数位和、是否受原数字n的限制(即前面的数位是否和n的对应数位完全相同);
    • 记忆化已计算过的状态,避免重复计算;
  3. 直接返回递归结果,包含0到n的所有符合条件的数。

代码实现

from functools import lru_cache

def count_digit_sum_le(x, n):
    s = str(n)
    length = len(s)
    
    @lru_cache(maxsize=None)
    def dp(pos, current_sum, tight):
        # pos: 当前处理的数位索引
        # current_sum: 已累计的数位和
        # tight: 布尔值,当前是否受原数字的数位限制(True表示前面数位和n完全相同,当前位最大只能取s[pos];False表示当前位可取值0-9)
        if pos == length:
            return 1 if current_sum <= x else 0
        limit = int(s[pos]) if tight else 9
        total = 0
        for d in range(0, limit + 1):
            new_tight = tight and (d == limit)
            new_sum = current_sum + d
            if new_sum > x:
                continue  # 数位和已超过x,无需继续递归
            total += dp(pos + 1, new_sum, new_tight)
        return total
    
    return dp(0, 0, True)

验证示例

当n=112,x=5时,调用count_digit_sum_le(5, 112)会返回31(包含0到112中数位和≤5的所有数),和你原始函数的结果一致,但效率提升数个数量级。

性能说明

  • 对于n=10^12(12位数),x最大为108(12×9),递归的状态数最多为12×109×2=2616,计算量极小;
  • 记忆化缓存会自动复用已计算的状态,避免重复递归。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 03:15:00