逆斐波那契算法?

发布于 2024-10-19 20:27:05 字数 419 浏览 7 评论 0原文

对于任意 n 计算 F(n) 的方法有数十种,其中许多方法都具有很高的运行时间和内存使用率。

然而,假设我想问相反的问题:

给定 F(n),n > 2、n是什么?

(n > 2 限制存在,因为 F(1) = F(2) = 1 并且没有明确的逆)。

解决这个问题最有效的方法是什么?通过枚举斐波那契数并在达到目标数时停止,可以很容易地在线性时间内完成此操作,但是有没有比这更快的方法呢?

编辑:目前,这里发布的最佳解决方案使用 O(log n) 内存在 O(log n) 时间内运行,假设数学运算在 O(1) 中运行并且机器字可以容纳任何O(1) 空间中的数字。我很好奇是否可以降低内存要求,因为您可以使用 O(1) 空间计算斐波那契数。

There are dozens of ways of computing F(n) for an arbitrary n, many of which have great runtime and memory usage.

However, suppose I wanted to ask the opposite question:

Given F(n) for n > 2, what is n?

(The n > 2 restriction is in there since F(1) = F(2) = 1 and there's no unambiguous inverse).

What would be the most efficient way of solving this problem? It's easy to do this in linear time by enumerating the Fibonacci numbers and stopping when you hit the target number, but is there some way of doing this any faster than that?

EDIT: currently, the best solution posted here runs in O(log n) time using O(log n) memory, assuming that mathematical operations run in O(1) and that a machine word can hold any number in O(1) space. I'm curious if it's possible to drop the memory requirements, since you can compute Fibonacci numbers using O(1) space.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

轮廓§ 2024-10-26 20:27:05

由于OP询问了不涉及任何浮点计算的矩阵解,所以它就是。假设数字运算具有 O(1) 复杂度,我们可以通过这种方式实现 O(logn) 复杂度。

让我们采用具有以下结构的 2x2 矩阵 A

1 1
1 0

现在考虑向量 (8, 5),存储两个连续的斐波那契数。如果将其乘以该矩阵,您将得到 (8*1 + 5*1, 8*1 + 5*0) = (13, 8) - 下一个斐波那契数。
如果我们概括的话,A^n * (1, 0) = (f(n), f(n - 1))

实际的算法需要两个步骤。

  1. 计算 A^2A^4A^8 等,直到我们通过所需的数字。
  2. 使用计算出的 A 幂,按 n 进行二分查找。

附带说明一下,任何形式为 f(n) = k1*f(n-1) + k2*f(n-2) + k3*f(n-3) + .. + kt* 的序列f(nt) 可以这样表示。

Since OP has asked about matrix solution not involving any floating point computations, here it is. We can achieve O(logn) complexity this way, assuming numeric operations have O(1) complexity.

Let's take 2x2 matrix A having following structure

1 1
1 0

Now consider vector (8, 5), storing two consecutive fibonacci numbers. If you multiply it by this matrix, you'll get (8*1 + 5*1, 8*1 + 5*0) = (13, 8) - the next fibonacci number.
If we generalize, A^n * (1, 0) = (f(n), f(n - 1)).

The actual algorithm takes two steps.

  1. Calculate A^2, A^4, A^8, etc. until we pass desired number.
  2. Do a binary search by n, using calculated powers of A.

On a side note, any sequence of the form f(n) = k1*f(n-1) + k2*f(n-2) + k3*f(n-3) + .. + kt*f(n-t) can be presented like this.

旧街凉风 2024-10-26 20:27:05

Wikipedia 给出的结果为

n(F) = Floor[ Log(F Sqrt(5) + 1/2)/Log(Phi)]

Phi 是黄金比例。

Wikipedia gives the result as

n(F) = Floor[ Log(F Sqrt(5) + 1/2)/Log(Phi)]

where Phi is the golden ratio.

调妓 2024-10-26 20:27:05

如果您可以轻松地用二进制解释 F(n),

formula

您可能会对常数 1.7 和 1.1 表示怀疑。这些之所以有效,是因为 d*1.44042009041... + C 永远不会非常接近整数。

如果有兴趣的话,我明天可以发布推导。

下面是一个 n = 2 到 91 的表格,显示了向下取整之前的公式结果:

 n  formula w/o floor     F(n) F(n) in binary

 2  2.540                    1 1
 3  3.981                    2 10
 4  4.581                    3 11
 5  5.421                    5 101
 6  6.862                    8 1000
 7  7.462                   13 1101
 8  8.302                   21 10101
 9  9.743                   34 100010
10 10.343                   55 110111
11 11.183                   89 1011001
12 12.623                  144 10010000
13 13.223                  233 11101001
14 14.064                  377 101111001
15 15.504                  610 1001100010
16 16.104                  987 1111011011
17 17.545                 1597 11000111101
18 18.385                 2584 101000011000
19 19.825                 4181 1000001010101
20 20.425                 6765 1101001101101
21 21.266                10946 10101011000010
22 22.706                17711 100010100101111
23 23.306                28657 110111111110001
24 24.147                46368 1011010100100000
25 25.587                75025 10010010100010001
26 26.187               121393 11101101000110001
27 27.028               196418 101111111101000010
28 28.468               317811 1001101100101110011
29 29.068               514229 1111101100010110101
30 30.508               832040 11001011001000101000
31 31.349              1346269 101001000101011011101
32 32.789              2178309 1000010011110100000101
33 33.389              3524578 1101011100011111100010
34 34.230              5702887 10101110000010011100111
35 35.670              9227465 100011001100110011001001
36 36.270             14930352 111000111101000110110000
37 37.111             24157817 1011100001001111001111001
38 38.551             39088169 10010101000111000000101001
39 39.151             63245986 11110001010000111010100010
40 40.591            102334155 110000110010111111011001011
41 41.432            165580141 1001110111101000110101101101
42 42.032            267914296 1111111110000000110000111000
43 43.472            433494437 11001110101101001100110100101
44 44.313            701408733 101001110011101010010111011101
45 45.753           1134903170 1000011101001010011111110000010
46 46.353           1836311903 1101101011100111110010101011111
47 47.193           2971215073 10110001000110010010010011100001
48 48.634           4807526976 100011110100011010000101001000000
49 49.234           7778742049 111001111101001100010111100100001
50 50.074          12586269025 1011101110001100110011100101100001
51 51.515          20365011074 10010111101110110010110100010000010
52 52.115          32951280099 11110101100000011001010000111100011
53 53.555          53316291173 110001101001111001100000101001100101
54 54.396          86267571272 1010000010101111100101010110001001000
55 55.836         139583862445 10000001111111110110001011011010101101
56 56.436         225851433717 11010010010101110010110110001011110101
57 57.276         365435296162 101010100010101101001000001100110100010
58 58.717         591286729879 1000100110101011011011110111110010010111
59 59.317         956722026041 1101111011000001000100111001011000111001
60 60.157        1548008755920 10110100001101100100000110001001011010000
61 61.598        2504730781961 100100011100101101100101101010100100001001
62 62.198        4052739537881 111010111110011010000110011011101111011001
63 63.038        6557470319842 1011111011011000111101100000110010011100010
64 64.478       10610209857723 10011010011001100001110010100010000010111011
65 65.078       17167680177565 11111001110100101001011110101000010110011101
66 66.519       27777890035288 110010100001110001011010001001010011001011000
67 67.359       44945570212853 1010001110000010110100101111110010101111110101
68 68.800       72723460248141 10000100010010001000000000000111101001001001101
69 69.400      117669030460994 11010110000010011110100110000101111111001000010
70 70.240      190392490709135 101011010010100100110100110001101101000010001111
71 71.681      308061521170129 1000110000010111000101001100010011100111011010001
72 72.281      498454011879264 1110001010101011101011110010100001001111101100000
73 73.121      806515533049393 10110111011000010110000111110110100110111000110001
74 74.561     1304969544928657 100101000101101110011100110001010110000110110010001
75 75.161     2111485077978050 111100000000110001001101110000001010111101111000010
76 76.602     3416454622906707 1100001000110011111101010100001100001000100101010011
77 77.442     5527939700884757 10011101000111010000111000010001101100000010100010101
78 78.042     8944394323791464 11111110001101110000100010110011001101000111001101000
79 79.483    14472334024676221 110011011010101000001011011000100111001001001101111101
80 80.323    23416728348467685 1010011001100010110001111101111000000110010000111100101
81 81.764    37889062373143906 10000110100110111110011011000111100111111011010101100010
82 82.364    61305790721611591 11011001110011010100101010110110101000101101011101000111
83 83.204    99194853094755497 101100000011010010011000101111110010000101000110010101001
84 84.644   160500643816367088 1000111010001101100111110000110100111001010110001111110000
85 85.244   259695496911122585 1110011010100111111010110110110011001001111111000010011001
86 86.085   420196140727489673 10111010100110101100010100111101000000011010101010010001001
87 87.525   679891637638612258 100101101111011101011101011110011011001101010100010100100010
88 88.125  1100087778366101931 111101000100010011000000000110000011010000101001100110101011
89 89.566  1779979416004714189 1100010110011110000011101100100011110011101111101111011001101
90 90.406  2880067194370816120 10011111111000000011011101101010100001101110100111100001111000
91 91.846  4660046610375530309 100000010101011110011111011001111000000001100100101011101000101

推导

在此处输入图像描述

α = log 2/log Φ ≈ 1.44042 所需的精度...

在此处输入图像描述

If you can easily interpret F(n) in binary,

formula

You may be suspicious of the constants 1.7 and 1.1. These work because d*1.44042009041... + C never gets very close to an integer.

I can post a derivation tomorrow if there is interest.

Here is a table with n = 2 through 91, which shows the formula result before flooring:

 n  formula w/o floor     F(n) F(n) in binary

 2  2.540                    1 1
 3  3.981                    2 10
 4  4.581                    3 11
 5  5.421                    5 101
 6  6.862                    8 1000
 7  7.462                   13 1101
 8  8.302                   21 10101
 9  9.743                   34 100010
10 10.343                   55 110111
11 11.183                   89 1011001
12 12.623                  144 10010000
13 13.223                  233 11101001
14 14.064                  377 101111001
15 15.504                  610 1001100010
16 16.104                  987 1111011011
17 17.545                 1597 11000111101
18 18.385                 2584 101000011000
19 19.825                 4181 1000001010101
20 20.425                 6765 1101001101101
21 21.266                10946 10101011000010
22 22.706                17711 100010100101111
23 23.306                28657 110111111110001
24 24.147                46368 1011010100100000
25 25.587                75025 10010010100010001
26 26.187               121393 11101101000110001
27 27.028               196418 101111111101000010
28 28.468               317811 1001101100101110011
29 29.068               514229 1111101100010110101
30 30.508               832040 11001011001000101000
31 31.349              1346269 101001000101011011101
32 32.789              2178309 1000010011110100000101
33 33.389              3524578 1101011100011111100010
34 34.230              5702887 10101110000010011100111
35 35.670              9227465 100011001100110011001001
36 36.270             14930352 111000111101000110110000
37 37.111             24157817 1011100001001111001111001
38 38.551             39088169 10010101000111000000101001
39 39.151             63245986 11110001010000111010100010
40 40.591            102334155 110000110010111111011001011
41 41.432            165580141 1001110111101000110101101101
42 42.032            267914296 1111111110000000110000111000
43 43.472            433494437 11001110101101001100110100101
44 44.313            701408733 101001110011101010010111011101
45 45.753           1134903170 1000011101001010011111110000010
46 46.353           1836311903 1101101011100111110010101011111
47 47.193           2971215073 10110001000110010010010011100001
48 48.634           4807526976 100011110100011010000101001000000
49 49.234           7778742049 111001111101001100010111100100001
50 50.074          12586269025 1011101110001100110011100101100001
51 51.515          20365011074 10010111101110110010110100010000010
52 52.115          32951280099 11110101100000011001010000111100011
53 53.555          53316291173 110001101001111001100000101001100101
54 54.396          86267571272 1010000010101111100101010110001001000
55 55.836         139583862445 10000001111111110110001011011010101101
56 56.436         225851433717 11010010010101110010110110001011110101
57 57.276         365435296162 101010100010101101001000001100110100010
58 58.717         591286729879 1000100110101011011011110111110010010111
59 59.317         956722026041 1101111011000001000100111001011000111001
60 60.157        1548008755920 10110100001101100100000110001001011010000
61 61.598        2504730781961 100100011100101101100101101010100100001001
62 62.198        4052739537881 111010111110011010000110011011101111011001
63 63.038        6557470319842 1011111011011000111101100000110010011100010
64 64.478       10610209857723 10011010011001100001110010100010000010111011
65 65.078       17167680177565 11111001110100101001011110101000010110011101
66 66.519       27777890035288 110010100001110001011010001001010011001011000
67 67.359       44945570212853 1010001110000010110100101111110010101111110101
68 68.800       72723460248141 10000100010010001000000000000111101001001001101
69 69.400      117669030460994 11010110000010011110100110000101111111001000010
70 70.240      190392490709135 101011010010100100110100110001101101000010001111
71 71.681      308061521170129 1000110000010111000101001100010011100111011010001
72 72.281      498454011879264 1110001010101011101011110010100001001111101100000
73 73.121      806515533049393 10110111011000010110000111110110100110111000110001
74 74.561     1304969544928657 100101000101101110011100110001010110000110110010001
75 75.161     2111485077978050 111100000000110001001101110000001010111101111000010
76 76.602     3416454622906707 1100001000110011111101010100001100001000100101010011
77 77.442     5527939700884757 10011101000111010000111000010001101100000010100010101
78 78.042     8944394323791464 11111110001101110000100010110011001101000111001101000
79 79.483    14472334024676221 110011011010101000001011011000100111001001001101111101
80 80.323    23416728348467685 1010011001100010110001111101111000000110010000111100101
81 81.764    37889062373143906 10000110100110111110011011000111100111111011010101100010
82 82.364    61305790721611591 11011001110011010100101010110110101000101101011101000111
83 83.204    99194853094755497 101100000011010010011000101111110010000101000110010101001
84 84.644   160500643816367088 1000111010001101100111110000110100111001010110001111110000
85 85.244   259695496911122585 1110011010100111111010110110110011001001111111000010011001
86 86.085   420196140727489673 10111010100110101100010100111101000000011010101010010001001
87 87.525   679891637638612258 100101101111011101011101011110011011001101010100010100100010
88 88.125  1100087778366101931 111101000100010011000000000110000011010000101001100110101011
89 89.566  1779979416004714189 1100010110011110000011101100100011110011101111101111011001101
90 90.406  2880067194370816120 10011111111000000011011101101010100001101110100111100001111000
91 91.846  4660046610375530309 100000010101011110011111011001111000000001100100101011101000101

Derivation

enter image description here

Required Precision for α = log 2/log Φ ≈ 1.44042...

enter image description here

痞味浪人 2024-10-26 20:27:05

通过计算无界单词来测量内存使用情况有点愚蠢,但只要这是模型,就会有一个 O(log n) 时间、O(1) 个单词 解决方案,类似于 Nikita Rybak 的解决方案,本质上是计算n 通过其 Zeckendorf 表示,它基于斐波那契数列 (YO DAWG)。

矩阵

      1  1
A  =       ,
      1  0

定义满足以下条件的

        F(m + 1)    F(m)
A^m  =                      .
          F(m)    F(m - 1)

: 我们将使用序列 A^F(k),而不是序列 A^(2^k)。后一个序列具有这样的属性:我们可以通过矩阵乘法向前移动

A^F(k + 1) = A^F(k - 1) * A^F(k)

,通过矩阵求逆和乘法向后移动,

A^F(k - 1) = A^F(k + 1) (A^F(k))^-1,

因此我们可以仅使用 eight six 12 个单词构建双向迭代器假设我们将一切都存储为有理数(以避免假设存在单位成本鸿沟)。剩下的就是调整这个 O(1) 空间算法来寻找 Zekendorf 表示。

def zeck(n):
    a, b = (0, 1)
    while b < n:
        a, b = (b, a + b)
    yield a
    n1 = a
    while n1 < n:
        a, b = (b - a, a)
        if n1 + a <= n:
            yield a
            n1 += a
            a, b = (b - a, a)

>>> list(zeck(0))
[0]
>>> list(zeck(2))
[1, 1]
>>> list(zeck(12))
[8, 3, 1]
>>> list(zeck(750))
[610, 89, 34, 13, 3, 1]

Measuring memory usage by counting unbounded words is sort of silly, but as long as that's the model, there's an O(log n) time, O(1) word solution similar to Nikita Rybak's that in essence computes n via its Zeckendorf representation, which is based on the Fibonacci numbers (YO DAWG).

Define the matrix

      1  1
A  =       ,
      1  0

which satisfies

        F(m + 1)    F(m)
A^m  =                      .
          F(m)    F(m - 1)

Instead of the sequence A^(2^k), we're going to use the sequence A^F(k). The latter sequence has the property that we can move forward with a matrix multiply

A^F(k + 1) = A^F(k - 1) * A^F(k)

and backward with a matrix inverse and multiplication

A^F(k - 1) = A^F(k + 1) (A^F(k))^-1,

so we can build a bidirectional iterator with only eight six twelve words assuming we store everything as rationals (to avoid assuming the existence of a unit-cost divide). The rest is just adapting this O(1)-space algorithm for finding a Zeckendorf representation.

def zeck(n):
    a, b = (0, 1)
    while b < n:
        a, b = (b, a + b)
    yield a
    n1 = a
    while n1 < n:
        a, b = (b - a, a)
        if n1 + a <= n:
            yield a
            n1 += a
            a, b = (b - a, a)

>>> list(zeck(0))
[0]
>>> list(zeck(2))
[1, 1]
>>> list(zeck(12))
[8, 3, 1]
>>> list(zeck(750))
[610, 89, 34, 13, 3, 1]
晨曦÷微暖 2024-10-26 20:27:05

已证明 fib n 的公式为 fib(n) = ( (phi)^n - (-phi)^(-n) ) / sqrt(5) 其中 phi = (1+sqrt(5)) / 2,黄金分割数。 (请参阅此链接)。

您可以尝试找到上面 fib 函数的数学逆函数,或者以 32/64 次操作进行二分搜索(取决于可搜索的最大值有多大),以找到与该数字匹配的 n(通过计算 fib 来尝试每个 n (n) 并根据 fib(n) 与给定斐波那契数的比较将样本空间一分为二)。

编辑:@rcollyer 的解决方案更快,因为我的解决方案是 O(lg n) 而他找到的解决方案是 O(1) = 常数时间。

It's been proven that the formula for a fib n is fib(n) = ( (phi)^n - (-phi)^(-n) ) / sqrt(5) where phi = (1+sqrt(5)) / 2, the golden section number. (see this link).

You could try to find a mathematical inverse to the fib function above, or otherwise do a binary search in 32/64 operations (depending on how big your searchable maximum is) to find the n that matches the number (try each n by computing fib(n) and splitting your sample space in two according to how fib(n) compares to the given fibonacci number).

Edit: @rcollyer's solution is faster, as mine is in O(lg n) and the one he found is in O(1) = constant time.

吻风 2024-10-26 20:27:05

所以我正在考虑这个问题,我认为可以在 O(lg n) 时间内使用 O(lg n) 内存使用来完成此操作。这是基于

F(n) = (1 / √5) (Φn - φn)

其中 Φ = (1 + √5)/2且 φ = 1 - Φ。

第一个观察结果是 φn < 1 对于任意 n > 1 1. 这意味着对于任何 n > 2、我们有

F(n) = ⌊ Φn / √5 ⌋

现在,将 n 写成二进制 bk-1bk -2...b1b0。这意味着

n = 2k-1 bk-1 + 2k-2 bk-2 + ... + 21 b1 + 20 b0

这意味着

F(n) = ⌊ Φ2k-1 bk-1 + 2k-2 bk-2 + ... + 21 b1 + 20 b0 / √5 ⌋

或者,更易读的是,

F(n) = ⌊ Φ2k-1 bk-1 Φ2k-2 bk-2 ... Φ21 b 1Φ20 b0 / √5 ⌋

这表明了以下算法。首先,开始计算所有 k 的 Φ2k,直到计算出一个数字 Φz,使得 ⌊ Φz / √5 ⌋ 大于您的数字 F(n)。现在,从那里开始向后迭代以这种方式生成的 Φ 的所有幂。如果当前数字大于指示的 Φ 次方,则将其除以 Φ 次方,并记录该数字除以该值。这个过程本质上是通过一次减去 2 的最大幂来一次恢复 n 的一位。因此,一旦完成,您就会找到n。

该算法的运行时间为 O(lg n),因为您可以通过重复平方生成 Φ2i,而我们只生成 O(lg n) 项。内存使用量为 O(lg n),因为我们存储所有这些值。

So I was thinking about this problem and I think that it's possible to do this in O(lg n) time with O(lg n) memory usage. This is based on the fact that

F(n) = (1 / √5) (Φn - φn)

Where Φ = (1 + √5)/2 and φ = 1 - Φ.

The first observation is that φn < 1 for any n > 1. This means that for any n > 2, we have that

F(n) = ⌊ Φn / √5 ⌋

Now, take n and write it in binary as bk-1bk-2...b1b0. This means that

n = 2k-1 bk-1 + 2k-2 bk-2 + ... + 21 b1 + 20 b0.

This means that

F(n) = ⌊ Φ2k-1 bk-1 + 2k-2 bk-2 + ... + 21 b1 + 20 b0 / √5 ⌋

Or, more readably, that

F(n) = ⌊ Φ2k-1 bk-1Φ2k-2 bk-2 ... Φ21 b1Φ20 b0 / √5 ⌋

This suggests the following algorithm. First, start computing Φ2k for all k until you compute a number Φz such that ⌊ Φz / √5 ⌋ that's greater than your number F(n). Now, from there, iterate backwards across all of the powers of Φ you generated this way. If the current number is bigger than the indicated power of Φ, then divide it by that power of Φ and record that the number was divided by this value. This process essentially recovers one bit of n at a time by subtracting out the largest power of 2 that you can at a time. Consequently, once you're done, you'll have found n.

The runtime of this algorithm is O(lg n), since you can generate Φ2i by repeated squaring, and we only generate O(lg n) terms. The memory usage is O(lg n), since we store all of these values.

痴梦一场 2024-10-26 20:27:05

您可以在 O(1) 时间和 O(1) 空间中找到任意 Fib(n) 的 n。

您可以使用定点 CORDIC 算法仅使用整数数据类型的移位和加法来计算 ln()。

如果 x = Fib(n),则 n 可以通过 CORDIC 确定,

     n = int(2.0801 * ln(x) + 2.1408)

运行时间由所需的精度水平确定。这两个浮点值将被编码为定点值。

该提案的唯一问题是,它返回一个不在斐波那契数列中的数字值,但最初的问题明确指出该函数的输入将为 Fib(n),这意味着只有有效的斐波那契数才是用过的。

You can find n for any Fib(n) in O(1) time and O(1) space.

You can use a fixed-point CORDIC algorithm to compute ln() using only shift and add on integer data types.

If x = Fib(n), then n can be determined by

     n = int(2.0801 * ln(x) + 2.1408)

CORDIC run-time is determined by the desired level of precision. The two floating-point values would be encoded as fixed-point values.

The only issue with this proposal is that it returns a value for numbers that are not in the Fibonacci sequence, but the original problem specifically stated that the input to the function would be Fib(n), which implies that only valid Fibonacci numbers would be used.

黒涩兲箜 2024-10-26 20:27:05

编辑:没关系。提问者在评论中指出,求幂绝对不是常数时间。


求幂是您在恒定时间内允许的数学运算之一吗?如果是这样,我们可以通过 封闭式公式 在恒定时间内计算 F(n) 。然后,给定一些 F,我们可以执行以下操作:

  1. 计算 F(1)、F(2)、F(4)、F(16)、F(256),...直到 F(2^k) < =F< F(2^{k+1})
  2. 在 2^k 和 2^{k+1} 之间对 i 进行二分查找,直到 F(i) <= F < F(i+1)

如果 F = F(n),则第一部分需要 k = O(log(n)) 步骤。第二部分是在大小为 O(2^k) 的范围内进行二分搜索,因此它也需要 k = O(log(n))。因此,总的来说,我们在 O(1) 空间中拥有 O(log(n)) 时间如果(这是一个很大的假设)我们在 O(1) 时间内求幂。

EDIT: Never mind. The asker has stated in comments that exponentiation is definitely not constant time.


Is exponentiation one of the mathematical operations that you'll allow in constant time? If so, we can compute F(n) in constant time via the closed-form formula. Then, given some F, we can do the following:

  1. Compute F(1), F(2), F(4), F(16), F(256), ... until F(2^k) <= F < F(2^{k+1})
  2. Do a binary search for i between 2^k and 2^{k+1} until F(i) <= F < F(i+1)

If F = F(n), then first part takes k = O(log(n)) steps. The second part is a binary search over a range of size O(2^k), so it also takes k = O(log(n)). So, in total, we have O(log(n)) time in O(1) space if (and it's a big if) we have exponentiation in O(1) time.

苦行僧 2024-10-26 20:27:05

斐波那契数列公式的封闭形式为:

Fn = Round(φ^n / Sqrt(5))

其中 φ 是黄金比例。

如果我们忽略舍入因子,则这是可逆的,其反函数为:

F(-1)n= log(n*Sqrt(5))/logφ 

因为我们忽略了舍入因子,所以计算公式中存在错误。然而,如果我们认为数字 n 是斐波那契数,当且仅当区间 [n*φ - 1/n, n*φ + 1/n] 包含自然数时:

一个数是斐波那契数,当且仅当区间 [n* φ - 1/n, n*φ + 1/n] 包含一个自然数,该数字在斐波那契序列中的索引由舍入 log(n*Sqrt(5))/logφ 给出,

这应该可以在(伪)-常数时间取决于用于计算对数和平方根等的算法。

编辑: φ = (1+Sqrt(5))/2

A closed form of the Fibonacci number formula is:

Fn = Round(φ^n / Sqrt(5))

Where φ is the golden ratio.

If we ignore the rounding factor this is invertible and the inverse function is:

F(-1)n= log(n*Sqrt(5))/logφ 

Because we ignored the rounding factor there is an error in the formula which could be calculated. However if we consider that a number n is a Fibonacci number iff the interval [n*φ - 1/n, n*φ + 1/n] contains a natural number then:

A number is a Fibonacci number iff the interval [n*φ - 1/n, n*φ + 1/n] contains a natural number and that number's index in the Fibonacci sequence is given by rounding log(n*Sqrt(5))/logφ

This should be doable in (pseudo)-constant time depending on the algorithms used for calculating the log and square roots etc.

Edit: φ = (1+Sqrt(5))/2

哑剧 2024-10-26 20:27:05

这可能与 user635541 的答案类似。我不完全理解他的做法。

使用其他答案中讨论的斐波那契数的矩阵表示,我们得到了从 F_nF_mF_{n+m} 的方法> 和 F_{nm} 在常数时间内仅使用加、乘、减和除(实际上不是!请参阅更新)。我们还有一个零(单位矩阵),所以它是一个数学群!

通常在进行二分搜索时,我们还需要一个除法运算符来取平均值。或者至少除以 2。但是,如果我们想从 F_{2n}F_n,则需要平方根。幸运的是,事实证明,加号和减号就是我们“接近”二分搜索所需的对数时间!

维基百科写了有关该方法的文章,讽刺的是称为 Fibonacci_search,但文章写得不是很清楚,所以我不知道和我的做法是不是一模一样。理解用于斐波那契搜索的斐波那契数与我们正在寻找的数无关是非常重要的。这有点令人困惑。为了演示该方法,这里首先是仅使用加号和减号的标准“二分搜索”的实现:

def search0(test):
    # Standard binary search invariants:
    #   i <= lo then test(i)
    #   i >= hi then not test(i)
    # Extra invariants:
    #   hi - lo = b
    #   a, b = F_{k-1}, F_k
    a, b = 0, 1
    lo, hi = 0, 1
    while test(hi):
        a, b = b, a + b
        hi = b
    while b != 1:
        mi = lo + a
        if test(mi):
            lo = mi
            a, b = 2*a - b, b - a
        else:
            hi = mi
            a, b = b - a, a
    return lo

>>> search0(lambda n: n**2 <= 25)
5
>>> search0(lambda n: 2**n <= 256)
8

这里 test 是一些布尔函数; ab 是连续的斐波那契数 f_kf_{k-1},这样上层之间的差异上界 hi 和下界 lo 始终为 f_k。我们需要ab,这样我们就可以有效地增加和减少隐式变量k

好吧,那么我们如何使用它来解决这个问题呢?我发现围绕斐波那契表示创建一个包装器很有用,它隐藏了矩阵细节。在实践中(斐波那契搜索器有这样的事情吗?)您可能希望手动内联所有内容。这将为您节省矩阵中的冗余,并围绕矩阵求逆进行一些优化。

import numpy as np
class Fib:
    def __init__(self, k, M):
        """ `k` is the 'name' of the fib, e.g. k=6 for F_6=8.
             We need this to report our result in the very end.
            `M` is the matrix representation, that is
             [[F_{k+1}, F_k], [F_k, F_{k-1}]] """
        self.k = k
        self.M = M
    def __add__(self, other):
        return Fib(self.k + other.k, self.M.dot(other.M))
    def __sub__(self, other):
        return self + (-other)
    def __neg__(self):
        return Fib(-self.k, np.round(np.linalg.inv(self.M)).astype(int))
    def __eq__(self, other):
        return self.k == other.k
    def value(self):
        return self.M[0,1]

然而代码确实有效,所以我们可以按如下方式测试它。请注意,当我们的对象是整数而不是斐波那契时,搜索函数几乎没有什么不同。

def search(test):
    Z = Fib(0, np.array([[1,0],[0,1]])) # Our 0 element
    A = Fib(1, np.array([[1,1],[1,0]])) # Our 1 element
    a, b = Z, A
    lo, hi = Z, A
    while test(hi.value()):
        a, b = b, a + b
        hi = b
    while b != A:
        mi = lo + a
        if test(mi.value()):
            lo = mi
            a, b = a+a-b, b-a
        else:
            hi = mi
            a, b = b-a, a
    return lo.k

>>> search(lambda n: n <= 144)
12
>>> search(lambda n: n <= 0)
0

剩下的悬而未决的问题是是否存在一种有效的幺半群搜索算法。这是不需要减/加逆的。我的猜测是否定的:如果没有负号,您需要 Nikita Rybak 的额外内存。

更新

我刚刚意识到我们根本不需要分裂。 F_n 矩阵的行列式就是 (-1)^n,所以我们实际上可以做任何事情而无需除法。在下面,我删除了所有矩阵代码,但保留了 Fib 类,因为否则一切都会变得非常混乱。

class Fib2:
    def __init__(self, k, fp, f):
        """ `fp` and `f` are F_{k-1} and F_{k} """
        self.k, self.fp, self.f = k, fp, f
    def __add__(self, other):
        fnp, fn, fmp, fm = self.fp, self.f, other.fp, other.f
        return Fib2(self.k + other.k, fn*fm+fnp*fmp, (fn+fnp)*fm+fn*fmp)
    def __sub__(self, other):
        return self + (-other)
    def __neg__(self):
        fp, f = self.f + self.fp, -self.f
        return Fib2(-self.k, (-1)**self.k*fp, (-1)**self.k*f)
    def __eq__(self, other):
        return self.k == other.k
    def value(self):
        return self.f

def search2(test):
    Z = Fib2(0, 1, 0)
    A = Fib2(1, 0, 1)
    ...

>>> search2(lambda n: n <= 280571172992510140037611932413038677189525)
200
>>> search2(lambda n: n <= 4224696333392304878706725602341482782579852840250681098010280137314308584370130707224123599639141511088446087538909603607640194711643596029271983312598737326253555802606991585915229492453904998722256795316982874482472992263901833716778060607011615497886719879858311468870876264597369086722884023654422295243347964480139515349562972087652656069529806499841977448720155612802665404554171717881930324025204312082516817125)
2000
>>> search2(lambda n: n <= 2531162323732361242240155003520607291766356485802485278951929841991312781760541315230153423463758831637443488219211037689033673531462742885329724071555187618026931630449193158922771331642302030331971098689235780843478258502779200293635651897483309686042860996364443514558772156043691404155819572984971754278513112487985892718229593329483578531419148805380281624260900362993556916638613939977074685016188258584312329139526393558096840812970422952418558991855772306882442574855589237165219912238201311184749075137322987656049866305366913734924425822681338966507463855180236283582409861199212323835947891143765414913345008456022009455704210891637791911265475167769704477334859109822590053774932978465651023851447920601310106288957894301592502061560528131203072778677491443420921822590709910448617329156135355464620891788459566081572824889514296350670950824208245170667601726417091127999999941149913010424532046881958285409468463211897582215075436515584016297874572183907949257286261608612401379639484713101138120404671732190451327881433201025184027541696124114463488665359385870910331476156665889459832092710304159637019707297988417848767011085425271875588008671422491434005115288334343837778792282383576736341414410248994081564830202363820504190074504566612515965134665683289356188727549463732830075811851574961558669278847363279870595320099844676879457196432535973357128305390290471349480258751812890314779723508104229525161740643984423978659638233074463100366500571977234508464710078102581304823235436518145074482824812996511614161933313389889630935320139507075992100561077534028207257574257706278201308302642634678112591091843082665721697117838726431766741158743554298864560993255547608496686850185804659790217122426535133253371422250684486113457341827911625517128815447325958547912113242367201990672230681308819195941016156001961954700241576553750737681552256845421159386858399433450045903975167084252876848848085910156941603293424067793097271128806817514906531652407763118308162377033463203514657531210413149191213595455280387631030665594589183601575340027172997222489081631144728873621805528648768511368948639522975539046995395707688938978847084621586473529546678958226255042389998718141303055036060772003887773038422366913820397748550793178167220193346017430024134496141145991896227741842515718997898627269918236920453493946658273870473264523119133765447653295022886429174942653014656521909469613184983671431465934965489425515981067546087342348350724207583544436107294087637975025147846254526938442435644928231027868701394819091132912397475713787593612758364812687556725146456646878912169274219209708166678668152184941578590201953144030519381922273252666652671717526318606676754556170379350956342095455612780202199922615392785572481747913435560866995432578680971243966868110016581395696310922519803685837460795358384618017215468122880442252343684547233668502313239328352671318130604247460452134121833305284398726438573787798499612760939462427922917659263046333084007208056631996856315539698234022953452211505675629153637867252695056925345220084020071611220575700841268302638995272842160994219632684575364180160991884885091858259996299627148614456696661412745040519981575543804847463997422326563897043803732970397488471644906183310144691243649149542394691524972023935190633672827306116525712882959108434211652465621144702015336657459532134026915214509960877430595844287585350290234547564574848753110281101545931547225811763441710217452979668178025286460158324658852904105792472468108996135476637212057508192176910900422826969523438985332067597093454021924077101784215936539638808624420121459718286059401823614213214326004270471752802725625810953787713898846144256909835116371235019527013180204030167601567064268573820697948868982630904164685161783088076506964317303709708574052747204405282785965604677674192569851918643651835755242670293612851920696732320545562286110332140065912751551110134916256237884844001366366654055079721985816714803952429301558096968202261698837096090377863017797020488044826628817462866854321356787305635653577619877987998113667928954840972022833505708587561902023411398915823487627297968947621416912816367516125096563705174220460639857683971213093125)
20000

这一切就像一个魅力。我唯一担心的是位复杂性在计算中占主导地位,我们可能只是进行了顺序搜索。或者实际上,仅查看位数就可以告诉您所查看的内容。但这并不那么有趣。

This might be similar to user635541's answer. I don't fully understand his approach.

Using the matrix representation for Fibonacci numbers, discussed in other answers, we get a way to go from F_n and F_m to F_{n+m} and F_{n-m} in constant time, using only plus, multiplication, minus and division (actually not! see the update). We also have a zero (the identity matrix), so it is a mathematical group!

Normally when doing binary search we also want a division operator for taking averages. Or at least division by 2. However if we want to go from F_{2n} to F_n it requires a square root. Luckily it turns out that plus and minus are all we need for a logarithmic time 'nearly' binary search!

Wikipedia writes about the approach, ironically called Fibonacci_search, but the article is not very clearly written, so I don't know if it is exactly the same approach as mine. It is very important to understand that the Fibonacci numbers used for the Fibonacci search have nothing to do with the numbers we are looking for. It's a bit confusing. To demonstrate the approach, here is first an implementation of standard 'binary search' only using plus and minus:

def search0(test):
    # Standard binary search invariants:
    #   i <= lo then test(i)
    #   i >= hi then not test(i)
    # Extra invariants:
    #   hi - lo = b
    #   a, b = F_{k-1}, F_k
    a, b = 0, 1
    lo, hi = 0, 1
    while test(hi):
        a, b = b, a + b
        hi = b
    while b != 1:
        mi = lo + a
        if test(mi):
            lo = mi
            a, b = 2*a - b, b - a
        else:
            hi = mi
            a, b = b - a, a
    return lo

>>> search0(lambda n: n**2 <= 25)
5
>>> search0(lambda n: 2**n <= 256)
8

Here test is some boolean function; a and b are consecutive fibonacci numbers f_k and f_{k-1} such that the difference between out upper bound hi and lower bound lo is always f_k. We need both a and b so we can increase and decrease the implicit variable k efficiently.

Alright, so how do we use this to solve the problem? I found it useful to create a wrapper around our Fibonacci representation, that hides the matrix details. In practice (is there such a thing for a Fibonacci searcher?) you would want to inline everything manually. That would spare you the redundancy in the matrices and make some optimization around the matrix inversion.

import numpy as np
class Fib:
    def __init__(self, k, M):
        """ `k` is the 'name' of the fib, e.g. k=6 for F_6=8.
             We need this to report our result in the very end.
            `M` is the matrix representation, that is
             [[F_{k+1}, F_k], [F_k, F_{k-1}]] """
        self.k = k
        self.M = M
    def __add__(self, other):
        return Fib(self.k + other.k, self.M.dot(other.M))
    def __sub__(self, other):
        return self + (-other)
    def __neg__(self):
        return Fib(-self.k, np.round(np.linalg.inv(self.M)).astype(int))
    def __eq__(self, other):
        return self.k == other.k
    def value(self):
        return self.M[0,1]

However the code does work, so we can test it as follows. Notice how little different the search function is from when our objects were integers and not Fibonaccis.

def search(test):
    Z = Fib(0, np.array([[1,0],[0,1]])) # Our 0 element
    A = Fib(1, np.array([[1,1],[1,0]])) # Our 1 element
    a, b = Z, A
    lo, hi = Z, A
    while test(hi.value()):
        a, b = b, a + b
        hi = b
    while b != A:
        mi = lo + a
        if test(mi.value()):
            lo = mi
            a, b = a+a-b, b-a
        else:
            hi = mi
            a, b = b-a, a
    return lo.k

>>> search(lambda n: n <= 144)
12
>>> search(lambda n: n <= 0)
0

The remaining open question is whether there is an efficient search algorithm for monoids. That is one that doesn't need a minus / additive inverse. My guess is no: that without minus you need the extra memory of Nikita Rybak.

Update

I just realized that we don't need division at all. The determinant of the F_n matrix is just (-1)^n, so we can actually do everything without division. In the below I removed all the matrix code, but I kept the Fib class, just because everything got so extremely messy otherwise.

class Fib2:
    def __init__(self, k, fp, f):
        """ `fp` and `f` are F_{k-1} and F_{k} """
        self.k, self.fp, self.f = k, fp, f
    def __add__(self, other):
        fnp, fn, fmp, fm = self.fp, self.f, other.fp, other.f
        return Fib2(self.k + other.k, fn*fm+fnp*fmp, (fn+fnp)*fm+fn*fmp)
    def __sub__(self, other):
        return self + (-other)
    def __neg__(self):
        fp, f = self.f + self.fp, -self.f
        return Fib2(-self.k, (-1)**self.k*fp, (-1)**self.k*f)
    def __eq__(self, other):
        return self.k == other.k
    def value(self):
        return self.f

def search2(test):
    Z = Fib2(0, 1, 0)
    A = Fib2(1, 0, 1)
    ...

>>> search2(lambda n: n <= 280571172992510140037611932413038677189525)
200
>>> search2(lambda n: n <= 4224696333392304878706725602341482782579852840250681098010280137314308584370130707224123599639141511088446087538909603607640194711643596029271983312598737326253555802606991585915229492453904998722256795316982874482472992263901833716778060607011615497886719879858311468870876264597369086722884023654422295243347964480139515349562972087652656069529806499841977448720155612802665404554171717881930324025204312082516817125)
2000
>>> search2(lambda n: n <= 2531162323732361242240155003520607291766356485802485278951929841991312781760541315230153423463758831637443488219211037689033673531462742885329724071555187618026931630449193158922771331642302030331971098689235780843478258502779200293635651897483309686042860996364443514558772156043691404155819572984971754278513112487985892718229593329483578531419148805380281624260900362993556916638613939977074685016188258584312329139526393558096840812970422952418558991855772306882442574855589237165219912238201311184749075137322987656049866305366913734924425822681338966507463855180236283582409861199212323835947891143765414913345008456022009455704210891637791911265475167769704477334859109822590053774932978465651023851447920601310106288957894301592502061560528131203072778677491443420921822590709910448617329156135355464620891788459566081572824889514296350670950824208245170667601726417091127999999941149913010424532046881958285409468463211897582215075436515584016297874572183907949257286261608612401379639484713101138120404671732190451327881433201025184027541696124114463488665359385870910331476156665889459832092710304159637019707297988417848767011085425271875588008671422491434005115288334343837778792282383576736341414410248994081564830202363820504190074504566612515965134665683289356188727549463732830075811851574961558669278847363279870595320099844676879457196432535973357128305390290471349480258751812890314779723508104229525161740643984423978659638233074463100366500571977234508464710078102581304823235436518145074482824812996511614161933313389889630935320139507075992100561077534028207257574257706278201308302642634678112591091843082665721697117838726431766741158743554298864560993255547608496686850185804659790217122426535133253371422250684486113457341827911625517128815447325958547912113242367201990672230681308819195941016156001961954700241576553750737681552256845421159386858399433450045903975167084252876848848085910156941603293424067793097271128806817514906531652407763118308162377033463203514657531210413149191213595455280387631030665594589183601575340027172997222489081631144728873621805528648768511368948639522975539046995395707688938978847084621586473529546678958226255042389998718141303055036060772003887773038422366913820397748550793178167220193346017430024134496141145991896227741842515718997898627269918236920453493946658273870473264523119133765447653295022886429174942653014656521909469613184983671431465934965489425515981067546087342348350724207583544436107294087637975025147846254526938442435644928231027868701394819091132912397475713787593612758364812687556725146456646878912169274219209708166678668152184941578590201953144030519381922273252666652671717526318606676754556170379350956342095455612780202199922615392785572481747913435560866995432578680971243966868110016581395696310922519803685837460795358384618017215468122880442252343684547233668502313239328352671318130604247460452134121833305284398726438573787798499612760939462427922917659263046333084007208056631996856315539698234022953452211505675629153637867252695056925345220084020071611220575700841268302638995272842160994219632684575364180160991884885091858259996299627148614456696661412745040519981575543804847463997422326563897043803732970397488471644906183310144691243649149542394691524972023935190633672827306116525712882959108434211652465621144702015336657459532134026915214509960877430595844287585350290234547564574848753110281101545931547225811763441710217452979668178025286460158324658852904105792472468108996135476637212057508192176910900422826969523438985332067597093454021924077101784215936539638808624420121459718286059401823614213214326004270471752802725625810953787713898846144256909835116371235019527013180204030167601567064268573820697948868982630904164685161783088076506964317303709708574052747204405282785965604677674192569851918643651835755242670293612851920696732320545562286110332140065912751551110134916256237884844001366366654055079721985816714803952429301558096968202261698837096090377863017797020488044826628817462866854321356787305635653577619877987998113667928954840972022833505708587561902023411398915823487627297968947621416912816367516125096563705174220460639857683971213093125)
20000

This all works like a charm. My only worry is that the bit complexity such dominates the calculation, that we might as well have just done a sequential search. Or actually, just looking at the number of digits could probably tell you pretty much which you were looking at. That's not as fun though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文