Pomocnik Fermata w procesie faktoryzacji


19

Chcielibyśmy czynniki pierwsze Liczba Półpierwsza . Celem wyzwania jest znajdują się dwa małe liczby całkowite u i v , tak że u v N można trywialny factorized metodą Fermata, co pozwala na łatwe odliczać czynniki N .NuvuvNN

Zadanie

Biorąc pod uwagę Liczba Półpierwsza i dodatnią liczbą całkowitą k określamy X i Y jako:Nkxy

y=x2-kN

x=kN
y=x2kN

Krok # 1 - Znajdź k

Najpierw musisz znaleźć najmniejszą możliwą wartość tak że y jest liczbą kwadratową ( czyli kwadrat idealny).ky

Pozwala to na czynniki z pojedynczej iteracji Algorytm Fermata . Mówiąc konkretniej, prowadzi to natychmiast do:kN

kN=(x+y)×(xy)

(Aktualizacja: ta sekwencja jest teraz opublikowana jako A316780 )

Krok # 2 - Faktoryzuj k

Następnie musisz znaleźć dwie dodatnie liczby całkowite i v takie, że:uv

c u = x +

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

gdzie i d są głównymi czynnikami N .cdN

streszczenie

Twoim zadaniem jest napisanie programu lub funkcji, która przyjmuje jako dane wejściowe i drukuje lub wyjściowe u i v w dowolnej kolejności i dowolnym rozsądnym formacie.Nuv

Przykład

Rozważmy N=199163

Krok 1

Najmniejsza możliwa wartość wynosi 40 , co daje:k40

r=2.8232-40x199163=7969329-7966520=2809=532KN=(2823+53)x(2823-53)kN=2876x2770

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

Krok 2

Prawidłowa faktoryzacja wynosi k = 4 × 10 , ponieważ:kk=4×10

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

[4,10][10,4]

Zasady

  • uv
  • uvN
  • Dane wejściowe są gwarantowane jako półpierwsze.
  • To jest golf golfowy, więc wygrywa najkrótsza odpowiedź w bajtach.
  • Standardowe luki są zabronione.

Przypadki testowe

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 ]

Przykładowa implementacja

fNuv

gNuvNO(1)


Czy mamy gwarancję, że dane wejściowe Nbędą w rzeczywistości półpierwszymi?
Greg Martin

@GregMartin Tak, jesteś.
Arnauld

Odpowiedzi:


8

Mathematica, 81 79 bajtów

Dzięki Martin Ender za oszczędność 2 bajtów!

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

Czysta funkcja przyjmująca półpierwsze jako dane wejściowe i zwracająca uporządkowaną parę dodatnich liczb całkowitych. Te Fornarzędzia pętla dokładna procedura opisana w pytaniu (przy użyciu #do wprowadzania w miejscu n), z x, jak tu zdefiniowana, mimo że przechowywanie j = k*nzamiast ksiebie i z=Sqrt[y]zamiast ysiebie. Obliczamy również p={x+z,x-z}wewnątrz Forpętli, co kończy się oszczędzaniem jednego bajtu (jak przy siódmej próbie). Następnie dwoma pożądanymi czynnikami są (x+z)/GCD[#,x+z]i (x-z)/GCD[#,x-z], które zwięzłe wyrażenie p/#~GCD~poblicza bezpośrednio jako parę uporządkowaną.

Ciekawostki: chcemy zapętlać, aż zbędzie liczbą całkowitą; ale ponieważ zamierzamy użyć Ceilingjuż w kodzie, oszczędza dwa bajty, !IntegerQ@zaby zdefiniować c=Ceiling(co kosztuje cztery bajty, jak wiedzą golfiści Mathematica), a następnie przetestować, czy c@z>z. Musimy zcoś zainicjować i że coś nie powinno być liczbą całkowitą, aby pętla mogła się rozpocząć; na szczęście Ejest to zwięzły wybór.


4

JavaScript (ES7), 86 81 bajtów

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)

Edycja: Zapisano 4 bajty dzięki @Arnauld.


4

Python 2, 127 121 117 111 107 104 101 99 bajtów

-1 bajt dzięki Neilowi ​​i -3 bajty dzięki 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

Wypróbuj online!

Ciekawostki:

pjest inicjalizowany, aby .5warunek pętli był spełniony przy pierwszej iteracji. Należy pamiętać, że jest on krótszy do sklepu p(jako x+ sqrt(y)), niż jest do przechowywania każdego xi yoddzielnie.


x*xzamiast x**2?
Neil

@Neil Tak, oczywiście. Dzięki
ćpun matematyki

1

Aksjomat, 131 115 bajtów

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

Funkcja, która rozwiązałaby pytanie, to r (n) powyżej. golf i 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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.