Fermats Faktorisierungshelfer


19

Wir möchten ein Semiprime faktorisieren . Das Ziel dieser Herausforderung ist es, zwei kleine ganze Zahlen und v zu finden, so dass uvN mit der Methode von Fermat trivial faktorisiert werden kann, wodurch die Faktoren von N leicht abgeleitet werden können .u v u v N NNuvuvNN

Die Aufgabe

Ausgehend von einem Halbwert N und einer positiven ganzen Zahl k definieren wir x und y als:

y=x2-kN

x=kN
y=x2kN

Schritt # 1 - Finden Sie k

Sie müssen zuerst den kleinstmöglichen Wert von k , sodass y eine quadratische Zahl ist (auch als perfektes Quadrat bezeichnet).

Dies ermöglicht die Faktorisierung von mit einer einzigen Iteration der Fermat-Faktorisierungsmethode . Konkret führt dies sofort zu:kN

kN=(x+y)×(xy)

(Update: Diese Sequenz ist jetzt als A316780 veröffentlicht )

Schritt # 2 - Faktorisierek

Sie müssen dann die beiden positiven ganzen Zahlen und so finden, dass:vuv

c u = x +

uv=k
dv=x-
cu=x+y
dv=xy

wobei und die Primfaktoren von .d NcdN

Zusammenfassung

Ihre Aufgabe ist es, ein Programm oder eine Funktion zu schreiben, die als Eingabe verwendet und und in beliebiger Reihenfolge und in einem angemessenen Format ausgibt oder ausgibt .u vNuv

Beispiel

Betrachten wirN=199163

Schritt 1

Der kleinstmögliche Wert von ist , was ergibt:40k40

y=28232-40×199.163=7.969.329-7,96652 Millionen=2809=532kN=(2823+53)×(2823-53)

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

Schritt 2

Die korrekte Faktorisierung von ist , weil:k = 4 × 10kk=4×10

k N = ( 719 × 4 ) × ( 277 × 10 ) N = 719 × 277

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

Die richtige Antwort wäre also entweder oder .[ 10 , 4 ][4,10][10,4]

Regeln

  • Es ist nicht erforderlich, die beiden oben beschriebenen Schritte strikt anzuwenden. Es steht Ihnen frei, eine andere Methode zu verwenden, solange die korrekten Werte für und .vuv
  • Sie müssen alle Werte von bis zur nativen Maximalgröße einer vorzeichenlosen Ganzzahl in Ihrer Sprache unterstützen.uvN
  • Der Eingang ist garantiert ein Halbbild.
  • Das ist Code-Golf, also gewinnt die kürzeste Antwort in Bytes.
  • Standardlücken sind verboten.

Testfälle

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 ]

Beispielimplementierung

fNuv

GNuvNO(1)


Sind wir Nsicher, dass der Input tatsächlich ein Semiprime sein wird?
Greg Martin

@ GregMartin Ja, das bist du.
Arnauld

Antworten:


8

Mathematica, 81 79 Bytes

Vielen Dank an Martin Ender für das Speichern von 2 Bytes!

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

Reine Funktion, die ein Semiprime als Eingabe verwendet und ein geordnetes Paar positiver Ganzzahlen zurückgibt. Die ForSchleife implementiert die genaue Prozedur, die in der Frage (unter Verwendung #für die Eingabe anstelle von n) beschrieben ist, mit xder dort definierten, obwohl wir j = k*nanstelle von sich kselbst und z=Sqrt[y]anstelle von sich yselbst speichern . Wir berechnen auch p={x+z,x-z}innerhalb der ForSchleife, wodurch am Ende ein Byte gespart wird (wie beim siebten Versuch). Dann sind die beiden gewünschten Faktoren (x+z)/GCD[#,x+z]und (x-z)/GCD[#,x-z], die der prägnante Ausdruck p/#~GCD~pdirekt als geordnetes Paar berechnet.

Kurioses: Wir wollen eine Schleife machen, bis zeine ganze Zahl ist. Da wir aber Ceilingbereits im Code verwenden werden, werden zwei Bytes gespart, um !IntegerQ@zzu definieren c=Ceiling(was, wie Mathematica-Golfer wissen, vier Bytes kostet) und dann zu testen, ob c@z>z. Wir müssen zetwas initialisieren , und dieses etwas sollte besser keine ganze Zahl sein, damit die Schleife beginnen kann; Zum Glück Eist eine prägnante Wahl.


4

JavaScript (ES7), 86 81 Bytes

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)

Bearbeiten: 4 Bytes dank @Arnauld gespeichert.


4

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

-1 Byte dank Neil & -3 Byte dank 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

Probieren Sie es online!

Kuriositäten:

pwird so initialisiert, .5dass die Schleifenbedingung bei der ersten Iteration wahr ist. Beachten Sie, dass das Speichern p(als x+ sqrt(y)) kürzer ist als das Speichern der einzelnen xund ygetrennt.


x*xstatt x**2?
Neil

@ Neil Ja, natürlich. Vielen Dank
Math Junkie

1

Axiom, 131 115 Bytes

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])

Die Funktion, die die Frage lösen würde, ist r (n) oben. ungolf und 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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.