Arytmetyka modularna i szybkie potęgowanie

Co to jest modulo

Czasem zdarza się, że niektóre wartości w naszym programie (np. wynik) są bardzo duże i nie mieszczą się w zakresach zmiennych udostępnianych przez języki programowania. Często jako wynik programu wystarczy wtedy podać jedynie jego resztę z dzielenia przez z góry określoną liczbę M.M. Zazwyczaj w celu ułatwienia obliczeń wybiera się MM będące liczbą pierwszą. Dzisiaj dowiesz się, jak wykonywać podstawowe operacje w arytmetyce modularnej oraz szybko potęgować liczby.

Poprzez zapis: ab (mod M)a \equiv b \ (mod \ M) (czytaj: aa przystaje do bb modulo MM) rozumiemy, że liczby aa i bb mają tą samą resztę z dzielenia przez M,M, czyli że aba-b jest podzielne przez M.M. Na przykład: 28 (mod 6),2\equiv 8 \ (mod \ 6), 17187 (mod 10).17 \equiv 187 \ (mod \ 10). Takie "równanie" nazywamy kongruencją.

Dodawanie, odejmowanie i mnożenie modulo

Trzy wyżej wymienione operacje wykonujemy dokładnie tak samo, jak w przypadku zwykłej arytmetyki na liczbach:

(a+b) (mod M)(a (mod M)+b (mod M)) (mod M)(a + b) \ (mod \ M) \equiv (a \ (mod \ M) + b \ (mod \ M)) \ (mod \ M)

(ab) (mod M)(a (mod M)b (mod M)) (mod M)(a \cdot b) \ (mod \ M) \equiv (a \ (mod \ M) \cdot b \ (mod \ M)) \ (mod \ M)

(ab) (mod M)(a (mod M)b (mod M)) (mod M)(a – b) \ (mod \ M) \equiv (a \ (mod \ M) - b \ (mod \ M)) \ (mod \ M)

Na przykład: 1717 (mod 10)(mod \ 10) ++ 2828 (mod 10)(mod \ 10) \equiv (7 (mod 10)(7 \ (mod \ 10) ++ 88 (mod 10))(mod \ 10)) (mod 10)(mod \ 10) == (7+8)(7 + 8) (mod 10)(mod \ 10) == 1515 (mod 10)(mod \ 10) \equiv 4545 (mod 10)(mod \ 10) == (17+28)(17+28) (mod 10).(mod \ 10).

Innymi słowy, jeśli chcemy poznać resztę z dzielenia przez MM sumy dwóch liczb, możemy najpierw zamiast każdej z nich wziąć jej resztę (mod MM), dodać do siebie te reszty i wziąć resztę z dzielenia przez MM tej sumy. Otrzymamy wtedy taki sam wynik, jak gdybyśmy najpierw dodali do siebie obie liczby, a następnie policzyli resztę tej sumy modulo M.M.

W przypadku odejmowania istnieje niebezpieczeństwo, że wynik będzie ujemny. Chcielibyśmy jednak modulować jedynie liczby dodatnie. Dlatego do wyniku odejmowania dodajemy MM - nie zmienia to nam reszty z dzielenia przez MM danej liczby, a zapewnia, że liczba, której resztę z dzielenia następnie obliczymy, będzie dodatnia.

W przypadku mnożenia istnieje natomiast niebezpieczeństwo, że jeśli liczba MM jest duża (np. M=109+7M=10^9+7) to mnożąc ze sobą dwie reszty, wykroczymy poza zakres intów. Aby uniknąć tego problemu, musimy po prostu pamiętać o zastosowaniu long longów.

Szybkie potęgowanie modulo

Zauważmy, że:

a do b

Pozwala to na zaimplementowanie prostego algorytmu do szybkiego potęgowania liczb:

long long modulo=1000000009; long long pow(long long base, long long power) { if (power == 0) return 1; else if (power % 2 == 0) { long long result = pow(base, power / 2); return (result * result) % modulo; } else return (base * pow(base, power - 1)) % modulo; }

Ile razy wykona się ta funkcja? Wykładnik bb nie będzie nieparzysty więcej razy niż parzysty. Oznacza to, że w przynajmniej połowie przypadków zmniejsza się on dwukrotnie – liczba wywołań funkcji będzie rzędu O(log(b)).O(log(b)). Jest to istotna różnica w porównaniu do wykonywania bb mnożeń „na pałę forem”.

Dzielenie modulo - odwrotność potęgowania

