Oblicz odwrotność liczby całkowitej modulo 100000000003


21

Zadanie jest następujące. Biorąc pod uwagę liczbę całkowitą x(taką, że xmodulo 100000000003nie jest równe 0) przedstawioną w kodzie w dowolny dogodny sposób, wypisz kolejną liczbę całkowitą y < 100000000003, aby (x * y) mod 100000000003 = 1.

Kod musi trwać krócej niż 30 minut, aby uruchomić się na standardowym komputerze stacjonarnym dla każdegox takiego wejścia |x| < 2^40.

Przypadki testowe

Wejście: 400000001. Wyjście: 65991902837

Wejście: 4000000001. Wyjście: 68181818185

Wejście: 2. Wyjście: 50000000002

Wejście: 50000000002. Wyjście: 2.

Wejście: 1000000. Wyjście: 33333300001

Ograniczenia

Nie wolno używać żadnych bibliotek ani wbudowanych funkcji, które wykonują arytmetykę modulo (lub tę odwrotną operację). Oznacza to, że nie możesz się obejść a % bbez wdrożenia %się. Możesz jednak użyć wszystkich innych niemodulo modulowanych wbudowanych funkcji arytmetycznych.

Podobne pytanie

Jest to podobne do tego pytania, choć, mam nadzieję, na tyle różne, że nadal będzie interesujące.


Więc a- (a / b) * b jest w porządku?
user253751

@immibis To wygląda dobrze.

tag: kod ograniczony?
Felipe Nardi Batista

1
Co jest specjalnego 100000000003? (tylko się zastanawiam)
NoOneIsHere

1
@Lembik Czy w takim przypadku mógłbyś wspomnieć o tym wymogu, że y <100000000003 w pytaniu?
isaacg

Odpowiedzi:


16

Pyth, 24 bajty

L-b*/bJ+3^T11Jy*uy^GT11Q

Zestaw testowy

Wykorzystuje to fakt, że mod ^ (p-2) p = mod ^ ^ p.

Najpierw ręcznie reimplementuję moduł, dla konkretnego przypadku mod 100000000003. Używam wzoru a mod b = a - (a/b)*b, w którym /jest dzielenie zmiennoprzecinkowe. Generuję moduł za 10^11 + 3pomocą, używając kodu +3^T11, a następnie zapisuję go J, a następnie używam tej i powyższej formuły do ​​obliczenia b mod 100000000003 za pomocą -b*/bJ+3^T11J. Funkcja ta jest określona jako yw L.

Następnie zaczynam od wejścia, następnie doprowadzam do dziesiątej mocy i redukuję mod 100000000003, i powtarzam to 11 razy. y^GTto kod wykonywany na każdym kroku i uy^GT11Quruchamia go 11 razy, zaczynając od danych wejściowych.

Teraz mam Q^(10^11) mod 10^11 + 3i chcę Q^(10^11 + 1) mod 10^11 + 3, więc mnożę przez dane wejściowe *, redukuję to mod 100000000003 ypo raz ostatni i generuję.


Naprawdę bardzo ładnie!

Domyślam się, że jest już za późno, żeby zaostrzyć przypadki testowe ....

1
@Lembik Zrobiłbym to mimo wszystko, ale opinie mogą się różnić. To twoje wyzwanie, spraw, aby działało tak, jak chcesz.
isaacg

Sposób, w jaki pytanie jest napisane, jest możliwe, że możesz zrezygnować z ostatecznej redukcji, chociaż poprosiłem o wyjaśnienie, czy wymagany jest wynik <100000000003.
Ørjan Johansen

9

Haskell , 118 113 105 101 bajtów

Inspirowane tym rozwiązaniem .

-12 od Ørjan Johansen

p=10^11+3
k b=((p-2)?b)b 1
r x=x-div x p*p
(e?b)s a|e==0=a|1<2=(div e 2?b$r$s*s)$last$a:[r$a*s|odd e]

