Fibonacci z zapamiętywaniem
Treść zadania
Oblicz $F_N$ — $N$-ty wyraz ciągu Fibonacciego ($F_0 = 0$, $F_1 = 1$, $F_n = F_{n-1} + F_{n-2}$), ale tym razem dla $N$ aż do $90$. Prosta rekurencja z ZAD-05 nie zdąży: dla $N = 90$ wykonałaby około $10^{19}$ wywołań.
Napisz rekurencyjną funkcję fibonacci(n, pamiec), która zapamiętuje obliczone wyniki (memoizacja): pamiec to lista, w której pamiec[k] jest równe None, dopóki $F_k$ nie zostało obliczone, a potem przechowuje jego wartość. Każdy wyraz ciągu jest wtedy liczony tylko raz.
Dane wejściowe
Jedna liczba naturalna N.
Dane wyjściowe
Jedna liczba naturalna — wartość $F_N$.
Ograniczenia
0 ≤ N ≤ 90
Uwagi
- Funkcja: jeśli $n < 2$, zwróć $n$. Jeśli
pamiec[n]nie jestNone, zwróć zapamiętaną wartość. W przeciwnym razie obliczfibonacci(n - 1, pamiec) + fibonacci(n - 2, pamiec), zapisz wynik wpamiec[n]i zwróć go. - Porównanie liczby wywołań: wersja bez pamięci liczy te same wyrazy wielokrotnie — dla $N$ wykonuje $2F_{N+1} - 1$ wywołań, czyli liczba wywołań rośnie wykładniczo (dla $N = 40$ to już ponad 300 milionów). Wersja z pamięcią oblicza każdy wyraz raz, więc wykonuje mniej niż $2N$ wywołań — liczba wywołań rośnie liniowo.
- Dla chętnych: Python ma gotowy mechanizm zapamiętywania. Dekorator
@lru_cachez modułufunctools, dopisany nad definicją funkcji, sam zapamiętuje wyniki dla każdego argumentu:
```python
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)`
Przykład
40
102334155
Potrzebujesz teorii?
Zasady obowiązujące w rozdziale 15
Poniższe zadania uczą rekurencji: funkcja rozwiązuje problem, wywołując samą siebie dla mniejszych danych, aż dojdzie do przypadku bazowego, w którym odpowiedź jest znana od razu (np. $0! = 1$).
Konwencje wspólne:
- Każde zadanie to osobny program: czyta standardowe wejście i wypisuje wynik na standardowe wyjście. Program wczytuje dane, wywołuje funkcję opisaną w treści i wypisuje wynik (gotowy szkielet znajdziesz w sekcji „Kod startowy”).
- Rozwiązanie musi być rekurencyjne. Właściwe obliczenia wykonuje funkcja, która wywołuje samą siebie. Nie używaj w niej pętli
foraniwhile, ani gotowych narzędzi, które wykonają całą pracę za Ciebie (np.sum(),pow(), operatora**,math.factorial(),list.index()). Sprawdzarka porównuje tylko wynik, ale celem zadań jest ćwiczenie rekurencji. - Każda funkcja rekurencyjna potrzebuje przypadku bazowego (kiedy przestajemy się wywoływać) i kroku rekurencyjnego (wywołania dla mniejszego problemu). Bez przypadku bazowego program przerwie działanie błędem
RecursionError. - Python ogranicza głębokość rekurencji (domyślnie do około 1000 zagnieżdżonych wywołań), dlatego dane w zadaniach są małe.
- Liczby naturalne liczymy od zera: $0, 1, 2, \dots$
- Program nie wypisuje komunikatów typu „Podaj liczbę:”.
Zadanie pochodzi z otwartego zbioru Nauka-Programowania (z rozwiązaniami wzorcowymi). Zgłoś błąd w treści lub testach.
Przywrócono Twój zapisany kod.
Python uruchomi się w przeglądarce przy pierwszym teście.
Kod zapisuje się automatycznie w tej przeglądarce. Tab wstawia wcięcie; aby opuścić edytor klawiaturą, naciśnij Esc, a potem Tab.
Testy
Program dostaje „Wejście” przez input() i musi wypisać „Oczekiwane wyjście”. Liczby porównywane są z tolerancją 0,01, a tekst podany w input("…") nie jest sprawdzany.
Test 1
Nie uruchomiono0
0
Test 2
Nie uruchomiono1
1
Test 3
Nie uruchomiono2
1
Test 4
Nie uruchomiono50
12586269025
Test 5
Nie uruchomiono70
190392490709135
Test 6
Nie uruchomiono90
2880067194370816120