Modułowe odwrotność multiplikatywna

22

Twoim zadaniem jest podanie dwóch liczb całkowitych ai bobliczenie modularnej multiplikatywnej odwrotności modułu b, jeśli taki istnieje.

Modularna odwrotność amodulo bjest liczbą ctaką, że ac ≡ 1 (mod b). Ten numer jest unikalnym modułem bdla dowolnej pary ai b. Istnieje tylko wtedy, gdy jest największym wspólnym dzielnikiem ai bjest 1.

Strona Wikipedia dla modułowego Liczba odwrotna może być konsultowany, jeśli potrzebujesz więcej informacji na dany temat.

Wejście i wyjście

Dane wejściowe są podawane jako dwie liczby całkowite lub lista dwóch liczb całkowitych. Twój program powinien wypisać albo pojedynczą liczbę, modularną odwrotność multiplikatywną, która znajduje się w przedziale 0 < c < b, lub wartość wskazującą, że nie ma odwrotności. Wartość może być dowolna, z wyjątkiem liczby z zakresu (0,b), i może być również wyjątkiem. Wartość powinna jednak być taka sama dla przypadków, w których nie ma odwrotności.

0 < a < b można założyć

Zasady

  • Program powinien zakończyć się w pewnym momencie i powinien rozwiązać każdy przypadek testowy w mniej niż 60 sekund
  • Obowiązują standardowe luki

Przypadki testowe

Poniższe przypadki testowe są podane w formacie, a, b -> output

1, 2 -> 1
3, 6 -> Does not exist
7, 87 -> 25
25, 87 -> 7
2, 91 -> 46
13, 91 -> Does not exist
19, 1212393831 -> 701912218
31, 73714876143 -> 45180085378
3, 73714876143 -> Does not exist

Punktacja

To jest kod golfowy, więc wygrywa najkrótszy kod dla każdego języka.

To i to są podobne pytania, ale oba dotyczą konkretnych sytuacji.

Halvard Hummel
źródło
6
Z Małego Twierdzenia Fermata wynika, że ​​multiplikatywna odwrotność a, jeśli istnieje, może być skutecznie obliczona jako ^ (phi (b) -1) mod b, gdzie phi jest funkcją sumaryczną Eulera: phi (p0 ^ k0 * p1 ^ k1 * ...) = (p0-1) * p0 ^ (k0-1) * (p1-1) * p1 ^ (k1-1) * ... Nie mówię, że prowadzi to do skrócenia kodu :)
ngn
1
@Jenny_mathy Przyjmowanie dodatkowych danych jest ogólnie zabronione.
Pan Xcoder
3
Liczę sześć odpowiedzi, które wydają się brutalnym wymuszaniem i mało prawdopodobne jest uruchomienie wszystkich przypadków testowych w 60 sekund (niektóre z nich dają błąd stosu lub pamięci jako pierwszy).
Ørjan Johansen
1
@ngn: Połączyłeś Małe Twierdzenie Fermata (FLT) z ulepszeniem Eulera. Fermat nie wiedział o funkcji phi Eulera. Ponadto ulepszenia FLT i Eulera mają zastosowanie tylko wtedy, gdy gcd (a, b) = 1. Wreszcie, w postaci, w której je napisałeś, „a ^ (\ phi (b) -1) mod b” odpowiada 1, a nie ^ (- 1). Aby uzyskać ^ (- 1), użyj ^ (\ phi (b) -2) mod b.
Eric Towers,
1
@EricTowers Euler jest konsekwencją. Odnośnie „gcd (a, b) = 1” - powiedziałem „jeśli istnieje [odwrotność]”. Czy jesteś pewien phi (b) -2?
ngn

Odpowiedzi:

11

Mathematica, 14 bajtów

Obowiązkowy Mathematica wbudowane :

ModularInverse

Jest to funkcja, która pobiera dwa argumenty ( ai b) i zwraca odwrotność mod b, jeśli istnieje. Jeśli nie, zwraca błąd ModularInverse: a is not invertible modulo b..

Tutleman
źródło
7

JavaScript (ES6), 79 73 62 61 bajtów

Zwraca, falsejeśli odwrotność nie istnieje.

Wykorzystuje rozszerzony algorytm euklidesowy i prawie natychmiast rozwiązuje wszystkie przypadki testowe.

f=(a,b,c=!(n=b),d=1)=>a?f(b%a,a,d,c-(b-b%a)/a*d):b<2&&(c+n)%n

Przypadki testowe