Wypróbuj online!

Haskell , 48 bajtów

Przepisz to rozwiązanie . Chociaż jest wystarczająco szybki dla wektora testowego, to rozwiązanie jest zbyt wolne dla innych wejść.

s x=until(\t->t-t`div`x*x==0)(+(10^11+3))1`div`x

Wypróbuj online!


Niesamowite! Lubię potęgowanie przez podejście do kwadratu.
isaacg

Najkrótszym rozwiązaniem byłoby coś w stylu Wypróbuj online! ale nie sądzę, aby jego wydajność była do zaakceptowania ...
bartavelle,

(1) Jest to krótszy, aby goperator (e?b)a s|...(2) Jeśli włączeniu aa snastępnie można zrobić !to non -operator i inline ydo niego. (3) Można pozbyć się drogi whereprzez lastpodstęp, kosztem powielania z. Wypróbuj online!
Ørjan Johansen

To są fajne sztuczki!
bartavelle

Och, i |e==0=apozbywam się tego nieznośnego powielania.
Ørjan Johansen

6

Brachylog , 22 bajty

∧10^₁₁+₃;İ≜N&;.×-₁~×N∧

Wypróbuj online!

Zajęło to około 10 minut w 1000000przypadku nieco innej (i dłuższej) wersji kodu, która była dokładnie dwa razy szybsza (sprawdzono tylko wartości dodatnie İzamiast zarówno dodatnich, jak i ujemnych). Dlatego wypełnienie tego wpisu powinno zająć około 20 minut.

Wyjaśnienie

Po prostu to opisujemy Input × Output - 1 = 100000000003 × an integeri pozwól Outputnam znaleźć arytmetykę ograniczeń .

∧10^₁₁+₃                   100000000003
        ;İ≜N               N = [100000000003, an integer (0, then 1, then -1, then 2, etc.)]
            &;.×           Input × Output…
                -₁         … - 1…
                  ~×N∧     … = the product of the elements of N

Technicznie nie potrzebujemy wyraźnego etykietowania , jednak jeśli go nie użyjemy, nie sprawdzi obudowy N = [100000000003,1](ponieważ często jest to bezużyteczne), co oznacza, że ​​będzie to bardzo powolne 2na przykład wprowadzanie danych, ponieważ będzie musiało znaleźć drugą najmniejszą liczbę całkowitą zamiast pierwszego.


1
Wow, nigdy nie spodziewałbym się, że arytmetyka ograniczeń to rozwiąże. Niesamowite!
isaacg

1
@isaacg Szybkość tego jest niestety całkowicie zależna od wartości İ, więc jest to wciąż dość wolne w przypadku dużych produktów.
Fatalize

Zaktualizowałem pytanie. Czy Twój kod zawsze zajmuje mniej niż 30 minut?

6

Python, 53 51 49 58 53 49 bajtów

-2 bajty dzięki orlp
-2 bajty dzięki Officialaimm
-4 bajty dzięki Felipe Nardi Batist
-3 bajty dzięki isaacg
-1 bajt dzięki Ørjan Johansen
-2 bajty dzięki Federico Poloni

x=input()
t=1
while t-t/x*x:t+=3+10**11
print t/x

Wypróbuj online!

Rozpracowanie tego zajęło mi około 30 minut. Moim rozwiązaniem jest zacząć od pierwszej liczby, która zmieni się na 1. Ta liczba to 1. Jeśli jest podzielna przez x, to y jest liczbą podzieloną przez x. Jeśli nie, dodaj 10000000003 do tego numeru, aby znaleźć drugą liczbę, której mod 1000000003 będzie równy 1 i powtórz.


Pierwszą liczbą, która zmieni się na 1, jest 1 ...
lub

@orlp lol dzięki. To zaoszczędziło mi 2 bajty :)
Zachary Cotton

Co ciekawe, na TIO jest to szybkie dla wszystkich przypadków testowych, ale nieco przypadkowe uderzenie w klawiaturę dało mi to, 421385994które czasy minęły.
Ørjan Johansen

