Calcola l'inverso di un numero intero modulo 100000000003


21

L'attività è la seguente. Dato un numero interox (tale che xmodulo 100000000003non è uguale a 0) presentato al tuo codice in qualsiasi modo ritieni opportuno, genera un altro numero intero in y < 100000000003modo che (x * y) mod 100000000003 = 1.

Il codice deve richiedere meno di 30 minuti per essere eseguito su un computer desktop standard per qualsiasi input xtale |x| < 2^40.

Casi test

Ingresso: 400000001. Uscita: 65991902837

Ingresso: 4000000001. Uscita: 68181818185

Ingresso: 2. Uscita: 50000000002

Ingresso: 50000000002. Uscita: 2.

Ingresso: 1000000. Uscita: 33333300001

restrizioni

Non è possibile utilizzare alcuna libreria o funzione incorporata che esegue l'aritmetica del modulo (o questa operazione inversa). Ciò significa che non puoi nemmeno fare a a % bmeno dell'attuazione% te stesso. Tuttavia, è possibile utilizzare tutte le altre funzioni integrate aritmetiche non modulo.

Domanda simile

Questo è simile a questa domanda, anche se si spera sia abbastanza diverso da essere ancora interessante.


Quindi a- (a / b) * b va bene?
user253751

@immibis Questo sembra a posto.

tag: codice limitato?
Felipe Nardi Batista,

1
Di cosa si tratta 100000000003? (solo chiedendosi)
NoOneIsHere

1
@Lembik In tal caso, potresti menzionare quel requisito che <100000000003 nella domanda?
Isaacg,

Risposte:


16

Pyth, 24 byte

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

Suite di test

Questo utilizza il fatto che a ^ (p-2) mod p = a ^ -1 mod p.

Innanzitutto, reimplemento manualmente il modulo, per il caso specifico del mod 100000000003. Uso la formula a mod b = a - (a/b)*b, dove /è la divisione floored. Genero il modulo con 10^11 + 3, usando il codice +3^T11, quindi lo salvo J, quindi uso questa e la formula sopra per calcolare b mod 100000000003 con -b*/bJ+3^T11J. Questa funzione è definita come yconL .

Successivamente, comincio con l'ingresso, quindi lo porto alla decima potenza e riduco la mod 100000000003 e lo ripeto 11 volte. y^GTè il codice eseguito in ogni passaggio euy^GT11Q esegue 11 volte a partire dall'input.

Ora ho Q^(10^11) mod 10^11 + 3, e voglio Q^(10^11 + 1) mod 10^11 + 3, quindi moltiplico per l'input con *, lo riduco mod 100000000003 con yun'ultima volta e l'output.


Davvero molto bello!

Immagino sia troppo tardi per me per stringere i casi di test ....

1
@Lembik Lo farei comunque, ma le opinioni possono variare. È la tua sfida, fallo funzionare come vuoi tu.
Isaacg,

Nel modo in cui viene scritta la domanda, è possibile che tu possa eliminare la riduzione finale, anche se ho chiesto un chiarimento sulla necessità di un risultato <100000000003.
Ørjan Johansen,

9

Haskell , 118 113 105 101 byte

Ispirato da questa soluzione .

-12 da Ø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]

Provalo online!

Haskell , 48 byte

Una riscrittura di questa soluzione . Sebbene abbastanza veloce per il vettore di test, questa soluzione è troppo lenta per altri input.

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

Provalo online!


Eccezionale! Mi piace l'espiazione mediante approccio quadrangolare.
Isaacg,

La soluzione più breve sarebbe qualcosa di simile Provalo online! ma non credo che le sue prestazioni siano accettabili ...
bartavelle,

(1) È più breve creare gun operatore (e?b)a s|...(2) Se si cambia ae squindi è possibile creare !un non- operatore e inline y. (3) Puoi sbarazzarti del costoso wherecon un lasttrucco, a costo di duplicare z. Provalo online!
Ørjan Johansen,

Ora quelli sono dei bei trucchi!
bartavelle

Oh, e |e==0=asi sbarazza di quella fastidiosa duplicazione.
Ørjan Johansen,

6

Brachylog , 22 byte

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

Provalo online!

Ciò ha richiesto circa 10 minuti 1000000con una versione leggermente diversa (e più lunga) del codice che era esattamente due volte più veloce (controllato solo valori positivi diİ anziché sia ​​positivi che negativi). Pertanto, il completamento di tale input dovrebbe richiedere circa 20 minuti.

