DeepSeek 辅助编写python程序求解欧拉计划932题:2025数

原题地址:https://pe-cn.github.io/932/

一开始让他自由发挥,结果写出来的程序是错的。

然后让他从穷举法开始编写,

python 复制代码
# coding=utf-8
def find_all_2025_numbers():
    results = []
    
    # 枚举所有可能的 a 和 b
    for a in range(1, 5000):
        for b in range(1, 5000):
            # 计算连接后的数
            # 先确定 b 的位数
            b_digits = len(str(b))
            N = a * (10 ** b_digits) + b
            
            # 检查是否为完全平方数
            s = a + b
            if N == s * s:
                results.append((N, a, b))
    
    # 按 N 排序并去重
    results = sorted(set(results), key=lambda x: x[0])
    
    # 输出结果
    print(f"{'N':<10} {'a':<10} {'b':<10} {'a+b':<10} (a+b)²")
    print("-" * 50)
    for N, a, b in results:
        s = a + b
        print(f"{N:<10} {a:<10} {b:<10} {s:<10} {s*s}")
    
    print(f"\n共找到 {len(results)} 个 2025 数")
    return results

if __name__ == "__main__":
    find_all_2025_numbers()

把输出反馈给他理解。

复制代码
n<=5000有如下规律:请分析总结
N          a          b          a+b        (a+b)²
--------------------------------------------------
81         8          1          9          81
2025       20         25         45         2025
3025       30         25         55         3025
88209      88         209        297        88209
494209     494        209        703        494209
4941729    494        1729       2223       4941729
7441984    744        1984       2728       7441984
24502500   2450       2500       4950       24502500
25502500   2550       2500       5050       25502500

上述穷举程序效率低,根据完全平方数的后几位找b,前几位找a的思路来重写,不做别的

终于编对了, 改进版如下:

根据完全平方数的性质,我来重写高效的程序:

python 复制代码
def solve_T16():
    n = 16
    total_sum = 0
    seen = set()
    
    # 枚举可能的位数 k (b的位数)
    for k in range(1, n):
        # 10^k 和 10^k - 1
        pow10_k = 10 ** k
        pow10_k_minus_1 = pow10_k - 1
        
        # b 的范围:k 位数
        min_b = 10 ** (k - 1)
        max_b = pow10_k - 1
        
        # 对于每个可能的 b,我们需要解方程:
        # N = s^2,且 N 的最后 k 位是 b
        # 即 s^2 ≡ b (mod 10^k)
        
        # 枚举可能的 s 模 10^k 的值
        # 实际上,我们需要 s^2 ≡ b (mod 10^k)
        # 可以通过枚举 s 模 10^k 来找到所有解
        
        # 对于给定的 b,我们需要找到所有 s 使得 s^2 ≡ b (mod 10^k)
        # 然后检查对应的 N 是否 ≤ 10^n
        
        # 更高效的方法:直接枚举 s 并检查 b 的位数条件
        # s 的范围:s^2 的位数 ≤ n,所以 s ≤ 10^(n/2)
        max_s = int(10 ** (n / 2)) + 1
        
        # 对于每个可能的 s 模 10^k 的余数,我们可以跳着枚举
        # 但更简单:枚举所有 s 并检查,因为 n=16 时 s 只有 10^8 个,但这对 Python 来说太大了
        
        # 改用数学方法:b = s(10^k - s)/(10^k - 1) 必须为整数
        # 所以 (10^k - 1) | s(10^k - s)
        
        # 枚举 s 模 10^k - 1 的倍数
        mod_val = pow10_k_minus_1
        max_s_val = max_s
        
        # 从最小的可能 s 开始
        s_start = 2  # s = a+b ≥ 2
        
        # 对于每个可能的 s,检查 b 是否为整数且为 k 位数
        for s in range(s_start, max_s_val + 1):
            # 计算 b = s(10^k - s)/(10^k - 1)
            numerator = s * (pow10_k - s)
            if numerator % pow10_k_minus_1 != 0:
                continue
            
            b = numerator // pow10_k_minus_1
            
            # 检查 b 是否为 k 位数
            if b < min_b or b > max_b:
                continue
            
            # 计算 a = s - b
            a = s - b
            if a <= 0:
                continue
            
            # 验证 N = a * 10^k + b = s^2
            N = a * pow10_k + b
            if N != s * s:
                continue
            
            # 检查 N 的位数是否 ≤ n
            if len(str(N)) > n:
                continue
            
            if N not in seen:
                seen.add(N)
                total_sum += N
                # print(f"N={N}, a={a}, b={b}, k={k}, s={s}")
    
    return total_sum