@ ØrjanJohansen Good sleuthing.

1
Jeśli potrzebujesz btylko raz, dlaczego nie zakodować na stałe?
Federico Poloni

5

JavaScript (ES6), 153 143 141 bajtów

Zainspirowany tą odpowiedzią od math.stackexchange.com .

Funkcja rekurencyjna oparta na algorytmie euklidesowym.

f=(n,d=(F=Math.floor,m=1e11+3,a=1,c=n,b=F(m/n),k=m-b*n,n>1))=>k>1&d?(e=F(c/k),a+=e*b,c-=e*k,f(n,c>1&&(e=F(k/c),k-=e*c,b+=e*a,1))):a+d*(m-a-b)

Modulo jest realizowane przez obliczenia:

quotient = Math.floor(a / b);
remainder = a - b * quotient;

Ponieważ iloraz jest również potrzebny, robienie tego w ten sposób ma sens.

Przypadki testowe


W ostatnim przypadku potrzebujesz tylko 64-bitowej podłogi, więc możesz zastąpić pozostałe 0 | x / y i usunąć deklarację
Oki

5

C ++ 11 (GCC / Clang, Linux), 104 102 bajtów

using T=__int128_t;T m=1e11+3;T f(T a,T r=1,T n=m-2){return n?f(a*a-a*a/m*m,n&1?r*a-r*a/m*m:r,n/2):r;}

https://ideone.com/gp41rW

Niegolfowany, oparty na twierdzeniu Eulera i potęgowaniu binarnym.

using T=__int128_t;
T m=1e11+3;
T f(T a,T r=1,T n=m-2){
    if(n){
        if(n & 1){
            return f(a * a - a * a / m * m, r * a - r * a / m * m, n / 2);
        }
        return f(a * a - a * a / m * m, r, n / 2);
    }
    return r;
}

ISO C ++ wymaga tylko longco najmniej 32-bitowego, więc niekoniecznie musi się trzymać 1e11 + 3. Jest 32-bitowy w systemie Windows x86-64. longjest 64-bitowym typem w systemie Linux x86-64 (i innych systemach operacyjnych, które używają SystemV ABI). Aby być w pełni przenośnym, musisz użyć long long, co gwarantuje, że jest co najmniej 64-bitowe od C ++ 11 .
Peter Cordes

__int128_tnie wydaje się być standardowym C ++, wydaje się być rozszerzeniem gcc, byłoby fajnie, gdybyś określił to jako język (C ++ 11 + gcc).
Felix Dombek

3
To nie powinna być witryna ekspertów C ++, mam nadzieję, że nikt tego nie zauważy.
SteelRaven

@PeterCordes Code golf nie musi być przenośny ani nawet dobrze uformowany, musi działać tylko na jednej implementacji.
aschepler

1
@aschepler: Wiem, dlatego powiedziałem „ty będzie potrzebować”. Pomyślałem, że warto wskazać, na której platformie będzie / nie pracował, na wypadek gdyby ktoś spróbował i wpadł w kłopoty.
Peter Cordes

4

Mathematica, 49 bajtów

x/.FindInstance[x#==k(10^11+3)+1,{x,k},Integers]&

Jak długo to trwa?

Mniej niż 0,001 s na moim komputerze (dla przypadku 2 ^ 40-1)
Keyu Gan


1

Rubinowy , 58 bajtów

Na razie wykorzystuje isaacgowskie małe twierdzenie Fermata, podczas gdy ja kończę mierzenie rozwiązania brutalnej siły.

->n,x=10**11+3{i=n;11.times{i**=10;i-=i/x*x};i*=n;i-i/x*x}

Aktualna wersja brute force, która wynosi 47 bajtów, lecz może być to zbyt wolno:

->n,x=10**11+3{(1..x).find{|i|i*=n;i-i/x*x==1}}

Wypróbuj online!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.