Spiegazione

Lo descriviamo semplicemente Input × Output - 1 = 100000000003 × an integere lasciamo che l'aritmetica dei vincoli Outputci trovi.

∧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

Tecnicamente non abbiamo bisogno dell'etichettatura esplicita , tuttavia se non lo usiamo, non controlleremo il caso N = [100000000003,1](perché spesso è inutile), il che significa che questo sarà molto lento per l'input, 2ad esempio perché dovrà trovare il secondo intero più piccolo invece del primo.


1
Wow, non mi sarei mai aspettato che l'aritmetica dei vincoli riuscisse a risolverlo. Eccezionale!
Isaacg,

1
@isaacg La velocità di questo è purtroppo completamente dipendente dal valore di İ, quindi questo è ancora piuttosto lento per i grandi prodotti.
Fatalizza il

Aggiornato la domanda. Il tuo codice impiega sempre meno di 30 minuti?

6

Python, 53 51 49 58 53 49 byte

-2 byte grazie a orlp
-2 byte grazie a officialaimm
-4 byte grazie a Felipe Nardi Batist
-3 byte grazie a isaacg
-1 byte grazie a Ørjan Johansen
-2 byte grazie a Federico Poloni

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

Provalo online!

Mi ci sono voluti circa 30 minuti per capirlo. La mia soluzione è iniziare con il primo numero che sarà mod a 1. Questo numero è 1. Se è divisibile per x, allora y è quel numero diviso per x. In caso contrario, aggiungi 10000000003 a questo numero per trovare il secondo numero con cui la mod 1000000003 sarà uguale a 1 e ripeti.


Il primo numero che cambierà a 1 è 1 ...
orlp

@orlp lol grazie. Mi ha salvato 2 byte :)
Zachary Cotton,

Interessante, su TIO questo è veloce per tutti i casi di test, ma un battito di tastiera un po 'casuale mi ha dato 421385994quali timeout.
Ørjan Johansen,

@ ØrjanJohansen Buona conoscenza.

1
Se è necessario bsolo una volta, perché non codificarlo?
Federico Poloni,

5

JavaScript (ES6), 153 143 141 byte

Ispirato da questa risposta da math.stackexchange.com .

Una funzione ricorsiva basata sull'algoritmo euclideo.

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 è implementato calcolando:

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

Poiché è necessario anche il quoziente, farlo in questo modo ha effettivamente un senso.

Casi test


Nell'ultima occorrenza è necessario solo il pavimento a 64 bit, quindi è possibile sostituire gli altri con 0 | x / y e rimuovere la dichiarazione
Oki

5

C ++ 11 (GCC / Clang, Linux), 104 102 byte

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

Ungolfed, basato sul teorema di Eulero e sull'esponentazione binaria.

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 ++ richiede solo longdi essere almeno a 32 bit, quindi non può necessariamente contenere 1e11 + 3. È a 32 bit su Windows x86-64. longè un tipo a 64 bit su Linux x86-64 (e altri sistemi operativi che utilizzano l'ABI SystemV), tuttavia. Quindi, per essere completamente portatile, dovresti usare long long, che è garantito per essere almeno a 64 bit dal C ++ 11 .
Peter Cordes,

__int128_tnon sembra essere C ++ standard, sembra essere un'estensione gcc, sarebbe bello se lo dichiarassi come linguaggio (C ++ 11 + gcc).
Felix Dombek,

3
Questo non dovrebbe essere un sito di esperti C ++, speravo che nessuno se ne accorgesse.
SteelRaven,

@PeterCordes Code golf non deve essere portatile o anche ben formato, deve solo lavorare su un'implementazione.
aschepler

1
@aschepler: lo so, ecco perché ho detto " avresti bisogno". Ho pensato che fosse utile indicare su quale piattaforma avrebbe funzionato / non avrebbe funzionato, nel caso qualcuno l'avesse provato e si fosse messo nei guai.
Peter Cordes,

4

Mathematica, 49 byte

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

Quanto tempo richiede l'esecuzione?

Meno di 0,001 secondi sul mio computer (per il caso 2 ^ 40-1)
Keyu Gan,


1

Rubino , 58 byte

Per ora usa l'applicazione isaacg del piccolo teorema di Fermat mentre finisco di programmare la soluzione di forza bruta.

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

Versione attuale della forza bruta, che è 47 byte ma potrebbe essere è troppo lento:

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

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.