马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 jerryxjr1220 于 2017-8-18 16:02 编辑
今天我们继续来看“欧拉计划”的第2题,求斐波那契数列中不超过400万的偶数的和。
这题初看起来,用穷举法应该是很容易求解的,斐波那契数列的通项公式:f(n) = f(n-1)+f(n-2), f(0)=1, f(1)=1
所以可以很简单的用递归写成:def fib(n):
return fib(n-1)+fib(n-2) if n>1 else 1
不过其实递归的效率是很低的,因为每次调用fib函数,程序都要先去计算一下fib(n-1)和fib(n-2),这样就会造成非常多的重复计算,导致效率变低。
我们可以用循环来改善递归中效率过低的问题。def fib(n):
a, b = 1, 1
for i in range(n):
a, b = a+b, a
return b
其实,如果我们搜一下,可以发现斐波那契数列是有通项计算公式的:F(n)=(1/5**0.5)*(((1+5**0.5)/2)**n - ((1-5**0.5)/2)**n)
这样,其实可以直接列式计算,比循环的效率更高,这里就不例举了。
有了斐波那契的公式,计算就自然很方便了。对了,题目还要求我们求所有偶数的和,那是不是我们需要对每一项都要进行奇偶判断?
其实是不必要的,我来看看斐波那契数列的规律,1,2,3,5,8,13,21,34...
有没有发现它是按照“奇,偶,奇,奇,偶,奇,奇,偶,奇,奇,偶..."这样的方式排列的。也就是说所有的偶数项都是出现在第2、5、8、11...这样的公差为3的项数上,我们只需要按照这个规律提取并计算就可以了。
def euler2(n):
a, b = 1, 1
res = []
while b<n:
res.append(b)
a, b = a+b, a
return sum(res[2::3])
同样一道题目有不同的解题方法,这就是算法的奥秘,你感觉到了吗?
最后,耍个宝,一行python代码输出:print(sum([int((lambda n: (1/5**0.5)*(((1+5**0.5)/2)**n - ((1-5**0.5)/2)**n))(i)) for i in range(3,1000,3) if (lambda n: (1/5**0.5)*(((1+5**0.5)/2)**n - ((1-5**0.5)/2)**n))(i)<4000000]))
|