您的位置:首页 > 编程语言 > Python开发

Even Fibonacci numbers

2014-09-11 14:47 369 查看
'''
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.
不超过4000000的Fibonacci序列中所有偶数的和
'''

分析:

方案一:求出所有小于4000000的Fibonacci序列,然后对所有偶数进行求和

方案二:分析序列规律,两个偶数中间有两个奇数,所以可以在求值的时候,进行过滤求和

方案三:偶数等于前面奇数之和,那么把所有数累加后,除2得到的结果就是所有偶数的和,前提是4000000前的一项数是偶数,若为奇数,那么须额外处理

那么问题还是在求Fibonacci序列

给定第一项1,每二项1,以后每项的值为前两项之和

注:方案与解法不一一对应

解法一:# 取两个变量,需要在计算时进行累加
def even_Fibonacci_numbers(limit=4000000):
fir = 1
sec = 1
tmp = fir + sec
res = fir + sec
while tmp < limit:
if tmp % 2 == 0:
res += tmp
fir, sec = sec, tmp
tmp = fir + sec
return res

此方法,需要关注序列中做去处的两项的值的交换,但空间方面就节省了

解法二:#采用数组保存序列值

def even_Fibonacci_numbers(limit=4000000):
fi = [1,1]
tmp = sum(fi)
while tmp < limit:
fi.append(tmp)
tmp = fi[-2] + fi[-1]
return sum([i for i in fi if i % 2 == 0])

此方法,只需要关注累加的那一项是否超过界限,但用列表来保存增加的项。

若需要增加的项很多,可以先开辟一段空间,解法上需要做一下修改。

解法三:#取两个变量,累计所有和,然后分析得到的序列的奇偶性,并处理
def even_Fibonacci_numbers(limit=4000000):
while tmp < limit:
fir, sec = sec, tmp
res += sec
tmp = fir + sec

if res % 2 == 1:
res = (res - sec) / 2
else:
if sec % 2 == 0:
res /= 2
else:
res = (res - sec - fir) / 2
return res

此方法,最后分析处理,fir,sec只有三种可能的情况,奇奇,奇偶,偶奇

fir,sec:偶奇,得到的res为奇数,所以需要减去sec,得到的结果再除以2,得最终结果

fir,sec:奇奇,奇偶,得到的res均为偶数,故需要进一步判断,

       若sec为偶数,那么将结果直接除以2即可

       若sec为奇数,那么得到的结果需要减去fir和sec,然后将结果除以2,得最终结果

这里再引用一下别人的做法,依然是分析序列:这个解法算是方案二的求解。

x, y, x + y, x + 2y, 2x + 3y, 3x + 5y

这里,我们需要取的值是x+y,3x+5y

python表示:

def calcE(limit=4000000):
x = y = 1
res = 0
while (res < limit):
res += (x + y)
x, y = x + 2 * y, 2 * x + 3 * y
return res

这个解法是这些解法中运行速度最快的,也许解决当前这个问题足够了,但是并不正确

当改变限界为6*10**6时,会得到错误结果。

正确的表示:

def calcE(limit=4000000):
x = y = 1
res = 0
while res < limit and x < limit and y < limit:
res += (x + y)
x, y = x + 2 * y, 2 * x + 3 * y

return res

对于参与累计的值,必须满足之前所有的值都小于限界,一但某个值超过了限界,那么就必须结束累计。

这样得到的结果才会是正确的。

 

提一点,有人用数学方法,直接推导最后的结果,算法复杂度O(1)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Euler Project Python