Étant donné deux nombres positifs x
et n
avec x<2^n
, écrivez la fonction la plus courte possible à calculer x^-1 mod 2^n
. En d'autres termes, trouvez y
tel que x*y=1 mod 2^n
.
Votre fonction doit s'achever dans un délai raisonnable pendant au moins n=64
, donc une recherche exhaustive ne fonctionnera pas.
Si l'inverse n'existe pas, vous devez l'indiquer à l'appelant d'une manière ou d'une autre (lever une exception, renvoyer une valeur sentinelle, etc.).
Si vous vous demandez par où commencer, essayez l' algorithme euclidien étendu .
Réponses:
Python
9589c
est votre fonction. Renvoie 0 s'il n'y a pas d'inverse (c'est-à-dire lorsque x est pair).la source
Python, 29 octets
Cela renvoie 0 pour pair x . Il utilise le théorème d'Euler, avec l'observation que 2 ^ n - 1 est divisible par 2 ^ ( n - 1) - 1, via l'exponentiation modulaire rapide intégrée de Python. C'est assez rapide pour n jusqu'à 7000 environ, où cela commence à prendre plus d'une seconde environ.
la source
Mathematica - 22
f[x,n]
retourney
avecx*y=1 mod 2^n
, sinonx is not invertible modulo 2^n
la source
GolfScript (23 caractères)
Le résultat sentinelle pour un inverse inexistant est
0
.Il s'agit d'une application simple du théorème d' Euler . , donc x - 1 ≡ x 2 n - 1 - 1xφ(2n)≡1(mod2n) x−1≡x2n−1−1(mod2n)
Malheureusement, c'est une exponentielle un peu trop grande pour être calculée directement, nous devons donc utiliser une boucle et effectuer une réduction modulaire à l'intérieur de la boucle. L'étape itérative est et nous avons le choix du cas de base: soit avecx2k−1=(x2k−1−1)2×x
k=1
ou
k=2
avecJe travaille sur une autre approche, mais la sentinelle est plus difficile.
L'observation clé est que nous pouvons construire l'inverse vers le haut peu à peu: si puis x y ∈ { 1 , 1 + 2 k - 1xy≡1(mod2k−1) , et si x est impair, nous avons x ( y + x y - 1 ) ≡ 1xy∈{1,1+2k−1}(mod2k) x . (Si vous n'êtes pas convaincu, vérifiez les deux cas séparément). Nous pouvons donc commencer à n'importe quel cas de base approprié et appliquer la transformation y ′ = ( x + 1 ) y - 1 un nombre approprié de fois.x(y+xy−1)≡1(mod2k) y′=(x+1)y−1
Depuis on obtient, par induction0x≡1(mod20)
où l'inverse est la somme d'une séquence géométrique. J'ai montré la dérivation pour éviter l'effet lapin hors du chapeau: étant donné cette expression, il est facile de voir que (étant donné que la valeur entre crochets est un entier, qui découle de sa dérivation comme une somme d'un entier séquence) le produit de gauche doit être dans la classe d'équivalence droite si est pair.x+1
Cela donne la fonction 19 caractères
qui donne des réponses correctes pour les entrées qui ont un inverse. Cependant, ce n'est pas si simple quand est pair. Une option potentiellement intéressante que j'ai trouvée est d'ajouter plutôt que .x
x&1
1
n x f
la source
Ruby - 88 caractères
Utilisez la fonction
f
.La fonction récursive de la page wiki liée renvoie simplement 0 en cas d'erreur.
la source
(e=->a,b{...})[x,2**n][0]
. Peut également enregistrer un personnage en testanta%b<1
au lieu dea%b==0
.Haskell, 42 octets
En utilisant un algorithme basé sur le lemme de Hensel qui double le nombre de chiffres à chaque itération, cela fonctionne en moins d'une seconde pour n jusqu'à environ 30 millions !
la source
Pyth , 9 octets
Essayez-le ici!
Prend la saisie dans l'ordre inverse. Ou, 9 octets aussi:
.^EtK^2QK
.Explication
la source
GAP, 39 octets
f(x,n)
renvoie l'inverse dex
modulo2^n
et donne un message d'erreurs'il n'y a pas d'inverse.
la source