任意のnに対してF(n)を計算する方法は何十通りあり、その多くはランタイムとメモリ使用量が優れています。
ただし、反対の質問をしたいとします。
F(n)がn> 2の場合、nとは何ですか?
(F(1) = F(2) = 1なので、n> 2の制限があり、明確な逆はありません)。
この問題を解決する最も効率的な方法は何でしょうか?フィボナッチ数列を列挙し、目標数に達したときに停止することで、これを線形時間で行うのは簡単ですが、これよりも速く行う方法はありますか?
編集:現在、ここに投稿された最良のソリューションは、数学演算がO(1)で実行されると仮定して、O(log n)メモリを使用してO(log n)時間で実行されます。 WordはO(1)スペースに任意の数を保持できます。 O(1)スペースを使用してフィボナッチ数を計算できるので、メモリ要件を削除できるかどうか知りたいです。
OPは、浮動小数点計算を含まない行列解について質問してきたので、ここにあります。数値演算にO(logn)
の複雑さがあると仮定すると、この方法でO(1)
の複雑さを実現できます。
次の構造を持つ2x2行列A
を取り上げましょう
_1 1
1 0
_
次に、2つの連続するフィボナッチ数を格納するベクトル_(8, 5)
_を考えます。この行列を掛けると、_(8*1 + 5*1, 8*1 + 5*0) = (13, 8)
_-次のフィボナッチ数になります。
一般化すると、A^n * (1, 0) = (f(n), f(n - 1))
。
実際のアルゴリズムには2つのステップがあります。
A^2
_、_A^4
_、_A^8
_などを計算して、必要な数を渡します。n
のべき乗を使用して、A
でバイナリ検索を実行します。余談ですが、f(n) = k1*f(n-1) + k2*f(n-2) + k3*f(n-3) + .. + kt*f(n-t)
という形式のシーケンスは次のように表すことができます。
F(n)をバイナリで簡単に解釈できる場合、
定数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
」
無制限の単語を数えることによるメモリ使用量の測定は愚かなことですが、それがモデルである限り、O(log n)時間がありますO(1) = Nikita Rybakと同様のWordソリューションは、本質的に、フィボナッチ数列(YO DAWG)に基づいて Zeckendorf表現 を介してn
を計算します。
マトリックスを定義する
_ 1 1
A = ,
1 0
_
満足する
_ F(m + 1) F(m)
A^m = .
F(m) F(m - 1)
_
シーケンスA^(2^k)
の代わりに、シーケンスA^F(k)
を使用します。後者のシーケンスには、行列乗算を使用して前に進むことができるという特性があります。
_A^F(k + 1) = A^F(k - 1) * A^F(k)
_
逆行列と乗算
_A^F(k - 1) = A^F(k + 1) (A^F(k))^-1,
_
で双方向イテレータを構築できます 8六 すべてを有理数として格納することを想定した12語(単位コストの分割の存在を想定しないため)。残りは、Zeckendorf表現を見つけるためにこのO(1)空間アルゴリズムを適応させているだけです。
_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]
_
Fib nの式はfib(n) = ( (phi)^n - (-phi)^(-n) ) / sqrt(5)
であることが証明されています。ここで、phi = (1+sqrt(5)) / 2
はゴールデンセクション番号です。 ( このリンク を参照)。
上記のfib関数の数学的逆を見つけようとするか、32/64操作でバイナリ検索を実行して(検索可能な最大値の大きさに応じて)、数値に一致するnを見つけます(fibを計算して各nを試してください) (n)そして、fib(n)が与えられたフィボナッチ数と比較する方法に従って、サンプル空間を2つに分割します。
編集:私がO(lg n)にあり、彼が見つけたものはO(1) =一定時間であるので、@ rcollyerの解はより高速です。
O(1)時間とO(1)スペースで、任意のFib(n)のnを見つけることができます。
固定小数点CORDICアルゴリズムを使用して、シフトと整数データ型の加算のみを使用してln()を計算できます。
X = Fib(n)の場合、nは
n = int(2.0801 * ln(x) + 2.1408)
CORDICランタイムは、必要な精度レベルによって決定されます。 2つの浮動小数点値は、固定小数点値としてエンコードされます。
この提案の唯一の問題は、フィボナッチ数列にない数値の値を返すことですが、元の問題では、関数への入力はFib(n)であり、有効なフィボナッチ数のみが中古。
したがって、私はこの問題について考えていました。O(lg n)のメモリ使用量でO(lg n)時間でこれを行うことが可能だと思います。これは、
F(n)=(1 /√5)(Φん -φん)
ここで、Φ=(1 +√5)/ 2およびφ= 1-Φ。
最初の観察はそのφん <1 for n>1。つまり、n> 2の場合、
F(n)=⌊Φん /√5⌋
次に、nを取得し、それをバイナリとしてbとして書き込みます。k-1bk-2... b1b。この意味は
n = 2k-1 bk-1 + 2k-2 bk-2 + ... + 21 b1 + 2 b。
この意味は
F(n)=⌊Φ2k-1 bk-1 + 2k-2 bk-2 + ... + 21 b1 + 2 b /√5⌋
または、より読みやすく、
F(n)=⌊Φ2k-1 bk-1Φ2k-2 bk-2 ...Φ21 b1Φ2 b /√5⌋
これは、次のアルゴリズムを示唆しています。まず、Φの計算を開始します2k 数Φを計算するまでのすべてのkz thatΦz /√5⌋F(n)より大きい。次に、そこから、この方法で生成したΦのすべてのパワーを逆方向に反復します。現在の数値が示されたΦの累乗よりも大きい場合は、Φのその累乗で除算し、数値がこの値で除算されたことを記録します。このプロセスは、基本的に、一度に可能な最大の2の累乗を差し引くことにより、一度に1ビットのnを回復します。したがって、完了したら、nが見つかります。
Φを生成できるため、このアルゴリズムの実行時間はO(lg n)です。2私 二乗を繰り返して、O(lg n)項のみを生成します。これらの値をすべて格納しているため、メモリ使用量はO(lg n)です。
編集:気にしないでください。質問者はコメントで、べき乗は一定の時間ではないことを述べています。
べき乗は、一定の時間内で許可される数学演算の1つですか?もしそうなら、我々は 閉形式の公式 を介して一定の時間でF(n)を計算できます。次に、いくつかのFが与えられれば、次のようにできます:
F = F(n)の場合、最初の部分はk = O(log(n))ステップになります。2番目の部分は、サイズO(2 ^ k)の範囲にわたるバイナリ検索です、したがって、k = O(log(n))も必要です。したがって、合計でO(log(n))時間O(1)スペースif(そしてそれが大きい場合)O(1)時間で指数化します。
フィボナッチ数式の閉じた形式は次のとおりです。
Fn = Round(φ^n / Sqrt(5))
ここで、φは黄金比です。
丸め係数を無視すると、これは反転可能であり、逆関数は次のとおりです。
F(-1)n= log(n*Sqrt(5))/logφ
丸め係数を無視したため、計算できる式にエラーがあります。ただし、間隔[n *φ-1/n、n *φ+ 1/n]に自然数が含まれている場合、数値nがフィボナッチ数であると考えると、次のようになります。
数は、区間[n *φ-1/n、n *φ+ 1/n]が自然数を含み、フィボナッチ数列内のその数のインデックスが丸めlog(n * Sqrt(5)によって与えられる場合、フィボナッチ数です。 )/logφ
これは、対数や平方根の計算に使用されるアルゴリズムに応じて、(疑似)一定の時間で実行できるはずです。
編集:φ=(1 + Sqrt(5))/ 2