More than a year ago, the php-programmer responded to the vacancy, sent a request and there was a task from Fibonacci: select all even Fibonacci numbers in the range from 1 to 10,000 . Decided using a loop (for). It was also necessary to create a SQL query for a sample of the next days of users' births, to impose something, I do not remember exactly, and write some function. I did everything, sent it. They sent the answer: “according to the results of the test task, you are not accepted”. What exactly they did not like and did not write. Right now I am sitting and thinking, probably because of Fibonacci, flying all the same ... :)
In this post I am going to show how it was possible to solve this problem effectively, and maybe even effectively, but this is not accurate. At the same time I will demonstrate a couple of thousands of facts proved about the Fibonacci numbers.
Theorize
The best thing to begin with is to look through the eyes of the first N Fibonacci numbers and try to find a pattern in the arrangement of even numbers.
Even numbers are marked in the sequence, as you can see every 3rd Fibonacci number is even, and probably all even numbers are in positions of multiples of 3. This will be our guess, now we need to confirm it and work out a calculation algorithm. ')
The best proof is simple, so thanks to AllexIn for the simple idea that I originally missed. Each subsequent Fibonacci number is the sum of the two previous ones, if the two previous numbers are odd, then the next one will be even, if the two previous numbers have one odd and the other even, then the next will be odd. In principle, this idea alone is already enough to “intuitively grope” the fact being proved. The proof by induction is obvious, but I cannot help but lead him
We prove that "every third Fibonacci number is even, and the two preceding each such number are odd."
Base induction . The first two numbers of fibonacci - odd, third number - even
Hypothesis Suppose that up to some multiple of the number 3 Fibonacci number is satisfied that every third is even, and the two preceding ones are odd.
Induction step . The number following the last even of the hypothesis is odd, since it is obtained from the sum of the odd with the even, the next after this number is also odd, because it is obtained from the sum of an even with an odd, and the next after it is even, because the two previous ones for him are odd, by construction its number is a multiple of 3, it is even, and the two preceding are odd.
This is how you can prove our guess without even resorting to mathematical calculations. You can formalize this idea, at the same time getting the formula to calculate every third Fibonacci number of and . Using the recurrence ratio we will receive:
So, if - even, then also even by virtue of this formula. Considering that , then every third Fibonacci number is really even, which confirms part of our guess. Here it is necessary to make sure that we do not miss other even numbers, i.e. that they all have multiples of 3. Thanks to janatem for his simple idea, because from the above formula for it also follows that if - odd then also odd, so we get the numbers with numbers - odd (by induction, start with - odd), and - even that covers all Fibonacci numbers, which means we really cover all even numbers.
There is still a way to show that there are no other even numbers. Suppose there is a number - even and then or where - some kind of natural.
Referring to the matrix representation of the Fibonacci numbers from the original post.
\ begin {pmatrix} 0 & 1 \\ 1 & 1 \ end {pmatrix} ^ n = \ begin {pmatrix} F_ {n-1} & F_n \\ F_n & F_ {n + 1} \ end {pmatrix}
Calculating the determinant of both parts, we get
It follows that the divisors of the numbers and match divisors i.e. neighboring Fibonacci numbers are mutually simple. This also means that mutually simple numbers and i.e. and . But by assumption - even, and - even on proven earlier. Thus, other even numbers except where in the Fibonacci sequence does not exist. And also we have established an interesting fact that neighboring Fibonacci numbers are mutually simple.
Finally, we will show at least one more way to prove our guess - use Luke's theorem.
Luke's theorem . Integer divides and if and only if it is a divisor where , in particular
Here - the greatest common divisor. If we put then . If a - even, then the left side is equal to 2, then the right side should also be 2, so that divided by 3 and at the same time the opposite is true. Thus we get exactly what we wanted to prove.
So, every third Fibonacci number is even, and every even number has a multiple of three. We have thoroughly proved it and no one dares to doubt it now.
Algorithm
And now it remains to come up with an algorithm. You can certainly do as originally pavellyzhin , but instead of checking we can check , What a twist! True, this does not affect the number of iterations of the algorithm, because we just changed the filter sequence. It is better to immediately generate a subsequence of Fibonacci numbers with the property we need (parity), so another obvious way is to use the Binet formula
F_n = \ left \ lfloor \ frac {\ varphi ^ n} {\ sqrt {5}} \ right \ rceil, \ qquad n \ in \ {3,6, \ ldots, 3k \ ldots \}
There are some difficulties with the efficiency of calculations, more about this in the original post. Therefore, I propose the best, in my opinion, method - iterative calculation , this can be done, as we have previously shown, by the formula . To build an iterative transition in the algorithm, we need to calculate , everything is just as simple
By the way, generally speaking it is easy to prove that
Then the algorithm is formally written as follows (the current even Fibonacci number the next Fibonacci number , - the upper limit for numbers given in the problem statement):
If a , then finish, otherwise add to the result
, go to step 2.
The algorithm is rather trivial - we simply jump over every third Fibonacci number and output it (if it is not more than ). The complexity of the algorithm is still linear, but the number of repetitions of step 2 is exactly equal to the number of even Fibonacci numbers in the range , for comparison, a simple algorithm with filtering requires 3 times more iterations (for each found, there will be 2 drops).
The algorithm exists on paper, on what was there an interview, PHP? Well, finally, uncover PHP means
Note : This method can always be improved, as, for example, showed the user hunroll . The idea is that for calculations we do not need anything superfluous, except for the partially obtained result, i.e. we can calculate even numbers using only previous even Fibonacci numbers.
We mentioned here the Luke theorem, which states that . As a consequence of it, we can get that Fibonacci number multiple of number if and only if its number multiple of number . Those. each 4th Fibonacci number is divided by 3, each 5th by 5, each 6th by 8, and so on.
Then, in a simple way, we obtain an algorithm for computing the Fibonacci subsequence, in which the elements are multiples of some given number . Using the fact that
The previous algorithm turns into
If a , then finish, otherwise add to the result
, go to step 2.
Where can be set as constants.
Summary of the notes . As the user ignorance rightly noted, in the generalized case, it is also possible to construct an algorithm that uses only numbers from a partial result.
Let us prove this by the method of mathematical induction, for t = 1 and t = 2, the execution is obvious. Let it be executed up to some t, then
Something like a total
The problem is of course completely synthetic, the number of iterations is very small (for the answer contains only 6 numbers, i.e. 6 iterations were performed, and the original algorithm “head-on” would take 18), but in this way the username that discovered something new here could now show a little deeper mathematical knowledge in Fibonacci numbers at the interview.
Edit: Thanks to janatem and AllexIn users for simple proofs, I included them in "Teoretiziruem", and also hunroll for an algorithm using only already received even numbers in calculations and to the user ignorance for its generalization.