Skip to Content

Números de Fibonacci

La sucesión de Fibonacci se define de la siguiente manera:

F0=0,F1=1,Fn=Fn1+Fn2F_0 = 0, F_1 = 1, F_n = F_{n-1} + F_{n-2}

Los primeros elementos de la sucesión (OEIS A000045 ) son:

0,1,1,2,3,5,8,13,21,34,55,89,...0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …

Propiedades

Los números de Fibonacci poseen muchas propiedades interesantes. Aquí hay algunas de ellas:

  • Identidad de Cassini:

Fn1Fn+1Fn2=(1)nF_{n-1} F_{n+1} - F_n^2 = (-1)^n

Esta identidad se puede demostrar por inducción. Una demostración de una sola línea de Knuth se obtiene tomando el determinante de la forma matricial 2x2 de más abajo.

  • La regla de “suma”:

Fn+k=FkFn+1+Fk1FnF_{n+k} = F_k F_{n+1} + F_{k-1} F_n

  • Aplicando la identidad anterior al caso k=nk = n, obtenemos:

F2n=Fn(Fn+1+Fn1)F_{2n} = F_n (F_{n+1} + F_{n-1})

  • A partir de esto podemos demostrar por inducción que, para cualquier entero positivo kk, FnkF_{nk} es múltiplo de FnF_n.

  • El recíproco también es cierto: si FmF_m es múltiplo de FnF_n, entonces mm es múltiplo de nn.

  • Identidad del GCD:

GCD(Fm,Fn)=FGCD(m,n)GCD(F_m, F_n) = F_{GCD(m, n)}

  • Los números de Fibonacci son las peores entradas posibles para el algoritmo de Euclides (véase el teorema de Lamé en Algoritmo de Euclides)

Codificación de Fibonacci

Podemos usar la sucesión para codificar enteros positivos en palabras de código binarias. Según el teorema de Zeckendorf, cualquier número natural nn se puede representar de forma única como una suma de números de Fibonacci:

N=Fk1+Fk2++FkrN = F_{k_1} + F_{k_2} + \ldots + F_{k_r}

tal que k1k2+2, k2k3+2, , kr2k_1 \ge k_2 + 2,\ k_2 \ge k_3 + 2,\ \ldots,\ k_r \ge 2 (es decir: la representación no puede usar dos números de Fibonacci consecutivos).

Se sigue que cualquier número se puede codificar de forma única en la codificación de Fibonacci. Y podemos describir esta representación con códigos binarios d0d1d2ds1d_0 d_1 d_2 \dots d_s 1, donde did_i es 11 si Fi+2F_{i+2} se usa en la representación. Al código se le agregará un 11 para indicar el final de la palabra de código. Nótese que esta es la única ocurrencia en la que aparecen dos bits 1 consecutivos.

\begin{eqnarray} 1 &=& 1 &=& F_2 &=& (11)_F \ 2 &=& 2 &=& F_3 &=& (011)_F \ 6 &=& 5 + 1 &=& F_5 + F_2 &=& (10011)_F \ 8 &=& 8 &=& F_6 &=& (000011)_F \ 9 &=& 8 + 1 &=& F_6 + F_2 &=& (100011)_F \ 19 &=& 13 + 5 + 1 &=& F_7 + F_5 + F_2 &=& (1001011)_F \end{eqnarray}

La codificación de un entero nn se puede hacer con un algoritmo voraz (greedy) simple:

  1. Iterar por los números de Fibonacci de mayor a menor hasta encontrar uno menor o igual que nn.

  2. Supongamos que este número fue FiF_i. Restar FiF_i de nn y poner un 11 en la posición i2i-2 de la palabra de código (indexando desde 0, del bit más a la izquierda al más a la derecha).

  3. Repetir hasta que no quede resto.

  4. Agregar un 11 final a la palabra de código para indicar su fin.

Para decodificar una palabra de código, primero se quita el 11 final. Después, si el ii-ésimo bit está prendido (indexando desde 0, del bit más a la izquierda al más a la derecha), se suma Fi+2F_{i+2} al número.

Fórmulas para el nthn^{\text{th}} número de Fibonacci { data-toc-label=“Fórmulas para el -ésimo número de Fibonacci” }