Arnauld
źródło
Dlaczego nie można wpisać nazwy funkcji f, jak w f (c, a, b = 0, d = 1, n = a) => c? F (a% c, c, d, b- ( aa% c) / c * d, n): a <2 && (b + n)% n?
RosLuP
@RosLup f(x,y)jest zawsze analizowany jako wywołanie funkcji, z wyjątkiem sytuacji, gdy jest to wyraźnie poprzedzone functionsłowem kluczowym. Z drugiej strony anonimowa funkcja strzałki jest zadeklarowana jako (x,y)=>somethingi f=(x,y)=>somethingprzypisuje funkcję do fzmiennej.
Arnauld
4

Galaretka , 2 bajty

æi

Wypróbuj online!

Używa wbudowanego do modułowego odwrotnego i zwraca 0 dla braku modułowego odwrotnego.

Galaretka , 7 bajtów

R×%⁸’¬T

Wypróbuj online!

Wyprowadza pusty zestaw (reprezentowany jako pusty ciąg) przy braku odwrotności modułowej. Skończy się pamięć w TIO dla największych przypadków testowych, ale powinna działać z wystarczającą ilością pamięci.

Jak to działa

R×%⁸’¬T  
R        Generate range of b
 ×       Multiply each by a
  %⁸     Mod each by b
    ’    Decrement (Map 1 to 0 and all else to truthy)
     ¬   Logical NOT
      T  Get the index of the truthy element.

Jeśli chcesz pracować dla większych przypadków testowych, wypróbuj tę (względnie nie golfową) wersję, która wymaga dużo czasu niż pamięci:

Galaretka, 9 bajtów

×⁴%³’¬ø1#

Wypróbuj online!

Jak to działa

×⁴%³’¬ø1#
        #   Get the first
      ø1      one integer
            which meets:
×⁴            When multiplied by a
  %³          And modulo-d by b
    ’         Decrement
     ¬        Is falsy
fireflame241
źródło
4

Python 2 , 34 bajty

f=lambda a,b:a==1or-~b*f(-b%a,a)/a

Wypróbuj online!

Rekurencyjna funkcja, która daje Trueza print f(1,2), które uważam za dopuszczalne, a błędy dla nieprawidłowych danych wejściowych.

xax1(modb)

ax1=kbk

Nabierający moda1kb(moda)kb1(moda)k .

kf(b%a,a) (działa, ponieważ Python podaje wartości dodatnie dla modulo z argumentem ujemnym).

aab

kax1=kbxkb+1a

Kritixi Lithos
źródło
3

Liczby R + , 15 bajtów

numbers::modinv

zwraca NAdla tych abez modów inwersyjnych b.

R-Fiddle, aby spróbować!

R , 33 bajty (niekonkurujące)

To się nie powiedzie na bardzo dużych b ponieważ faktycznie tworzy wektor 32*bbitów wielkości .

function(a,b)which((1:b*a)%%b==1)

Wypróbuj online!

Zwraca integer(0)(pusta lista) dla tych abez modów inwersyjnych b.

Giuseppe
źródło
3

Mathematica, 18 bajtów