if __name__ == "__main__":
    result = solve_T16()
    print(f"T(16) = {result}")

这个程序的思路:

  1. 固定 b 的位数 k
  2. 直接枚举 s = a+b,因为 s 的范围相对较小(s ≤ 10^(n/2) = 10^8)
  3. 通过公式 b = s(10^k - s)/(10^k - 1) 计算 b
  4. 检查 b 是否为整数且为 k 位数
  5. 验证所有条件并累加结果

对于 n=16,s 最多有 10^8 个,但每个 k 都要遍历一次,总计算量约为 16 × 10^8 = 1.6e9,在 Python 中仍然较大,但比枚举 a,b 要高效很多。

实际运行速度有点慢。n=16,用了4分多钟。再让他优化。

你说得对,当 n=16 时,s 需要遍历到 10^8,这个数量级在 Python 中仍然太慢。我需要进一步优化。

关键优化点:利用 s(10^k - s) 必须被 10^k - 1 整除的条件,可以大幅减少枚举量。

python 复制代码
def solve_T16():
    n = 16
    total_sum = 0
    seen = set()
    
    # 枚举可能的位数 k (b的位数)
    for k in range(1, n):
        pow10_k = 10 ** k
        d = pow10_k - 1  # 10^k - 1
        
        # b 的范围:k 位数
        min_b = 10 ** (k - 1)
        max_b = pow10_k - 1
        
        # s 的最大值:s^2 的位数 ≤ n,所以 s ≤ 10^(n/2)
        max_s = int(10 ** (n / 2))
        
        # 我们需要 s(10^k - s) ≡ 0 (mod d)
        # 即 s(10^k - s) = s(pow10_k - s) ≡ 0 (mod d)
        # 由于 pow10_k ≡ 1 (mod d),所以 s(1 - s) ≡ 0 (mod d)
        # 即 s(s - 1) ≡ 0 (mod d)
        
        # 所以 d 必须整除 s(s-1)
        # 这意味着 s 要么是 d 的倍数,要么 s-1 是 d 的倍数
        # 或者更一般地,s 和 s-1 分别包含 d 的因子
        
        # 方法1:枚举 d 的倍数
        # s 必须是 d 的倍数,或者 s-1 是 d 的倍数
        # 但更精确地,我们需要考虑 d 的因子分解
        
        # 简单但有效的方法:枚举 d 的所有因子对
        # 对于每个因子 f 整除 d,设 s 是 f 的倍数,且 s-1 是 d/f 的倍数
        
        # 获取 d 的所有因子
        factors = []
        i = 1
        while i * i <= d:
            if d % i == 0:
                factors.append(i)
                if i != d // i:
                    factors.append(d // i)
            i += 1
        
        # 对于每对因子 (f, g) 满足 f * g = d
        # 我们需要 s 满足:f | s 且 g | (s-1)
        # 即 s ≡ 0 (mod f) 且 s ≡ 1 (mod g)
        
        # 使用中国剩余定理求解
        for f in factors:
            g = d // f
            
            # 解同余方程组:s ≡ 0 (mod f), s ≡ 1 (mod g)
            # 需要 gcd(f, g) = 1,否则可能无解
            from math import gcd
            if gcd(f, g) != 1:
                continue
            
            # 使用扩展欧几里得算法求解
            # 找到 x, y 使得 f*x + g*y = 1
            # 则 s = f * (1 - 0) * y? 实际上标准解是:
            # s = 0 * g * inv_g_mod_f + 1 * f * inv_f_mod_g
            # 但更简单:s = f * ((1 * inv_f_mod_g) % g)
            
            # 计算 f 模 g 的逆元
            inv_f_mod_g = pow(f, -1, g)
            s0 = f * inv_f_mod_g % (f * g)
            s0 = s0 % d
            
            # s0 是模 d 的一个解,所有解为 s = s0 + t*d
            # 枚举所有 s ≤ max_s
            if s0 == 0:
                s0 = d  # 避免 s=0
            s = s0
            while s <= max_s:
                # 检查这个 s 是否有效
                if s >= 2:  # s = a+b ≥ 2
                    # 计算 b = s(10^k - s)/d
                    numerator = s * (pow10_k - s)
                    if numerator % d == 0:
                        b = numerator // d
                        
                        # 检查 b 是否为 k 位数
                        if min_b <= b <= max_b:
                            a = s - b
                            if a > 0:
                                N = a * pow10_k + b
                                if len(str(N)) <= n and N not in seen:
                                    seen.add(N)
                                    total_sum += N
                
                s += d
            
            # 同样处理 s ≡ 1 (mod f), s ≡ 0 (mod g) 的情况
            # 交换 f 和 g 的角色
            inv_g_mod_f = pow(g, -1, f)
            s1 = g * inv_g_mod_f % (f * g)
            s1 = s1 % d
            if s1 == 0:
                s1 = d
            s = s1
            while s <= max_s:
                if s >= 2:
                    numerator = s * (pow10_k - s)
                    if numerator % d == 0:
                        b = numerator // d
                        if min_b <= b <= max_b:
                            a = s - b
                            if a > 0:
                                N = a * pow10_k + b
                                if len(str(N)) <= n and N not in seen:
                                    seen.add(N)
                                    total_sum += N
                s += d
    
    return total_sum

if __name__ == "__main__":
    result = solve_T16()
    print(f"T(16) = {result}")

这个优化的关键点:

  1. 利用同余关系 :从 s(10^k - s) ≡ 0 (mod d) 且 10^k ≡ 1 (mod d) 推导出 s(s-1) ≡ 0 (mod d)

  2. 因子分解:d 的每个因子对 (f, g) 满足 f × g = d,对应两种情况:

    • f | s 且 g | (s-1)
    • g | s 且 f | (s-1)
  3. 中国剩余定理:解同余方程组得到 s 模 d 的解,然后每次增加 d 枚举所有可能的 s

这样枚举量从 O(10^8) 降低到 O(因子个数 × (max_s / d)),对于大多数 k,d 很大,枚举量很小。

这个版本n=16只用18秒就算完了。

相关推荐
阿里嘎多学长2 小时前
2026-10-20 GitHub 热点项目精选
开发语言·程序员·github·代码托管
happylifetree3 小时前
Python67:核心语法-函数进阶-参数类型(函数作为参数)
python
布吉岛的石头3 小时前
Java 程序员第 50 阶段2:预训练的目标函数:自回归语言建模本质
java·开发语言·人工智能·深度学习·回归·transformer
小羊没烦恼!3 小时前
铁道部新客票系统设计(二)
开发语言·前端·数据库·python·oracle·c#·php
quantdash_cc4 小时前
从实时行情到价格观察表:用 Python 和 Pandas 构建策略输入数据
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
镜子AI4 小时前
镜子AI工程实践:用 Python 做 GEO 实体一致性审计,并自动生成 JSON-LD 结构化数据
人工智能·python·json
昂好的day5 小时前
VisionMaster 通信模块实战(上):Modbus、TCP 收发、协议组装解析
开发语言·网络·网络协议·tcp/ip·c#
努力实干6 小时前
面向对象设计原则——C++
开发语言·c++·数码相机
NetX行者7 小时前
四语言 Hello World 背后:编译模型与运行时对比
开发语言
Pin_Qing8 小时前
账单没超,请求先被拒了
大数据·开发语言·人工智能