Expresión en forma cerrada

Hay una fórmula conocida como “fórmula de Binet”, aunque ya era conocida por Moivre:

Fn=(1+52)n(152)n5F_n = \frac{\left(\frac{1 + \sqrt{5}}{2}\right)^n - \left(\frac{1 - \sqrt{5}}{2}\right)^n}{\sqrt{5}}

Esta fórmula es fácil de demostrar por inducción, pero se puede deducir con ayuda del concepto de funciones generatrices o resolviendo una ecuación funcional.

Se puede notar de inmediato que el valor absoluto del segundo término siempre es menor que 11, y además decrece muy rápido (exponencialmente). Por lo tanto, el valor del primer término por sí solo es “casi” FnF_n. Esto se puede escribir de forma estricta como:

Fn=[(1+52)n5]F_n = \left[\frac{\left(\frac{1 + \sqrt{5}}{2}\right)^n}{\sqrt{5}}\right]

donde los corchetes denotan el redondeo al entero más cercano.

Como estas dos fórmulas exigirían una precisión muy alta al trabajar con números fraccionarios, son de poca utilidad en cálculos prácticos.

Fibonacci en tiempo lineal

El nn-ésimo número de Fibonacci se puede encontrar fácilmente en O(n)O(n) calculando los números uno por uno hasta nn. Sin embargo, también hay formas más rápidas, como veremos.

Podemos partir de un enfoque iterativo, para aprovechar el uso de la fórmula Fn=Fn1+Fn2F_n = F_{n-1} + F_{n-2}; por lo tanto, simplemente precalcularemos esos valores en un arreglo. Teniendo en cuenta los casos base para F0F_0 y F1F_1.

int fib(int n) { int a = 0; int b = 1; for (int i = 0; i < n; i++) { int tmp = a + b; a = b; b = tmp; } return a; }

De esta manera obtenemos una solución lineal, de tiempo O(n)O(n), conservando todos los valores anteriores a nn en la sucesión.

Forma matricial

Para pasar de (Fn,Fn1)(F_n, F_{n-1}) a (Fn+1,Fn)(F_{n+1}, F_n), podemos expresar la recurrencia lineal como una multiplicación de matrices 2x2:

(1110)(FnFn1)=(Fn+Fn1Fn)=(Fn+1Fn) (1amp;11amp;0)\begin{pmatrix} 1 &amp; 1 \ 1 &amp; 0 \end{pmatrix} (FnFn1)\begin{pmatrix} F_n \ F_{n-1} \end{pmatrix}

(Fn+Fn1Fn)\begin{pmatrix} F_n + F_{n-1} \ F_{n} \end{pmatrix}

(Fn+1Fn)\begin{pmatrix} F_{n+1} \ F_{n} \end{pmatrix}

Esto nos permite tratar la iteración de la recurrencia como una multiplicación repetida de matrices, que tiene propiedades convenientes. En particular,

(1110)n(F1F0)=(Fn+1Fn) (1amp;11amp;0)\begin{pmatrix} 1 &amp; 1 \ 1 &amp; 0 \end{pmatrix}^n (F1F0)\begin{pmatrix} F_1 \ F_0 \end{pmatrix}

(Fn+1Fn)\begin{pmatrix} F_{n+1} \ F_{n} \end{pmatrix}

donde F1=1,F0=0F_1 = 1, F_0 = 0. De hecho, como

(1110)=(F2F1F1F0) (1amp;11amp;0)\begin{pmatrix} 1 &amp; 1 \ 1 &amp; 0 \end{pmatrix} = (F2amp;F1F1amp;F0)\begin{pmatrix} F_2 &amp; F_1 \ F_1 &amp; F_0 \end{pmatrix}

podemos usar la matriz de forma directa:

(1110)n=(Fn+1FnFnFn1) (1amp;11amp;0)\begin{pmatrix} 1 &amp; 1 \ 1 &amp; 0 \end{pmatrix}^n = (Fn+1amp;FnFnamp;Fn1)\begin{pmatrix} F_{n+1} &amp; F_n \ F_n &amp; F_{n-1} \end{pmatrix}