PowerMod[#,-1,#2]&

wkład

[31, 73714876143]

J42161217
źródło
3

Python 2 , 51 49 54 53 51 49 bajtów

-1 bajt dzięki oficjalnemu
-1 bajtowi dzięki Kudłaty

a,b=input()
i=a<2
while(a*i%b-1)*b%a:i+=1
print+i

Wypróbuj online!

Drukuje, 0gdy nie ma rozwiązania.

Pręt
źródło
1
Wyjścia 0dla a=1i b=2; z przypadków testowych, powinien wypisać 1.
Shaggy
1
Jak zauważył Kudłaty, nie udaje się2, 1
Pan Xcoder
@Shaggy powinien już działać
Rod
To nie zwraca odpowiedzi w ciągu 60 sekund (w TIO) dla danych wejściowych 31,73714876143.
Ilmari Karonen,
3

Japt , 9 8 bajtów

Pobiera dane wejściowe w odwrotnej kolejności. Wyjścia -1dla braku dopasowania. Występuje, gdy większa liczba całkowita staje się większa.

Ç*V%UÃb1

Sprawdź to

  • Oszczędność 1 bajtu dzięki ETH wskazując na błędną i bardzo oczywistą przestrzeń.
Kudłaty
źródło
73714876143,31Wygląda na to, że dane wejściowe testu powodują błąd braku pamięci w przeglądarce Firefox (i powodują awarię Chromium). Nie sądzę, żeby to była prawidłowa odpowiedź.
Ilmari Karonen,
@IlmariKaronen: Jasno wskazałem ten fakt w moim rozwiązaniu. Możemy założyć nieskończoną pamięć na potrzeby kodu golfa, aby problemy z pamięcią i awarie nie unieważniały tego rozwiązania.
Kudłaty
1
Niestety problemy z pamięcią uniemożliwiają również stwierdzenie, czy kod rzeczywiście rozwiązałby przypadki testowe w 60 sekund, jak określono w wyzwaniu. Podejrzewam, że tak się nie stanie, nawet jeśli dostępna będzie wystarczająca ilość pamięci, aby się nie zawiesić, ale bez komputera, który może tak długo uruchamiać program, nie ma pewności.
Ilmari Karonen,
2

Python 3 + gmpy , 23 bajty

Nie sądzę, że w Pythonie może być krótszy.

gmpy.invert
import gmpy

Wypróbuj online! (nie będzie działać, jeśli nie masz zainstalowanego Gmaila)

Pan Xcoder
źródło
2

Python 3 , 49 bajtów

lambda a,b:[c for c in range(b)if-~c*a%b==1][0]+1

Wypróbuj online!

Python 3 , 50 bajtów

lambda a,b:[c for c in range(1,b+1)if c*a%b==1][0]

Wypróbuj online!

Wyrzuca to IndexError: list index out of rangew przypadku, gdy nie ma modularnego odwrotności multiplikatywnej, jak dopuszczają to reguły.

Pan Xcoder
źródło
To nie zwraca wyniku dla danych wejściowych 31,73714876143w ciągu 60 sekund (w TIO).
Ilmari Karonen,
@IlmariKaronen Wydaje się, że skończę za 56 sekund na mojej maszynie (Macbook Pro '15)
Mr. Xcoder
2

8 , 6 bajtów

Kod

invmod

Wyjaśnienie

invmodjest ósmym słowem, które oblicza wartość odwrotności amodulo b. Powracanull w przypadku przepełnienia lub innych błędów.

Przypadki użycia i testowe

ok> 1 2 invmod .
1
ok> 3 6 invmod .
null
ok> 7 87 invmod .
25
ok> 25 87 invmod .
7
ok> 2 91 invmod .
46
ok> 13 91 invmod .
null
ok> 19 1212393831 invmod .
701912218
ok> 31 73714876143 invmod .
45180085378
ok> 3 73714876143 invmod .
null
Dwór Chaosu
źródło
2

Pari / GP , 22 bajty

a->b->lift(1/Mod(a,b))

Zgłasza błąd, gdy nie ma odwrotności.

Wypróbuj online!

alephalpha
źródło
2

J , 28 bajtów

4 :'(1=x+.y)*x y&|@^<:5 p:y'

Wypróbuj online!

Wykorzystuje twierdzenie Eulera . Zwraca 0, jeśli odwrotność nie istnieje.

Wyjaśnienie

4 :'(1=x+.y)*x y&|@^<:5 p:y'  Input: a (LHS), b (RHS)
4 :'                       '  Define an explicit dyad - this is to use the special
                              form `m&|@^` to perform modular exponentiation
                          y   Get b
                      5 p:    Euler totient
                    <:        Decrement
             x                Get a
                   ^          Exponentiate
               y&|@             Modulo b
       x+.y                   GCD of a and b
     1=                       Equals 1
            *                 Multiply
mile
źródło
2

Pyth , 10 bajtów

3 bajty zapisane dzięki @Jakube .

xm%*szdQQ1

Wypróbuj tutaj!

Zwroty -1 brak multiplikatywnej odwrotności.

Podział kodu

xm%*szdQQ1      Let Q be the first input.
 m      Q       This maps over [0 ... Q) with a variable d.
   *szd         Now d is multiplied by the evaluated second input.
  %    Q        Now the remained modulo Q is retrieved.
x        1      Then, the first index of 1 is retrieved from that mapping.

Pyth , 15 13 bajtów

KEhfq1%*QTKSK

Zgłasza wyjątek w przypadku, gdy nie istnieje odwrotność multiplikatywna.

Wypróbuj tutaj!

Pyth , 15 bajtów

Iq1iQKEfq1%*QTK

Dodaje to wiele bajtów do obsługi przypadku, w którym taka liczba nie istnieje. Program można znacznie skrócić, jeśli nie będzie trzeba zajmować się tą sprawą:

fq1%*QTK

Wypróbuj tutaj!

Pan Xcoder
źródło
2 bajty zapisane za pomocąKExm%*QdKK1
Jakube,
Lub 3 bajty, jeśli xm%*szdQQ1
zamienisz
@Jakube Wielkie dzięki, edycja!
Pan Xcoder,
Jak to działa?
Kritixi Lithos
@ Cowsquack Dodałem całkowicie prymitywny podział kodu, ale nie mam czasu na pełne wyjaśnienie. Mam nadzieję, że jest to na razie wystarczająco jasne, ale postaram się wkrótce dodać bardziej kompletne wyjaśnienie.
Pan Xcoder,
1

C (gcc) , 115 bajtów

#define L long long
L g(L a,L b,L c,L d){return a?g(b%a,a,d-b/a*c,c):b-1?0:d;}L f(L a,L b){return(g(a,b,1,0)+b)%b;}

Wypróbuj online!

Rozszerzony algorytm euklidesowy, wersja rekurencyjna

C (gcc) , 119 bajtów

long long f(a,b,c,d,t,n)long long a,b,c,d,t,n;{for(c=1,d=0,n=b;a;a=t)t=d-b/a*c,d=c,c=t,t=b%a,b=a;return b-1?0:(d+n)%n;}

Wypróbuj online!

Rozszerzony algorytm euklidesowy, wersja iteracyjna

nwellnhof
źródło
1

C (gcc) , 48 110 104 bajtów

#define f(a,b)g(a,b,!b,1,b)
long g(a,b,c,d,n)long a,b,c,d,n;{a=a?g(b%a,a,d,c-(b-b%a)/a*d):!--b*(c+n)%n;}

Wypróbuj online!

Powinno to działać ze wszystkimi wejściami (które mieszczą się w długim czasie) w ciągu 60 sekund.

Edytować. Już nadużywam nzmiennej, więc równie dobrze mogę założyć, że gcc umieszcza pierwsze przypisanie %rax.

sufitowy
źródło
1
Niestety, daje to błędne wyniki nawet dla dość małych danych wejściowych z powodu przepełnienia liczb całkowitych w pętli. Na przykład f(3,1000001)zwraca 717, co oczywiście jest nonsensem (poprawna odpowiedź to 333334). Ponadto, nawet jeśli ten błąd został naprawiony przy użyciu szerszego typu liczb całkowitych, to podejście brutalnej siły z pewnością przekroczyłoby limit czasu dla niektórych większych przypadków testowych podanych w wyzwaniu.
Ilmari Karonen,
0

Axiom, 45 bytes

f(x:PI,y:PI):NNI==(gcd(x,y)=1=>invmod(x,y);0)

0 for error else return z with x*z Mod y =1

RosLuP
źródło
0

Python 2, 52 bytes

-3 bytes thanks to Mr. Xcoder.

f=lambda a,b,i=1:i*a%b==1and i or i<b and f(a,b,i+1)

Try it online!

Outputs False on no solution and errors out as b gets larger.

Embedded TIO

I'm just testing out iframes in Stack Snippets and they work absolutely fantastic.

totallyhuman
źródło
I'm not certain this works, can't i*a%b be 0?
Wheat Wizard
Fails with "maximum recursion depth exceeded" error for input (31,73714876143).
Ilmari Karonen
0

JavaScript (ES6), 42 41 39 38 bytes

Outputs false for no match. Will throw a overflow error as the second number gets to be too large.

x=>y=>(g=z=>x*z%y==1?z:z<y&&g(++z))(1)
Shaggy
źródło
0

Jelly, 27 bytes

²%³
⁴Ç⁹Сx⁸
ÆṪ’BṚçL$P%³×gỊ¥

Try it online!

Uses Euler's theorem with modular exponentiation. Since Jelly doesn't have a builtin to perform modular exponentiation, it had to be implemented, and it took most of the bytes.

miles
źródło
0

Axiom, 99 bytes

w(a,b,x,u)==(a=0=>(b*b=1=>b*x;0);w(b rem a,a,u,x-u*(b quo a)));h(a,b)==(b=0=>0;(b+w(a,b,0,1))rem b)

it use the function h(); h(a,b) return 0 if error [not exist inverse] otherwise it return the z such that a*z mod b = 1 This would be ok even if arguments are negative...

this would be the general egcd() function that retunr a list of int (so they can be negative too)

egcd(aa:INT,bb:INT):List INT==
   x:=u:=-1   -- because the type is INT
   (a,b,x,u):=(aa,bb,0,1)
   repeat
      a=0=>break
      (q,r):=(b quo a, b rem a)
      (b,a,x,u):=(a,r,u,x-u*q)
   [b,x, (b-x*aa)quo bb]

this is how use it

(7) -> h(31,73714876143)
   (7)  45180085378
                                                    Type: PositiveInteger

i find the base algo in internet from https://pastebin.com/A13ybryc

RosLuP
źródło