L'aiutante della fattorizzazione di Fermat


19

Vorremmo fattorizzare un semiprimo . L'obiettivo di questa sfida è quella di trovare due piccoli interi e tali che può essere banalmente fattorizzata con il metodo di Fermat, consentendo in tal modo di dedurre facilmente i fattori di .u v u v N NNuvuvNN

L'obiettivo

Dato un semiprimi e un intero positivo , definiamo ed come:k x yNkxy

y=x2-kN

x=kN
y=x2kN

Passaggio n. 1: trovak

Devi prima trovare il valore più piccolo possibile di modo che sia un numero quadrato ( aka quadrato perfetto).yky

Ciò consente di fattorizzare con una singola iterazione del metodo di fattorizzazione di Fermat . Più concretamente, questo porta immediatamente a:kN

kN=(x+y)×(xy)

(Aggiornamento: questa sequenza è ora pubblicata come A316780 )

Step # 2 - Fattorizzak

Devi quindi trovare i due numeri interi positivi e tali che:vuv

c u = x +

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

dove e sono i fattori primi di .d NcdN

Sommario

Il vostro compito è quello di scrivere un programma o funzione che prende come input e stampe o uscite e in qualsiasi ordine e qualsiasi formato ragionevole.u vNuv

Esempio

ConsideriamoN=199163

Passo 1

Il valore più piccolo possibile di è , che dà:40k40

y=2.8232-40×199.163=7969,329 mila-7,96652 milione=2809=532kN=(2823+53)×(2823-53)kN=2876×2770

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

Passo 2

La fattorizzazione corretta di è k = 4 \ volte 10 , perché: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

Quindi, la risposta corretta sarebbe o .[ 10 , 4 ][4,10][10,4]

Regole

  • Non è necessario applicare rigorosamente i due passaggi sopra descritti. Sei libero di usare qualsiasi altro metodo, purché trovi i valori corretti di e .vuv
  • Devi supportare tutti i valori di fino alla dimensione massima nativa di un numero intero senza segno nella tua lingua.uvN
  • L'input è garantito per essere un semiprime.
  • Questo è code-golf, quindi vince la risposta più breve in byte.
  • Sono vietate le scappatoie standard.

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

Esempio di implementazione

Nello snippet di seguito, la funzione è un'implementazione non golfata che accetta come input e restituisce e .N u vfNuv

Solo a scopo illustrativo, lo snippet include anche la funzione che accetta , e come input e calcola i fattori di in .N u v N O ( 1 )gNuvNO(1)


Siamo garantiti che l'ingresso Nsarà di fatto un semiprime?
Greg Martin,

@GregMartin Sì, lo sei.
Arnauld,

Risposte:


8

Mathematica, 81 79 byte

Grazie a Martin Ender per aver salvato 2 byte!

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

Funzione pura che prende un semiprime come input e restituisce una coppia ordinata di numeri interi positivi. Il Forciclo implementa la procedura esatta descritta nella domanda (usando #per l'input al posto di n), con xcome definito lì, sebbene memorizziamo j = k*ninvece di kse stesso e z=Sqrt[y]invece di yse stesso. Calcoliamo anche p={x+z,x-z}all'interno del Forciclo, che finisce per salvare un byte (su come il settimo tentativo). Quindi i due fattori desiderati sono (x+z)/GCD[#,x+z]e (x-z)/GCD[#,x-z], che l'espressione concisa p/#~GCD~pcalcola direttamente come coppia ordinata.

Curiosità: vogliamo fare un ciclo fino a quando non zè un numero intero; ma dal momento che useremo Ceilinggià nel codice, salva due byte !IntegerQ@zper definire c=Ceiling(che costa quattro byte, come sanno i golfisti di Mathematica) e quindi verifica se c@z>z. Dobbiamo inizializzarci za qualcosa e che qualcosa non dovrebbe essere un numero intero in modo che il ciclo possa iniziare; fortunatamente, Eè una scelta concisa.


4

JavaScript (ES7), 86 81 byte

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)

Modifica: salvato 4 byte grazie a @Arnauld.


4

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

-1 byte grazie a Neil e -3 byte grazie a 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

Provalo online!

curiosità:

pviene inizializzato in .5modo tale che la condizione del loop sia vera alla prima iterazione. Si noti che è più breve per memorizzare p(come x+ sqrt(y)) che per memorizzare ciascuno di xe yseparatamente.


x*xinvece di x**2?
Neil,

@Neil Sì, certo. Grazie
drogato di matematica il

1

Assioma, 131 115 byte

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 funzione che risolverebbe la domanda è r (n) sopra. ungolf e prova

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
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.