Niestety, dzielenia modulo nie możemy wykonywać tak "niefrasobliwie", jak reszty operacji, ponieważ bardzo często a÷ba \div b daje inną resztę z dzielenia przez M,M, niż a(modM)÷b(modM)a \pmod{M} \div b \pmod{M}

Np. z jednej strony (12÷2)(12 \div 2) pmod10pmod{10} == 66 (mod10),\pmod{10}, a z drugiej: (12(mod10))(12 \pmod{10}) ÷\div (2(mod10))(2 \pmod{10}) == (2(mod10))(2 \pmod{10}) ÷\div (2(mod10))(2 \pmod{10}) == 1(mod10).1 \pmod{10}. Coś tutaj się nie zgadza...

Może też się zdarzyć, że aa nie jest podzielne przez b,b, a mimo tego dzielenie modulo da się wykonać, np. 33 nie dzieli 77 , ale 7(mod10)÷3(mod10)9(mod10),7 \pmod{10} \div 3 \pmod{10} \equiv 9 \pmod{10}, ponieważ 39=277(mod10)3 \cdot 9 = 27 \equiv 7 \pmod{10}}

Aby dzielenie modulo wykonywać poprawnie, musimy podejść do niego od całkiem nowej strony. Otóż przedstawmy sobie dzielenie jako mnożenie przez odwrotność:

(a÷b)(modM)=ab1(modM)=a(modM)b1(modM)(a \div b) \pmod M = a \cdot b^{-1} \pmod M = a \pmod M \cdot b^{-1} \pmod M

Gdzie b1b^{-1} to taka liczba, że bb11 (modM).b \cdot b^{-1} \equiv 1 \ \pmod M. Umiemy już mnożyć, więc musimy nauczyć się znajdywać odwrotność modulo. W tym celu skorzystamy z Małego Twierdzenia Fermata, które mówi, że: Dla MM będącego liczbą pierwszą i bb niepodzielnego przez MM zachodzi: bM11(modM)b^{M – 1} \equiv 1\pmod{M}

Dowód: Rozważmy wszystkie możliwe kolorowania "koła fortuny", podzielonego na MM kawałków, na bb kolorów. W sumie jest ich bMb^M - każdy kawałek możemy pokolorować na jeden z bb kolorów. Zauważmy, że po obróceniu dowolnego kolorowania, takiego, że nie całe koło jest pomalowane na ten sam kolor, otrzymamy jakieś inne kolorowanie. W sumie kolorowań, w których całe koło jest jednokolorowe, mamy bb - tyle, ile kolorów. Czyli pozostałe bMbb^M-b kolorowań możemy poustawiać po MM kolorowań tak, że kolorowania w jednej grupie da się uzyskać z siebie poprzez obracanie koła. Każde kolorowanie trafi do dokładnie jednej grupy wraz z M1M-1 kolorowaniami, które możemy z niego uzyskać, obracając koło. Czyli MM dzieli bMb=b(bM11).b^M-b = b(b^{M-1}-1). Ponieważ MM nie dzieli bb oraz jest pierwsze, MM musi dzielić bM11,b^{M-1}-1, czyli bM11(modM).b^{M-1} \equiv 1 \pmod{M}. To kończy dowód.

Wykorzystując Małe Twierdzenie Fermata, dostajemy:

bb11bM1(modM)b \cdot b^{-1} \equiv 1 \equiv b ^ {M – 1} \pmod{M}

bb1=bM2b(modM)b \cdot b^{-1} = b ^ {M – 2} \cdot b \pmod{M}

b1bb1=bM2bb1(modM)b^{-1} \cdot b \cdot b^{-1} = b ^ {M – 2} \cdot b \cdot b^{-1} \pmod{M} (pomnożyliśmy stronami poprzednią kongruencję przez b1b^{-1})

b1bM2(modM)b ^ {-1} \equiv b ^ {M – 2}\pmod{M} (ponieważ bb11(modM)b \cdot b^{-1} \equiv 1 \pmod{M} "znikają" z obu stron)

bM2b ^ {M – 2} umiemy policzyć w O(log M),O(log \ M), używając szybkiego potęgowania, czyli umiemy już też dzielić (mod M).(mod \ M).

Przypomnijmy na koniec, że aby zastosować Małe Twierdzenie Fermata, MM musi być liczbą pierwszą. Jak radzić sobie z dzieleniem, gdy jest ono złożone dowiesz się w artykule Teoria liczb I.

Zadania