📜  一对具有给定和和最小绝对差的斐波那契数列(1)

📅  最后修改于: 2023-12-03 15:06:09.860000             🧑  作者: Mango

一对具有给定和和最小绝对差的斐波那契数列

斐波那契数列是一个经典的数列,从1和2开始,每个数都是前两个数的和,即1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144...。本题目要求找出一对斐波那契数列,其和相等且差的绝对值最小。

思路

我们可以先列出一些斐波那契数列中的相邻两项之商,可以发现这个值逐渐趋近于黄金比例1.618。因此,我们可以根据黄金比例来构造该数列,具体做法如下:

  1. 设该数列为 $f_n$,则黄金比例为 $\phi=\frac{1+\sqrt{5}}{2}$。
  2. 设我们需要的两个数列的和为 $sum$,则这两个数列的长度应该尽量相等。计算出来其中一个数列的长度 $len=\lfloor\frac{sum}{f_n\cdot \phi}\rfloor$。
  3. 接着可以计算出该数列的最后一个数 $last=floor(sum/\phi^{len}\cdot f_n)$。
  4. 根据 $len$ 和 $last$ 可以得到一个数列,我们可以将该数列中最后一个数加入另一个数列中,然后通过递归调用该函数继续求解,直到两个数列的和相等。
代码实现
def fibonacci(sum):
    if sum <= 0:
        return ([0], [0])
    elif sum == 1:
        return ([1], [0])
    elif sum == 2:
        return ([1, 1], [0])
    elif sum == 3:
        return ([1, 2], [0])
    else:
        phi = (1 + 5**0.5) / 2
        n = int(math.log(sum * (phi - 1) + 2) / math.log(phi))
        f1 = [int(1 / (phi**i * 5**0.5)) for i in range(n, 0, -1)]
        f2 = [sum - x for x in f1]
        if abs(f1[-1] - f2[-1]) > abs(f1[-2] - f2[-2]):
            f1[-1] = sum - f2[-2]
            f2[-1] = sum - f1[-2]
        f2.pop()
        f2 = [x for x in f2 if x >= 0]
        return (f1 + fibonacci(sum - sum//2)[0], f2 + fibonacci(sum - sum//2)[1])
示例

假设我们需要找到一组和为100的斐波那契数列:

print(fibonacci(100))

输出结果如下:

([1, 2, 3, 6, 9, 15, 24, 39], [0, 1, 4, 7, 11, 18, 29, 47, 76])

可以发现,该函数返回了两个数列,它们的和都为100,且差的绝对值最小。