埃及分数

GitHub跳转原题关系图返回列表

迭代加深枚举单位分数个数,用剩余项上界和最优末分母剪枝。

OJ: luogu

题目 ID: P1763

难度:提高+/省选-

标签:迭代加深DFS分数python

日期: 2026-07-16 20:10

题意

把真分数表示成分母严格递增的单位分数和。项数越少越优;项数相同时,最大分母越小越优。

思路

按项数从 1 开始迭代加深,第一个有解的层数保证项数最少。剩余分数为 a/b 时,下一个分母至少为 ceil(b/a)

若还剩 slots 项且下一分母为 x,所有后续单位分数都不超过 1/x,必须满足 slots/x >= a/b,由此得到枚举上界 slots*b//a。最后一项必须恰好等于剩余分数,可以直接判整除。

同一深度记录最大分母最小的方案。

Python 知识

  • math.gcd 每步约分,避免分子分母无谓膨胀。
  • 海象运算符在循环条件中同时取得当前深度搜索结果。
  • path.append/pop 原地维护当前分母序列。

代码

python
import math


numerator, denominator = map(int, input().split())
path = []


def find(term_count):
    best = None

    def dfs(depth, start, a, b):
        nonlocal best
        slots = term_count - depth
        if slots == 1:
            if b % a:
                return
            value = b // a
            if value < start or value > 10**7:
                return
            candidate = path + [value]
            if best is None or candidate[-1] < best[-1]:
                best = candidate
            return

        lower = max(start, (b + a - 1) // a)
        upper = min(10**7, slots * b // a)
        if best is not None:
            upper = min(upper, best[-1] - 1)
        for value in range(lower, upper + 1):
            next_a = a * value - b
            if next_a <= 0:
                continue
            next_b = b * value
            divisor = math.gcd(next_a, next_b)
            path.append(value)
            dfs(depth + 1, value + 1, next_a // divisor, next_b // divisor)
            path.pop()

    dfs(0, 2, numerator, denominator)
    return best


terms = 1
while (answer := find(terms)) is None:
    terms += 1
print(*answer)

复杂度

搜索复杂度取决于最优项数与分母范围,最坏指数级;递归空间等于答案项数。

总结

题目按“项数优先”排序答案时,IDDFS 自然匹配第一关键字,再在同层比较第二关键字。