Zapis wieżowy
Tym razem omówimy rozwiązanie zadania Zapis wieżowy z Akademickich Mistrzostw Polski w Programowaniu Zespołowym z 2006 roku.
Dla ciągu liczb naturalnych oraz liczby naturalnej należy wyznaczyć resztę z dzielenia przez wieży potęgowej, w której liczby z ciągu są kolejnymi wykładnikami. Innymi słowy, mamy znaleźć wartość wyrażenia
Przykładowo, gdyż Oczywiście, bezpośrednie obliczanie potęg nie wchodzi w grę, gdyż ich wartości rosną coraz szybciej z każdym dodatkowym wykładnikiem i już liczba ma 3951 cyfr. Dla uproszczenia zapisu wieżę potęgową będziemy oznaczali przez
W rozwiązaniu zadania pomoże nam twierdzenie Eulera, które mówi, że dla względnie pierwszych liczb naturalnych i spełniona jest kongruencja
(*) |
gdzie oznacza liczbę liczb względnie pierwszych z i nie większych niż ta liczba. Jeśli zatem liczby i byłyby względnie pierwsze, to moglibyśmy:
- wyznaczyć
- rekurencyjnie obliczyć rozwiązanie mniejszego problemu dla ciągu i modułu czyli
- korzystając z twierdzenia Eulera, wyznaczyć rozwiązanie
Przypomnijmy, że jeśli znamy rozkład modułu na czynniki pierwsze to do obliczenia możemy wykorzystać następujący wzór:
(**) |
Rozkład ten możemy znaleźć w czasie przeglądając wszystkie potencjalne dzielniki liczby nie większe niż Zatem w takim też czasie wykonamy krok 1 algorytmu. Z kolei potęgowanie z kroku 3 możemy wykonać w czasie stosując metodę wielokrotnego podnoszenia do kwadratu. W sumie wykonamy wywołań rekurencyjnych, w -tym wywołaniu obliczając gdzie oraz dla co da algorytm o złożoności czasowej
Zauważmy jednak, że ze wzoru widać, iż dla nieparzystego jest liczbą parzystą, natomiast dla parzystego mamy Wynika z tego, że ciąg kolejnych modułów ma co najwyżej wyrazów, zatem wystarczy, że wykonamy wywołań rekurencyjnych. A po drugie, pracę wykonaną we wszystkich wywołaniach kroku 1 można sumarycznie oszacować przez Zatem lepszym oszacowaniem czasu działania naszego algorytmu jest czyli po prostu
Niestety, abyśmy mieli pewność, że algorytm działa poprawnie, nie tylko liczby i muszą być względnie pierwsze, ale również liczby i dla wszystkich Na szczęście twierdzenie Eulera można uogólnić, aby działało również bez założenia o względnej pierwszości. Nowa wersja brzmi następująco: dla dowolnych liczb naturalnych i spełniona jest kongruencja
(***) |
gdzie jest pewną liczbą zależną od jednak nie większą niż
Zanim udowodnimy to twierdzenie, zobaczmy, jak dzięki niemu naprawić nasz algorytm. Zmodyfikujemy go tak, aby nie tylko obliczał wartości ale również dodatkowy bit równy 1 wtedy, gdy Znowu pokażemy, jak wykonać krok (2) algorytmu: załóżmy zatem, że i obliczyliśmy już oraz
Wyznaczmy Jeśli to więc i wystarczy przyjąć Z kolei jeśli to czyli
Zatem w obu przypadkach mamy Z kolei wyznaczyć można następująco: jeśli to a w przeciwnym przypadku możemy wykonać potęgowanie w każdej iteracji domnażając jedno i sprawdzając, czy wynik osiągnął już (wykonamy co najwyżej takich iteracji). Ostatecznie złożoność czasowa całego algorytmu nie zmienia się.
Pozostaje udowodnić dane wzorem uogólnienie twierdzenia Eulera. Zdefiniujmy ciąg następująco:
oraz niech będzie najmniejszą liczbą, taką że Oznaczmy też
Liczba jest liczbą powstałą po usunięciu z wszystkich czynników pierwszych występujących w zatem liczby i są względnie pierwsze. Z twierdzenia Eulera wynika zatem, że
Ponadto każda z liczb jest całkowita, więc liczba również. Mnożąc powyższe równanie przez dostajemy
Korzystając z faktu, że kongruencja jest spełniona wtedy i tylko wtedy, gdy spełniona jest możemy przemnożyć przez obie strony i moduł powyższego równania:
Liczby i są względnie pierwsze, zatem z multiplikatywności funkcji dostajemy Ponadto wykładniki w rozkładach na czynniki pierwsze liczb zmniejszają się, więc Zatem ostatecznie dostajemy tezę twierdzenia: