StartAlgorytmyAlgorytmy arytmetyczneSzybka rekurencja modularna
Baza Wiedzy
Wersja offline serwisu przeznaczona na urządzenia z systemem Android.

Darowizny
darowiznaWspomóż rozwój serwisu


Nagłówki RSS
Kanał artykuły
Kanał implementacje
Kanał komentarze
Kanał forum


Bookmarki









Sonda
Implementacji w jakim języku programowania poszukujesz?
 
Szybka rekurencja modularna
Ocena użytkowników:+++++ / 1
SłabyŚwietny 
Wpisany przez Rafał Świetlicki
czwartek, 11 stycznia 2007 09:58
Niech x, y będą dowolnymi liczbami całkowitymi, a, b dowolnymi liczbami całkowitymi różnymi od zera, m – liczbą całkowitą większą niż 1.
Załóżmy, że dany jest ciąg liczb całkowitych zdefiniowany rekurencyjnie:
G0 = x, G1 = y
Gn = aGn-2 + bGn-1
, gdzie n ≥ 2.

Interesuje nas obliczenie Gn mod m dla ustalonej liczby n.
Przyjmując np. x = y = a = b = 1, m = 10 jako Gn mod m dostaniemy ostatnią cyfrę n – tej liczby Fibonacciego.

Algorytm polegający na wyznaczaniu kolejnych wyrazów Gk mod m dla k = 2, 3, ..., n ma złożoność O(n) i dla bardzo dużych wartości n jest niepraktyczny. Można to zrobić o wiele szybciej w czasie O(log n) wykorzystując działania na macierzach oraz szybkie potęgowanie modularne.
Korzystając z indukcji matematycznej łatwo udowodnić następującą tożsamość:
Szybka rekurencja modularna

Ze wzoru tego wynika, że należy najpierw obliczyć:
Image

Potęgowanie macierzy odbywa się podobnie jak potęgowanie liczby opisane w artykule szybkie potęgowanie modularne. Jeżeli liczby a i/lub b są niemniejsze niż m to najpierw w macierzy, którą będziemy potęgować zastępujemy te liczby ich resztami z dzielenia przez m. Wprowadzamy macierz pomocniczą X o dwóch wierszach i dwóch kolumnach, która na początku będzie równa macierzy jednostkowej. Dalej, wyznaczamy kolejne cyfry rozwinięcia dwójkowego liczby n – 2. W każdym kroku (których ilość jest równa liczbie cyfr dwójkowych liczby n – 2), przemnażamy macierz X przez samą siebie a wynik mnożenia ponownie przypisujemy pod macierz X. Dodatkowo, jeżeli kolejna cyfra dwójkowa liczby n – 2 (licząc od cyfry najwyższego rzędu) jest równa 1, macierz:
Image

przemnażamy przez macierz X
Na koniec każdy z czterech elementów macierzy X zastępujemy jego resztą z dzielenia przez m.

Ponieważ cyfry dwójkowe liczby n – 2 pobierane są od cyfry najwyższego rzędu, zatem najprościej potęgowanie macierzy modulo m zrealizować rekursywnie tak, jak zostało to wykonane w dołączonej implementacji algorytmu.

Ostatecznie przyjmując:
Image

Otrzymujemy:
Image


Dowod poprawności algorytmu (Adam Mika):
Dowód poprawności szybkiej rekurencji modularnej



Autor Język programowania Komentarz Otwórz Pobierz Ocena
Tomasz Lubiński Ada
Implementacja w Ada
Implementacja w Ada
++++- / 1
Tomasz Lubiński C# MS Visual Studio .net
Implementacja w C#
Implementacja w C#
++++- / 1
Rafał Świetlicki C/C++
Implementacja w C/C++
Implementacja w C/C++
++++- / 1
Dawid Drozd C/C++
Implementacja w C/C++
Implementacja w C/C++
++++- / 1
Tomasz Lubiński Delphi/Pascal
Implementacja w Delphi/Pascal
Implementacja w Delphi/Pascal
++++- / 1
Rafał Świetlicki Java
Implementacja w Java
Implementacja w Java
+++-- / 2
 
Dodaj własną implementację tego algorytmu
  • Zaloguj się na stronie
Plik:
Język programowania:
Komentarz:
  By móc dodać implementacje zaloguj się na stronie



Poprawiony: wtorek, 19 lipca 2011 12:06

Dodaj komentarz

Kod antysapmowy
Odśwież