Multiplikativni inverz
Modularni multiplikativni inverz cijelog broja modulo je cijeli broj koji zadovoljava kongruenciju .
Na primjer, , jer je . Primijetimo da je inverz različit za različite , i da ne postoji uvijek (pokušajte ga pronaći za , ), a može se pokazati da postoji ako i samo ako su i relativno prosti. Multiplikativni inverzi korisni su u modularnom dijeljenju - dijeljenje brojem modulo odgovarat će množenju s , kao i u običnoj aritmetici.
Jedan način za njihovo računanje koristi Eulerov teorem.
Eulerov teorem
Eulerova funkcija , engl. Euler's Totient Function, daje broj prirodnih brojeva izmedu i koji su relativno prosti s . Npr., , jer su 1, 3, 7 i 9 relativno prosti s 10. Primijetimo da će za proste vrijediti .
Neka su prosti brojevi iz rastava na proste faktore, i neka ih ima . Tada se vrijednost Eulerove funkcije može dobiti formulom . Sljedeći algoritam implementira ovu formulu u složenosti :
int phi(int n) {
int rez = n;
for (int i = 2; i * i <= n; ++i) {
/* Provjeravamo je li n djeljiv s i. Ako jest, onda je i prost broj iz njegovog rastava. */
/* Kako znamo da je i prost? Počinjemo s prostim brojem 2. Za trenutni i, u while petlji ispod */
/* ćemo 'ukloniti' sva javljanja faktora i iz n, pa svaki sljedeći i koji dijeli (promijenjeni) n */
/* neće biti višekratnik trenutnog i. Tako svaki trenutni i nije višekratnik brojeva 2..i-1, pa je prost. */
if (n % i == 0) {
while (n % i == 0)
n /= i;
/* rez = rez * (1 - 1/i) = rez - rez/i */
rez -= rez / i;
}
}
/* Ako je n>1, onda postoji prost faktor od n veći od sqrt(n). */
/* Takav može biti samo jedan. Dokaz: pretp. da postoje dva prosta faktora a,b>sqrt(n). */
/* Tada i a*b dijeli n, pa je a*b<=n. Ali, sqrt(n)*sqrt(n)<a*b<=n pa slijedi n<n (kontradikcija). */
/* Taj preostali prosti faktor upravo je trenutni n, pa promijenimo rez kao gore. */
if (n > 1)
rez -= rez / n;
return rez;
}
Kako je Eulerova funkcija vezana za računanje multiplikativnih inverza, postat će jasnije uvođenjem Eulerovog teorema. On kaže da, za relativno proste prirodne brojeve i , vrijedi .
Množenjem obiju strana gornje kongruencije s , dobivamo . Za prost , izraz se pojednostavljuje na .
Računanje multiplikativnog inverza
Korištenjem Eulerovog teorema, algoritma za brzo potenciranje objašnjenog u poglavlju Važne formule, i gornje funkcije phi, možemo lako izračunati multiplikativni inverz broja modulo :
int multiplikativni_inverz(int a, int m){
return brzo_potenciranje(a, phi(m)-1, m);
}
Ako je vrijednost phi(m) unaprijed poznata, npr. kada je prost i vrijednost funkcije , složenost ove metode određena je funkcijom brzo_potenciranje i iznosi . U nekim slučajevima, poput računa modulo , ovaj pristup može biti dovoljno dobar.
Ako se radi o računu modulo gdje je složen broj, a vrijednost Eulerove funkcije phi(m) nije unaprijed poznata, potrebno je računati i nju što može biti vremenski zahtjevno. Bolji pristup koristio bi prošireni Euklidov algoritam, ili računao inverze za niz brojeva odjednom kao ispod. Razumijevanje tih algoritama traži dodatno poznavanje teorije brojeva, ali same formule i implementacija nisu teški. Više o njima možete saznati ovdje.
/* računanje inverza svih brojeva u intervalu [1, m-1] */
inv[1] = 1;
for(int i = 2; i < m; ++i)
inv[i] = m - (m/i) * inv[m%i] % m;