Así, para encontrar FnF_n en tiempo O(logn)O(\log n), hay que elevar la matriz a la nn. (Véase Exponenciación binaria)

struct matrix { long long mat[2][2]; matrix friend operator *(const matrix &a, const matrix &b){ matrix c; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { c.mat[i][j] = 0; for (int k = 0; k < 2; k++) { c.mat[i][j] += a.mat[i][k] * b.mat[k][j]; } } } return c; } }; matrix matpow(matrix base, long long n) { matrix ans{ { {1, 0}, {0, 1} } }; while (n) { if(n&1) ans = ans*base; base = base*base; n >>= 1; } return ans; } long long fib(int n) { matrix base{ { {1, 1}, {1, 0} } }; return matpow(base, n).mat[0][1]; }

Método de duplicación rápida

Al expandir la expresión matricial anterior para n=2kn = 2\cdot k

(F2k+1F2kF2kF2k1)=(1110)2k=(Fk+1FkFkFk1)2 (F2k+1amp;F2kF2kamp;F2k1)\begin{pmatrix} F_{2k+1} &amp; F_{2k}\ F_{2k} &amp; F_{2k-1} \end{pmatrix}

(1amp;11amp;0)\begin{pmatrix} 1 &amp; 1\ 1 &amp; 0 \end{pmatrix}^{2k}

(Fk+1amp;FkFkamp;Fk1)\begin{pmatrix} F_{k+1} &amp; F_{k}\ F_{k} &amp; F_{k-1} \end{pmatrix} ^2

podemos encontrar estas ecuaciones más simples:

F2k+1=Fk+12+Fk2F2k=Fk(Fk+1+Fk1)=Fk(2Fk+1Fk). F2k+1amp;=Fk+12+Fk2F2kamp;=Fk(Fk+1+Fk1)=Fk(2Fk+1Fk)\begin{align} F_{2k+1} &amp;= F_{k+1}^2 + F_{k}^2 \ F_{2k} &amp;= F_k(F_{k+1}+F_{k-1}) = F_k (2F_{k+1} - F_{k})\ \end{align}.

Así, usando las dos ecuaciones anteriores, los números de Fibonacci se pueden calcular fácilmente con el siguiente código:

pair<int, int> fib (int n) { if (n == 0) return {0, 1}; auto p = fib(n >> 1); int c = p.first * (2 * p.second - p.first); int d = p.first * p.first + p.second * p.second; if (n & 1) return {d, c + d}; else return {c, d}; }

El código anterior devuelve FnF_n y Fn+1F_{n+1} como un par.

Periodicidad módulo p

Consideremos la sucesión de Fibonacci módulo pp. Demostraremos que la sucesión es periódica.

Demostrémoslo por contradicción. Consideremos los primeros p2+1p^2 + 1 pares de números de Fibonacci tomados módulo pp:

(F0, F1), (F1, F2), , (Fp2, Fp2+1)(F_0,\ F_1),\ (F_1,\ F_2),\ \ldots,\ (F_{p^2},\ F_{p^2 + 1})

Solo puede haber pp restos distintos módulo pp, y a lo sumo p2p^2 pares distintos de restos, así que hay al menos dos pares idénticos entre ellos. Esto basta para demostrar que la sucesión es periódica, ya que un número de Fibonacci solo está determinado por sus dos predecesores. Por lo tanto, si se repiten dos pares de números consecutivos, eso también significa que los números posteriores al par se repetirán de la misma manera.

Ahora elegimos dos pares de restos idénticos con los índices más chicos en la sucesión. Sean los pares (Fa, Fa+1)(F_a,\ F_{a + 1}) y (Fb, Fb+1)(F_b,\ F_{b + 1}). Demostraremos que a=0a = 0. Si esto fuera falso, habría dos pares anteriores (Fa1, Fa)(F_{a-1},\ F_a) y (Fb1, Fb)(F_{b-1},\ F_b) que, por la propiedad de los números de Fibonacci, también serían iguales. Sin embargo, esto contradice el hecho de que habíamos elegido pares con los índices más chicos, lo que completa nuestra demostración de que no hay preperíodo (es decir, los números son periódicos a partir de F0F_0).

Problemas de práctica