Números pares de Fibonacci

Inspirado por un comentario en una publicación de Fibonacci para una entrevista . El usuario pavellyzhin mencionó la siguiente tarea de entrevista ( comentario ):
Hace más de un año, "php-programmer" respondió a la vacante, enviaron TK y hubo una tarea de Fibonacci: seleccionar todos los números de Fibonacci incluso en el rango de 1 a 10000 . Decidió usar un bucle (for). Allí, también era necesario hacer una consulta SQL para seleccionar los cumpleaños más cercanos de los usuarios, para inventar algo, simplemente no recuerdo y escribo algún tipo de función. Hice todo, lo envié. Enviaron una respuesta: "de acuerdo con los resultados de la tarea de prueba, usted no es aceptado". Lo que no les gustó exactamente no fue escrito. Ahora estoy sentado y pensando, probablemente después de todo por Fibonacci volé ... :)
En esta publicación voy a mostrar cómo fue posible resolver este problema de manera efectiva, y tal vez incluso de manera eficiente, pero esto no es exacto. Al mismo tiempo, demostraré un par de miles de hechos probados sobre los números de Fibonacci.


Teorizando



La mejor manera de comenzar es mirar a través de los ojos de los primeros números de N Fibonacci e intentar encontrar un patrón en la disposición de los números pares.

1.1, bf2,3.5, bf8,13.21, bf34,55.89, bf144, ldots


Los números pares están marcados en la secuencia, como puede ver, cada tercer número de Fibonacci es par y, probablemente, todos los números pares están en posiciones de múltiplos de 3. Esta será nuestra suposición, ahora debemos confirmarlo y desarrollar un algoritmo de cálculo.

La mejor prueba es simple, así que gracias a AllexIn por la idea simple que inicialmente me perdí. Cada número subsiguiente de Fibonacci es la suma de los dos anteriores, si los dos números anteriores son impares, el siguiente será par, si en los dos números anteriores uno es impar y el otro es par, entonces el siguiente será impar. En principio, esta idea por sí sola ya es suficiente para "palpar intuitivamente" el hecho comprobado. La prueba por inducción es obvia, pero no puedo resistirme, para no traerla.

Probamos que "cada tercer número de Fibonacci es par, y los dos que preceden a cada número son impares".
  • Base de inducción . Los dos primeros números de Fibonacci 1.1 - impar, tercer número 2 - incluso
  • Hipótesis Suponga que hasta un número de Fibonacci múltiplo de 3 es cierto que cada tercio es par, y los dos anteriores son impares.
  • Paso de inducción . El número que sigue al último par de la hipótesis es impar, porque se obtiene de la suma de lo impar con lo par, después de ese número ya también es impar, porque se obtiene de la suma de los pares con los impares, y el siguiente después de que es par, porque los dos anteriores que acaba de recibir son impares, por construcción su número es múltiplo de 3, es par, y los dos anteriores son impares.


Así es como podemos probar nuestras suposiciones sin siquiera recurrir a cálculos matemáticos. Puede formalizar esta idea, al mismo tiempo que obtiene una fórmula para calcular cada tercer número de Fibonacci Fn+3 de Fn y Fn+1 . Usando la relación recursiva Fn+2=Fn+1+Fn obtenemos:

Fn+3=Fn+2+Fn+1=2Fn+1+Fn


Entonces si Fn - incluso entonces Fn+3 También incluso en virtud de esta fórmula. Dado que F3=2 , entonces cada tercer número de Fibonacci es realmente par, lo que confirma parte de nuestra suposición. Aquí debe asegurarse de no perder otros números pares, es decir, que todos tienen múltiplos de 3. Gracias a janatem por su idea simple, porque de la fórmula anterior para Fn+3 También se deduce que si Fn - extraño entonces Fn+3 también extraño, así que obtenemos esos números con números 3k2,3k1,k in mathbbN - impar (por inducción, comience con F1=F2=1 - impar), y 3k,k in mathbbN - par, que cubre todos los números de Fibonacci, lo que significa que realmente cubrimos todos los números pares.

Hay otra forma, ya que sería posible demostrar que no hay otros números pares. Supongamos que existe un número Fm - incluso y 0 not equivm mod3 entonces m=3k1 o m=3k+1 donde k - Algún tipo de natural.

