Étant donné deux nombres n et m, évaluez la tour de puissance infinie:
n ^ (n + 1) ^ (n + 2) ^ (n + 3) ^ (n + 4) ^ ... mod m
Gardez à l'esprit que ^ est associatif à droite. Donc 2 ^ 3 ^ 4 = 2 ^ (3 ^ 4). Maintenant, comment pouvez-vous éventuellement attribuer une valeur à une séquence infinie d'opérateurs associatifs à droite?
Définissez f (n, m, i) comme la tour de puissance contenant les i premiers termes de la tour de puissance infinie. Ensuite, il y a une constante C telle que pour chaque i> C, f (n, m, i) = f (n, m, C). On pourrait donc dire que la tour de puissance infinie converge vers une certaine valeur. Nous sommes intéressés par cette valeur.
Votre programme doit être capable de calculer n = 2017, m = 10 ^ 10 en moins de 10 secondes sur un PC moderne raisonnable. Autrement dit, vous devez implémenter un algorithme réel, pas de bruteforcing.
Vous pouvez supposer que n <2 30 et m <2 50 pour les limites numériques de votre langage de programmation, mais votre algorithme doit théoriquement fonctionner pour n'importe quelle taille n , m . Cependant, votre programme doit être correct pour les entrées dans ces limites de taille, les débordements de valeurs intermédiaires ne sont pas excusés si les entrées sont dans ces limites.
Exemples:
2, 10^15
566088170340352
4, 3^20
4
32, 524287
16
la source
n
et nem
sont pas garantis d'être co-prime.Réponses:
Pyth, 23 octets
Définit une fonction
g
, en prenant m et n dans cet ordre.Essayez-le en ligne
Comment ça fonctionne
Python 2,
10976 octetsEssayez-le en ligne!
Pourquoi ça marche
Nous utilisons la généralisation suivante du théorème d' Euler .
Lemme. n 2φ ( m ) ≡ n φ ( m ) (mod m ) pour tous les n (si n est premier à m ).
Preuve: pour toutes les puissances premières p k divisant m ,
Par conséquent, n 2φ ( m ) ≡ n φ ( m ) (mod m ).
Corollaire. Si k ≥ φ ( m ), alors n k ≡ n φ ( m ) + ( k mod φ ( m )) (mod m ).
Preuve: Si k ≥ 2φ ( m ), le lemme donne n k = n 2φ ( m ) n k - 2φ ( m ) ≡ n φ ( m ) n k - 2φ ( m ) = n k - φ ( m ) ( mod m ) et nous répétons jusqu'à ce que l'exposant soit inférieur à 2φ ( m ).
la source
sympy.totient
.Haskell , 156 octets
(?)
prend deuxInteger
s et retourne unInteger
, utilisez as(10^10)?2017
(ordre inversé par rapport à OP.)Essayez-le en ligne! (J'ai mis les cas à tester dans l'en-tête cette fois, car ils utilisent la notation d'exponentiation.)
Curieusement, le cas de test le plus lent n'est pas celui avec une limite de vitesse (c'est presque instantané), mais l'
524287 ? 32
un, car il524287
s'agit d'un nombre premier beaucoup plus grand que celui qui apparaît dans les facteurs des autres cas de test.Comment ça fonctionne
(x&m)y
estx^y `mod` m
, ou mod de puissance, utilisant l'exponentiation par quadrature.n#p
est la fonction de totient d'Euler den
, en supposant qu'iln
n'y a pas de facteurs premiers plus petits quep
.m
estn
avec tous lesp
facteurs divisés.k
tels facteurs, le totient doit lui-même obtenir un facteur correspondant(p-1)*p^(k-1)
, qui est calculé commediv(n*p-n)(p*m)
.1`max`...
gère le cas oùn
n'était pas réellement divisible parp
, ce qui rend l'autre argumentmax
égal à0
.m?n
utilise que quandy
est assez grand,n^y `mod` m
est le même quen^(t+(y`mod`t)) `mod` m
, quandt
est le totient dem
. (Let+
est nécessaire pour ces facteurs premiersn
etm
ont en commun, qui sont tous maximisés.)la source
Mathematica, 55 octets
Exemples:
la source
Pari / GP , 59 octets
Essayez-le en ligne!
la source