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

如何在0.5秒内统计[L,R]范围内各位数字之和能被10整除的回文数(1≤L≤R≤10¹²)?

如何在0.5秒内统计[L,R]范围内各位数字之和能被10整除的回文数(1≤L≤R≤10¹²)?

首先得指出你代码里的两个核心问题:

  1. circle_num函数逻辑错误:你现在的函数只检查第一个数字的累加和是否能被10整除,而不是所有数字的总和!比如数字19的和是10,本应返回True,但你的函数会在第一次循环(加1)时直接返回False,完全不符合需求。正确逻辑应该是累加所有数字后再判断总和是否能被10整除。
  2. 效率瓶颈:你通过字符串拼接生成回文数,再转整数,之后又转字符串计算数字和,这些字符串操作的开销极大,在1e12的范围内循环很容易超时。

优化思路

回文数的结构自带规律,我们可以利用这一点直接通过前半部分计算完整回文数的数值和数字和,完全规避字符串操作:

  • 偶数位回文数:比如4位的abba,前半部分是ab,回文数的值为ab * 100 + ba,数字和是(a+b)*2。
  • 奇数位回文数:比如5位的abcba,前半部分是abc,回文数的值为abc * 100 + ba,数字和是(a+b+c)*2 - c(中间的c被累加了两次,需要减去一次)。

另外,我们可以按回文数的位数分块处理,从1位到12位依次遍历,遇到生成的回文数超过R时直接终止当前位数的循环,减少无效计算。

优化后的代码

def digit_sum(n):
    """计算一个数的各位数字之和"""
    res = 0
    while n > 0:
        res += n % 10
        n = n // 10
    return res

def reverse_num(n):
    """反转一个整数(例如123→321)"""
    res = 0
    while n > 0:
        res = res * 10 + n % 10
        n = n // 10
    return res

def count_palindromes(L, R):
    count = 0
    # 预先计算10的幂次,避免重复计算
    pow10 = [1] * 13
    for i in range(1, 13):
        pow10[i] = pow10[i-1] * 10
    
    # 遍历所有可能的回文数位数(1到12位)
    for digit_len in range(1, 13):
        if digit_len % 2 == 1:
            # 处理奇数位回文数
            half_len = (digit_len + 1) // 2
            min_half = pow10[half_len - 1] if half_len > 1 else 1
            max_half = pow10[half_len] - 1
            pow_val = pow10[half_len - 1]  # 生成回文数的幂次
            
            for half in range(min_half, max_half + 1):
                palin = half * pow_val + reverse_num(half // 10)
                if palin > R:
                    break  # 后续half更大,回文数也更大,直接终止循环
                if palin >= L:
                    total_sum = digit_sum(half) * 2 - (half % 10)
                    if total_sum % 10 == 0:
                        count += 1
        else:
            # 处理偶数位回文数
            half_len = digit_len // 2
            min_half = pow10[half_len - 1]
            max_half = pow10[half_len] - 1
            pow_val = pow10[half_len]  # 生成回文数的幂次
            
            for half in range(min_half, max_half + 1):
                palin = half * pow_val + reverse_num(half)
                if palin > R:
                    break
                if palin >= L:
                    total_sum = digit_sum(half) * 2
                    if total_sum % 10 == 0:
                        count += 1
    return count

# 输入处理
s = input().strip()
L, R = map(int, s.split())
print(count_palindromes(L, R))

代码说明

  1. digit_sum和reverse_num:用纯数学运算实现,比字符串操作效率高得多。
  2. 分位数处理:针对每个位数的回文数,直接计算前半部分的范围,避免无效循环。
  3. 提前终止:当生成的回文数超过R时,直接break当前位数的循环,因为后续前半部分更大,回文数只会更大。
  4. 数字和直接推导:通过前半部分的数字和直接计算整个回文数的数字和,无需遍历回文数的每一位。

这个代码的循环次数约2e6次,所有操作都是高效的算术运算,完全可以在0.5秒内完成1e12范围内的统计。

备注:内容来源于stack exchange,提问作者Firrew_MinhQuan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 08:49:38