1. 程式人生 > 其它 >藍橋杯 斐波那契數列(python)

藍橋杯 斐波那契數列(python)

技術標籤:python

藍橋杯 斐波那契數列(python)

問題描述
Fibonacci數列的遞推公式為:Fn=Fn-1+Fn-2,其中F1=F2=1。
當n比較大時,Fn也非常大,現在我們想知道,Fn除以10007的餘數是多少。

最初看到這個問題,筆者最開始考慮到的是利用遞迴進行解決,於是有了如下程式碼

# -*- coding: utf-8 -*-
import sys
def fibonacci(num):
    if num == 0:
        return 0
    if num == 1:
        return 1
    if num == 2:
        return
1 return (fibonacci(num - 1)+ fibonacci(num - 2))%10007 def main(): #當遞迴深度超出999時會進行報錯,所以要加上這段程式碼 sys.setrecursionlimit(9000000) print(fibonacci(int(input()))) if __name__ == '__main__': main()
執行結果
10
55

就目前來看這段程式碼是沒有問題的,但是一旦執行比較大的數值執行速度就會很慢引發超時,於是乎這裡給出另一種方法

def main():
    num = eval(input
()) lst = [0, 1, 1] if num == 0: print(0) return for i in range(2,num): lst.append((lst[i - 1] + lst[i])%10007) print(lst.pop()) if __name__ == '__main__': main()
運算結果:
99999
6415

相比於前者,這段程式碼運算大數值的執行速度要快很多 (根本不是一個等級)。
那麼問題就來了,為什麼會產生這種情況呢?
這裡一下引用python遞迴執行過慢的原因及解決方案


python在執行遞迴的時候,每次用到之前的數值,都會重新計算一次……所以才會這麼慢。
於是乎這位答主提出將結果放入快取提高執行效率,於是乎根據修改可以得到如下程式碼。

# -*- coding: utf-8 -*-
import sys
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(num):
    if num == 0:
        return 0
    if num == 1:
        return 1
    if num == 2:
        return 1
    return (fibonacci(num - 1)+ fibonacci(num - 2))%10007
def main():
    #當遞迴深度超出999時會進行報錯,所以要加上這段程式碼
    sys.setrecursionlimit(9000000)
    print(fibonacci(int(input())))
if __name__ == '__main__':
    main()

執行結果:
1500
1945

速度確實有很大的提升但,一旦執行大於1553的數值就無法繼續得出結果了。這裡貼出
Python 快取機制與 functools.lru_cache
因為筆者自己學識有限,這裡就個人就很難深究下去了,如有大佬,希望可以指點一下。