【欧拉计划2】Even Fibonacci numbers
欢迎访问我的新博客:http://www.milkcu.com/blog/
原文地址:http://www.milkcu.com/blog/archives/1367386440.html
该题来自Project Euler的第二题,求数值小于4百万的偶数项的和。今天继续我的欧拉计划。
问题描述
英语原文
Even Fibonacci numbers
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
中文描述
在Fibonacci数列中,每一项由它的前两项之和生成。从1,2开始,前十项为:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
考虑Fibonacci数列中数值不超过4百万的项,求出值为偶数的项的和。
解决方案
我的解法
这是中规中矩的方法,用了点循环队列的思想,虽然可以用几个变量替代。在写代码的过程中,还犯了一个傻傻的错误,感谢论坛朋友的帮助。
# include <stdio.h> # define BOUND 4000000 int main(void) { int fib[3]; int i; long long int sum; fib[0] = 1; fib[1] = 2; sum = 2; for(i = 2; fib[(i - 1) % 3] < BOUND; i++) { fib[i % 3] = fib[(i - 1) % 3] + fib[(i - 2) % 3]; //队列的思想 if(fib[i % 3] % 2 == 0) { sum += fib[i % 3]; } } printf("%d\n", fib[(i - 2) % 3]); printf("%d", sum); }
下面是题目解析提供的几种解法。
直接求解
这个方法和我的方法原理是一样的。
# include <stdio.h> int main(void) { int limit; int a, b, h; int sum; limit = 4000000; a = b = 1; sum = 0; while(b < limit) { if(b % 2 == 0) { sum += b; } h = a + b; a = b; b = h; } printf("%d", sum); }
另一种方法
仔细观察数列,可以发现,每三个Fibnacci数有一个偶数。利用这个规律,可以省去条件判断。
# include <stdio.h> int main(void) { int limit; int a, b, c; int sum; limit = 4e6; a = 1; b = 1; c = 2; sum = 0; while(c < limit) { sum += c; a = b + c; b = a + c; c = a + b; } printf("%d", sum); }
高效方案
如果把偶数项拿出来:
2,8,34,144……
它们遵循的这样的规律:
E(n)=4*E(n-1)+E(n-2)
# include <stdio.h> int main(void) { int limit; int a, b; int sum; limit = 4e6; sum = 2; a = 2; b = 8; while(b < limit) { sum += b; b = 4 * b + a; a = (b - a) / 4; //在没有使用第三变量的情况下,变量后移 } printf("%d", sum); }
要证明上关系式成立,只需证:
F(n)=4*F(n-3)+F(n-6)
证明过程如下:
F(n) = F(n-1) + F(n-2)
= F(n-2)+F(n-3)+F(n-2)=2 F(n-2) + F(n-3)
= 2(F(n-3)+F(n-4))+F(n-3))=3 F(n-3) + 2 F(n-4)
= 3 F(n-3) + F(n-4) + F(n-5) + F(n-6)
= 4 F(n-3) + F(n-6)
最后答案
4613732