Pasemos a la representación matricial de los números de Fibonacci de la publicación original

\ begin {pmatrix} 0 & 1 \\ 1 & 1 \ end {pmatrix} ^ n = \ begin {pmatrix} F_ {n-1} & F_n \\ F_n & F_ {n + 1} \ end {pmatrix}

\ begin {pmatrix} 0 & 1 \\ 1 & 1 \ end {pmatrix} ^ n = \ begin {pmatrix} F_ {n-1} & F_n \\ F_n & F_ {n + 1} \ end {pmatrix}


Calculando el determinante de ambas partes, obtenemos

(1)n=Fn+1Fn1F2n


Se deduce que los divisores de números Fn+1,Fn y Fn1,Fn divisores de partido (1)n es decir los números vecinos de Fibonacci son mutuamente simples. Esto también significa que la simplicidad mutua y los números F3k,F3k1 y F3k,F3k+1 es decir F3k y Fm . Pero por suposición Fm - incluso, y F3k - incluso como se probó previamente. Así que otros números pares que F3k donde k in mathbbN en la secuencia de Fibonacci no existe. Y también establecimos un hecho interesante de que los números vecinos de Fibonacci son mutuos simples.

Finalmente, mostramos al menos una forma más de demostrar nuestra suposición: usar el teorema de Luke.

El teorema de Luke . El entero divide Fm y Fn , si y solo si es un divisor Fd donde d= mcd(m,n) en particular

 gcd(Fm,Fn)=F gcd(m,n)


Aqui  gcd Es el mayor factor común. Si poner m=3 entonces  gcd(2,Fn)=F gcd(3,n) . Si Fn - incluso, entonces el lado izquierdo es 2, de modo que el lado derecho también es igual a 2, es necesario que n dividido por 3 y al mismo tiempo lo contrario es cierto. Por lo tanto, obtenemos exactamente lo que queríamos probar.

Entonces, cada tercer número de Fibonacci es par, y cada par tiene un múltiplo de tres. Hemos probado esto cuidadosamente y nadie se atreve a dudarlo ahora.

Algoritmo


Y ahora queda por encontrar un algoritmo. Por supuesto, puede hacer lo que originalmente hizo pavellyzhin , pero en lugar de verificar 0 equivFn mod2 podemos verificar 0 equivn mod3 , esto es un giro! Es cierto que esto no afecta el número de iteraciones del algoritmo, porque acabamos de cambiar el filtro de secuencia. Es mejor generar inmediatamente una subsecuencia de números de Fibonacci con la propiedad que necesitamos (paridad), por lo que otra forma obvia es usar la fórmula de Binet

F_n = \ left \ lfloor \ frac {\ varphi ^ n} {\ sqrt {5}} \ right \ rceil, \ qquad n \ in \ {3,6, \ ldots, 3k \ ldots \}

F_n = \ left \ lfloor \ frac {\ varphi ^ n} {\ sqrt {5}} \ right \ rceil, \ qquad n \ in \ {3,6, \ ldots, 3k \ ldots \}


Hay dificultades con la eficiencia de los cálculos, más sobre esto en la publicación original. Por lo tanto, propongo el mejor método, en mi opinión, cálculo iterativo Fn+3 , esto se puede hacer, como mostramos anteriormente, mediante la fórmula Fn+3=2Fn+1+Fn . Para construir una transición iterativa en el algoritmo, necesitamos calcular Fn+4 , todo es igual de simple

Fn+4=Fn+3+Fn+2=2Fn+1+Fn+Fn+1+Fn=3Fn+1+2Fn


Por cierto, en general, es fácil demostrar que

Fn+m=FmFn+1+Fm1Fn


Luego, formalmente, el algoritmo se escribe de la siguiente manera (el número actual actual de Fibonacci Fn seguido por el número de Fibonacci Fn+1 , M Es el límite superior para los números dados en la condición del problema):

  1. Fn leftarrowF3=2, quadFn+1 leftarrowF4=3
  2. Si Fn>M , luego termine, de lo contrario agregue al resultado Fn
  3. (Fn,Fn+1) leftarrow(2Fn+1+Fn,3Fn+1+2Fn) vaya al paso 2.

