Aide à la factorisation de Fermat


19

Nous aimerions factoriser un semi-premier . Le but de ce défi est de trouver deux petits entiers u et v tels que u v N peut être trivialement factorise avec la méthode de Fermat, permettant ainsi de déduire facilement les facteurs de N .NuvuvNN

La tâche

Étant donné un semi-premier et un entier positif k , nous définissons x et y comme:NkXy

y=x2-kN

X=kN
y=X2-kN

Étape # 1 - Trouvez k

Vous devez d'abord trouver la plus petite valeur possible de telle que y soit un nombre carré ( aka carré parfait).ky

Cela permet de factoriser avec une seule itération de la méthode de factorisation de Fermat . Plus concrètement, cela conduit immédiatement à:kN

kN=(X+y)×(X-y)

(Mise à jour: cette séquence est maintenant publiée sous A316780 )

Étape # 2 - Factoriser k

Il faut ensuite trouver les deux entiers positifs et v tels que:uv

c u = x +

uv=k
dv=x-
cu=X+y
v=X-y

et d sont les facteurs premiers de N .cN

Sommaire

Votre tâche consiste à écrire un programme ou une fonction qui prend comme entrée et imprime ou affiche u et v dans n'importe quel ordre et dans n'importe quel format raisonnable.Nuv

Exemple

Considérons N=199163

Étape 1

La plus petite valeur possible de est 40 , ce qui donne:k40

y=28232-40×199163=7969329-7966520=2809=532kN=(2823+53)

x=(40×199163)=2823
y=2823240×199163=79693297966520=2809=532
k N = 2876 × 2770
kN=(2823+53)×(2823-53)
kN=2876×2770

Étape 2

La factorisation correcte de est k = 4 × 10 , car:kk=4×10

k N = ( 719 × 4 ) ×

kN=2876×2770
kN=(719×4)×(277×10)
N=719×277

Donc, la bonne réponse serait soit [4,10][10,4]

Règles

  • uv
  • uvN
  • L'entrée est garantie comme un semi-premier.
  • Il s'agit de code-golf, donc la réponse la plus courte en octets l'emporte.
  • Les failles standard sont interdites.

Cas de test

N          | k    | Output
-----------+------+------------
143        | 1    | [   1,  1 ]
2519       | 19   | [   1, 19 ]
199163     | 40   | [   4, 10 ]
660713     | 1    | [   1,  1 ]
4690243    | 45   | [   9,  5 ]
11755703   | 80   | [  40,  2 ]
35021027   | 287  | [   7, 41 ]
75450611   | 429  | [ 143,  3 ]
806373439  | 176  | [   8, 22 ]
1355814601 | 561  | [  17, 33 ]
3626291857 | 77   | [   7, 11 ]
6149223463 | 255  | [  17, 15 ]
6330897721 | 3256 | [  74, 44 ]

Exemple d'implémentation

Dans l'extrait ci-dessous, la fonction est une implémentation non gérée qui prend NfNuv

gNuvNO(1)


Sommes-nous garantis que l'entrée Nsera en fait un semi-premier?
Greg Martin

@GregMartin Oui, vous l'êtes.
Arnauld du

Réponses:


8

Mathematica, 81 79 octets

Merci à Martin Ender pour avoir économisé 2 octets!

(c=Ceiling;For[j=0;z=E,c@z>z,p=(x=c@Sqrt[j+=#])+{z=Sqrt[x^2-j],-z}];p/#~GCD~p)&

Fonction pure prenant un semi-premier en entrée et renvoyant une paire ordonnée d'entiers positifs. La Forboucle implémente la procédure exacte décrite dans la question (en utilisant #pour l'entrée à la place de n), avec xcomme défini ici, bien que nous stockions à la j = k*nplace de klui-même et z=Sqrt[y]au lieu de ylui - même. Nous calculons également p={x+z,x-z}à l'intérieur de la Forboucle, ce qui finit par économiser un octet (comme pour le septième essai). Ensuite, les deux facteurs souhaités sont (x+z)/GCD[#,x+z]et (x-z)/GCD[#,x-z], que l'expression concise p/#~GCD~pcalcule directement comme une paire ordonnée.

Curiosités: nous voulons boucler jusqu'à ce que zsoit un entier; mais comme nous allons utiliser Ceilingdéjà dans le code, il économise deux octets de plus !IntegerQ@zà définir c=Ceiling(ce qui coûte quatre octets, comme le savent les golfeurs de Mathematica), puis teste si c@z>z. Nous devons initialiser zà quelque chose, et que quelque chose vaut mieux ne pas être un entier pour que la boucle puisse démarrer; heureusement, Ec'est un choix concis.


4

JavaScript (ES7), 86 81 octets

n=>(g=k=>(y=(n*k)**.5+1|0,y+=(y*y-n*k)**.5)%1?g(k+1):n*u++%y?g(k):[--u,k/u])(u=1)

Edit: 4 octets enregistrés grâce à @Arnauld.


4

Python 2, 127 121 117 117 111 107 104 101 99 octets

-1 octet grâce à Neil & -3 octets grâce à ovs

N=input()
k=u=1;p=m=.5
while p%1:p=1+(k*N)**m//1;p+=(p*p-k*N)**m;k+=1
while N*u%p:u+=1
print~-k/u,u

Essayez-le en ligne!

Curiosités:

pest initialisé à .5pour que la condition de boucle soit vraie à la première itération. Notez qu'il est plus court de stocker p(en tant que x+ sqrt(y)) que de stocker chacun xet yséparément.


x*xau lieu de x**2?
Neil

@Neil Oui, bien sûr. Merci
math junkie

1

Axiome, 131 115 octets

v(x)==floor(x^.5)::INT;r(n)==(k:=0;repeat(k:=k+1;x:=1+v(k*n);y:=v(x*x-k*n);x^2-y^2=k*n=>break);[w:=gcd(k,x+y),k/w])

La fonction qui résoudrait la question est r (n) ci-dessus. ungolf et test

vv(x)==floor(x^.5)::INT    

--(x-y)*(x+y)=k*n
rr(n)==
  k:=0
  repeat
     k:=k+1
     x:=1+vv(k*n)
     y:=vv(x*x-k*n)
     x^2-y^2=k*n=>break
  [w:=gcd(k,x+y),k/w]


(4) -> [[i,r(i)] for i in [143,2519,199163,660713,4690243,11755703]]
   (4)
   [[143,[1,1]], [2519,[1,19]], [199163,[4,10]], [660713,[1,1]],
    [4690243,[9,5]], [11755703,[40,2]]]
                                                      Type: List List Any
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.