Is there any algorithm to compute the nth fibonacci number in sub linear time?
相关问题
- Faster loop: foreach vs some (performance of jsper
- Why wrapping a function into a lambda potentially
- Finding k smallest elements in a min heap - worst-
- binary search tree path list
- High cost encryption but less cost decryption
相关文章
- What are the problems associated to Best First Sea
- ceil conterpart for Math.floorDiv in Java?
- Coin change DP solution to keep track of coins
- why 48 bit seed in util Random class?
- Algorithm for partially filling a polygonal mesh
- Robust polygon normal calculation
- DOM penalty of using html attributes
- Which is faster, pointer access or reference acces
Following from Pillsy's reference to matrix exponentiation, such that for the matrix
then
Raising matrices to powers using repeated multiplication is not very efficient.
Two approaches to matrix exponentiation are divide and conquer which yields Mn in O(ln n) steps, or eigenvalue decomposition which is constant time, but may introduce errors due to limited floating point precision.
If you want an exact value greater than the precision of your floating point implementation, you have to use the O ( ln n ) approach based on this relation:
The eigenvalue decomposition on M finds two matrices U and Λ such that Λ is diagonal and
Raising a the diagonal matrix Λ to the nth power is a simple matter of raising each element in Λ to the nth, so this gives an O(1) method of raising M to the nth power. However, the values in Λ are not likely to be integers, so some error will occur.Defining Λ for our 2x2 matrix as
To find each λ, we solve
which gives
using the quadratic formula
If you've read Jason's answer, you can see where this is going to go.
Solving for the eigenvectors X1 and X2:
These vectors give U:
Inverting U using
so U-1 is given by
Sanity check:
So the sanity check holds.
Now we have everything we need to calculate Mn1,2:
so
Which agrees with the formula given elsewhere.
You can derive it from a recurrance relation, but in engineering computing and simulation calculating the eigenvalues and eigenvectors of large matrices is an important activity, as it gives stability and harmonics of systems of equations, as well as allowing raising matrices to high powers efficiently.
The
n
th Fibonacci number is given bywhere
Assuming that the primitive mathematical operations (
+
,-
,*
and/
) areO(1)
you can use this result to compute then
th Fibonacci number inO(log n)
time (O(log n)
because of the exponentiation in the formula).In C#:
Wikipedia has a closed form solution http://en.wikipedia.org/wiki/Fibonacci_number
Or in c#:
Here's my recursive version that recurses log(n) times. I think that it's easiest to read in the recursive form:
It works because you can compute
fib(n),fib(n-1)
usingfib(n-1),fib(n-2)
if n is odd and if n is even, you can computefib(n),fib(n-1)
usingfib(n/2),fib(n/2-1)
.The base case and the odd case are simple. To derive the even case, start with a,b,c as consecutive fibonacci values (eg, 8,5,3) and write them in a matrix, with a = b+c. Notice:
From that, we see that a matrix of the first three fibonacci numbers, times a matrix of any three consecutive fibonacci numbers, equals the next. So we know that:
So:
Simplifying the right hand side leads to the even case.
For really big ones, this recursive function works. It uses the following equations:
You need a library that lets you work with big integers. I use the BigInteger library from https://mattmccutchen.net/bigint/.
Start with an array of of fibonacci numbers. Use fibs[0]=0, fibs[1]=1, fibs[2]=1, fibs[3]=2, fibs[4]=3, etc. In this example, I use an array of the first 501 (counting 0). You can find the first 500 non-zero Fibonacci numbers here: http://home.hiwaay.net/~jalison/Fib500.html. It takes a little editing to put it in the right format, but that is not too hard.
Then you can find any Fibonacci number using this function (in C):
I've tested this for the 25,000th Fibonacci number and the like.
You can do it by exponentiating a matrix of integers as well. If you have the matrix
then
(M^n)[1, 2]
is going to be equal to then
th Fibonacci number, if[]
is a matrix subscript and^
is matrix exponentiation. For a fixed-size matrix, exponentiation to an positive integral power can be done in O(log n) time in the same way as with real numbers.EDIT: Of course, depending on the type of answer you want, you may be able to get away with a constant-time algorithm. Like the other formulas show, the
n
th Fibonacci number grows exponentially withn
. Even with 64-bit unsigned integers, you'll only need a 94-entry lookup table in order to cover the entire range.SECOND EDIT: Doing the matrix exponential with an eigendecomposition first is exactly equivalent to JDunkerly's solution below. The eigenvalues of this matrix are the
(1 + sqrt(5))/2
and(1 - sqrt(5))/2
.