藍橋杯 斐波那契數列(python)
阿新 • • 發佈:2021-01-04
技術標籤: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
因為筆者自己學識有限,這裡就個人就很難深究下去了,如有大佬,希望可以指點一下。