Linear recurrence relations
A linear recurrence relation is a function or sequence of terms where each term is a linear combination of previous terms. As such, only multiplications by constants are allowed per each term before adding them up.
When prompted with the following task
Given f, a function defined as a linear recurrence relation, compute f(N) where N might get very large
the right way to approach the problem isn’t by brute-forcing the solution (e.g. by sieving as in primes generation) but rather to find a transformation matrix for the recurrence and repeatedly multiplying it by itself in order to find the result (i.e. applying it multiple times to an input vector).
Constructing a transformation matrix such that
\[TF_i = F_{i+1}\]is the fundamental step. In the Fibonacci sequence
\[T = \begin{bmatrix} 0 & 1 \\ 1 & 1 \end{bmatrix}\]To efficiently compute \( T^{N-1} \) the most popular method is to use exponentiation by squaring that does it in \( O(\log{N}) \) time. A brief reminder follows
\[x^y= \begin{cases} x \, ( x^{2})^{\frac{y - 1}{2}}, & \mbox{if } y \mbox{ is odd} \\ (x^{2})^{\frac{y}{2}} , & \mbox{if } y \mbox{ is even}. \end{cases}\]Multiplying two matrices together takes \( O(K^3) \) time (with \( K \) being any of the transformation matrix dimensions) with the standard method so overall is \( O(K^3 \log{N}) \).
Putting everything together
The following code calculates the \( N^{th} \) Fibonacci number in \( O(K^3 \log{N}) \)