Valuta le torri di potenza modulari


13

Dati due numeri n e m, valuta la torre di potenza infinita:

n ^ (n + 1) ^ (n + 2) ^ (n + 3) ^ (n + 4) ^ ... mod m

Tieni presente che ^ è associativo. Quindi 2 ^ 3 ^ 4 = 2 ^ (3 ^ 4). Ora come puoi eventualmente assegnare un valore a una sequenza infinita di operatori associativi a destra?

Definisci f (n, m, i) come la torre di potere contenente i primi termini della torre di potere infinita. Quindi c'è una costante C tale che per ogni i> C, f (n, m, i) = f (n, m, C). Quindi si potrebbe dire che la torre di potenza infinita converge su un certo valore. Siamo interessati a quel valore.


Il tuo programma deve essere in grado di calcolare n = 2017, m = 10 ^ 10 in meno di 10 secondi su un PC moderno ragionevole. Cioè, dovresti implementare un vero algoritmo, senza bruteforcing.

Puoi supporre che n <2 30 e m <2 50 per i limiti numerici nel tuo linguaggio di programmazione, ma il tuo algoritmo deve teoricamente funzionare per qualsiasi dimensione n , m . Tuttavia, il programma deve essere corretto per gli input entro questi limiti di dimensione, gli overflow di valori intermedi non sono giustificati se gli input sono entro questi limiti.

Esempi:

2, 10^15
566088170340352

4, 3^20
4

32, 524287
16

Tip (per contendenti): ne msono , non garantito per essere co-prime.
Leaky Nun,

1
10 ^ 10 (e 10 ^ 20 e potenzialmente 3 ^ 20 per numeri interi con segno) è maggiore dei tipi interi predefiniti di molte lingue. È necessario che sia supportato questo input di grandi dimensioni?
Maniglia della porta

1
@orlp Quel "sì" include 10 ^ 20? Perché questo non rientra in un numero intero a 64 bit, quindi se vuoi richiederlo, ti suggerirei di indicarlo esplicitamente, perché altrimenti otterrai molte risposte non valide da parte di persone che assumono quel 64 bit i numeri interi saranno abbastanza precisi.
Martin Ender,

1
In entrambi i casi, qual è l'input più grande che dobbiamo supportare?
Martin Ender,

@Doorknob Ho aggiunto limiti più indulgenti alla sfida. Tuttavia il tuo algoritmo deve teoricamente funzionare per qualsiasi dimensione m, n .
orlp,

Risposte:


7

Pyth, 23 byte

M&tG.^HsgBu-G/GH{PGGhHG

Definisce una funzione g, prendendo m e n in quell'ordine.

Provalo online

Come funziona

M&tG.^HsgBu-G/GH{PGGhHG
M                         def g(G, H):
 &tG                        0 if G == 1, else …
                 PG         prime factors of G
                {           deduplicate that
          u-G/GH   G        reduce that on lambda G,H:G-G/H, starting at G
                              (this gives the Euler totient φ(G))
        gB          hH      bifurcate: two-element list [that, g(that, H + 1)]
       s                    sum
    .^H               G     H^that mod G

Python 2, 109 76 byte

import sympy
def g(n,m):j=sympy.totient(m);return m-1and pow(n,j+g(n+1,j),m)

Provalo online!

Perché funziona

Usiamo la seguente generalizzazione del teorema di Eulero .

Lemma. n 2φ ( m )n φ ( m ) (mod m ) per tutti n (indipendentemente dal fatto che n sia coprime in m ).

Prova: per tutte le potenze prime p k che dividono m ,

  • Se p divide n , allora perché φ ( m ) ≥ φ ( p k ) = p k - 1 ( p - 1) ≥ 2 k - 1k , abbiamo n 2φ ( m ) ≡ 0 ≡ n φ ( m ) (mod p k ).
  • Altrimenti, poiché φ ( p k ) divide φ ( m ), il teorema di Eulero indica n 2φ ( m ) ≡ 1 ≡ n φ ( m ) (mod p k ).

Pertanto, n 2φ ( m )n φ ( m ) (mod m ).

Corollario. Se k ≥ φ ( m ), allora n kn φ ( m ) + ( k mod φ ( m )) (mod m ).

Prova: se k ≥ 2φ ( m ), il lemma dà n k = n 2φ ( m ) n k - 2φ ( m )n φ ( m ) n k - 2φ ( m ) = n k - φ ( m ) ( mod m ) e ripetiamo fino a quando l'esponente è inferiore a 2φ ( m ).


In che modo questo gestisce il caso in cui la base e il modulo non sono coprime? PS sympy ha una funzione totient.
orlp,

@orlp Ho aggiunto una prova. Non sono sicuro di come mi sono perso sympy.totient.
Anders Kaseorg,

Ora vedo. Bel metodo!
orlp,

5

Haskell , 156 byte

(?)impiega due se Integerrestituisce un Integer, usa come (10^10)?2017(ordine inverso rispetto a OP.)

1?n=0
m?n=n&m$m#2+m#2?(n+1)
1#_=1
n#p|m<-until((<2).gcd p)(`div`p)n=m#(p+1)*1`max`div(n*p-n)(p*m)
(_&_)0=1
(x&m)y|(a,b)<-divMod y 2=mod(x^b*(mod(x*x)m&m)a)m

Provalo online! (Questa volta ho messo i test per testare nell'intestazione, poiché usano la notazione esponenziale.)

Curiosamente, il caso di test più lento non è quello con un limite di velocità (che è quasi istantaneo), ma 524287 ? 32quello, perché 524287è un numero molto più grande di quello che appare nei fattori degli altri casi di test.

Come funziona

  • (x&m)yè x^y `mod` m, o power mod, usando esponentiation mediante quadratura.
  • n#pè la funzione completa di Eulero di n, supponendo che nnon abbia fattori primi minori di p.
    • mè ncon tutti i pfattori divisi.
    • Se ci sono ktali fattori, il totale dovrebbe a sua volta ottenere un fattore corrispondente (p-1)*p^(k-1), che viene calcolato come div(n*p-n)(p*m).
    • 1`max`...gestisce il caso in cui nnon era effettivamente divisibile per p, il che rende l'altro argomento maxuguale 0.
  • La funzione principale m?nusa che quando yè abbastanza grande, n^y `mod` mè uguale a n^(t+(y`mod`t)) `mod` m, quando tè il totale di m. ( t+È necessario per quei fattori primi ne mhanno in comune, che tutti vengono massimizzati.)
  • L'algoritmo si interrompe perché le funzioni iterate di totient alla fine colpiscono 1.

1

Mathematica, 55 byte

n_~f~1=0;n_~f~m_:=PowerMod[n,(t=EulerPhi@m)+f[n+1,t],m]

Esempi:

In[1]:= n_~f~1=0;n_~f~m_:=PowerMod[n,(t=EulerPhi@m)+f[n+1,t],m]

In[2]:= f[2, 10^15]

Out[2]= 566088170340352

In[3]:= f[4, 3^20]

Out[3]= 4

In[4]:= f[32, 524287]

Out[4]= 16

In[5]:= f[2017, 10^10]

Out[5]= 7395978241

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.