El algoritmo es bastante trivial: simplemente saltamos a cada tercer número de Fibonacci e imprimimos (si no es más M ) La complejidad del algoritmo sigue siendo lineal, pero el número de repeticiones del paso 2 es exactamente igual al número de números pares de Fibonacci en el rango 1 ldotsM , para comparar, un algoritmo simple con filtrado requiere 3 veces más iteraciones (por cada encontrado, habrá 2 descartados).

El algoritmo existe en papel, ¿cuál fue la entrevista, PHP? Bueno, finalmente descubrir PHP significa

function evenfibs($ubound) { $result = []; [$evenf, $nextf] = [2, 3]; while($evenf <= $ubound) { array_push($result, $evenf); [$nextf, $evenf] = [ 3 * $nextf + 2 * $evenf, 2 * $nextf + $evenf]; } return $result; } 


Nota : Este método siempre se puede mejorar, como, por ejemplo, mostró el usuario hunroll . La idea es que para los cálculos no necesitamos nada superfluo, excepto el resultado parcialmente obtenido, es decir. podemos calcular números pares usando solo los números anteriores de Fibonacci pares.

Fn+3=2Fn+1+Fn=3Fn+2Fn1=3Fn+Fn1+Fn1=3Fn+(Fn1+Fn2)+Fn3=4Fn+Fn3



 function evenfibs($ubound) { if($ubound < 2) return []; $evens = [2]; $next = 8; for($i = 1; $next <= $ubound; $i++) { $evens[$i] = $next; $next = $evens[$i]*4 + $evens[$i-1]; } return $evens; } 


Generalización


Mencionamos aquí el teorema de Luke, que establece que  gcd(Fm,Fn)=F gcd(m,n) . Como consecuencia de ello, podemos obtener que el número de Fibonacci Fn múltiplo de Fm , si y solo si su número n múltiplo a número m . Es decir cada 4to número de Fibonacci se divide por 3, cada 5to por 5, cada 6to por 8, etc.

Luego, de manera simple, obtenemos un algoritmo para calcular la subsecuencia de Fibonacci, en el que los elementos son múltiplos de un número dado Fm . Usando el hecho de que

Fn+m=FmFn+1+Fm1FnFn+m+1=Fm+1Fn+1+FmFn


El algoritmo anterior se convierte en

  1. Fn leftarrowFm, quadFn+1 leftarrowFm+1
  2. Si Fn>M , luego termine, de lo contrario agregue al resultado Fn
  3. (Fn,Fn+1) leftarrow(FmFn+1+Fm1Fn,Fm+1Fn+1+FmFn) vaya al paso 2.

Donde Fm1,Fm,Fm+1 se puede establecer como constantes.

Resumen de notas . Como la ignorancia del usuario señaló correctamente, en el caso generalizado, también es posible construir un algoritmo que use solo números de un resultado parcial.

Fn+1=Fn+Fn1Fn+2=3FnFn2Fn+3=4Fn+Fn3Fn+4=7FnFn4Fn+5=11Fn+Fn5 cdotsFn+t=(Ft+2Ft1)Fn+(1)t1Fnt



Probemos esto por el método de inducción matemática, para t = 1 yt = 2, el cumplimiento es obvio. Supongamos que soporta algo de t; entonces

Fn+t+1=Fn+t+Fn+t1=(Ft+2Ft1)Fn+(1)t1Fnt+(Ft1+2Ft2)Fn+(1)t2Fnt+1=(Ft+Ft1+2(Ft1+Ft2))Fn+(1)t1(FntFnt+1)=(Ft+1+2Ft)Fn+(1)t1(FntFntFnt1)=(Ft+1+2Ft)Fn+(1)tFnt1



Algo como un total


La tarea, por supuesto, es completamente sintética, el número de iteraciones es muy pequeño (para M=$10,00 la respuesta contiene solo 6 números, es decir Se habrían completado 6 iteraciones, y el algoritmo original "de frente" habría requerido 18), pero de esta manera un usuario que descubrió algo nuevo aquí ahora puede mostrar un poco más de conocimiento matemático en los números de Fibonacci en la entrevista.

Editar: Gracias a los usuarios de janatem y AllexIn por las pruebas simples, las incluí en "Teoremización", así como también por el algoritmo usando solo los números pares ya obtenidos en los cálculos y la ignorancia del usuario por generalizarlo.

Source: https://habr.com/ru/post/450594/


All Articles