Fermat의 인수 분해 도우미


19

semiprime 을 인수 분해하고 싶습니다 . 이 과제의 목표는 두 개의 작은 정수를 찾을 수 있습니다 U를 하고 v에 그런 v에 N이 이렇게 쉽게의 요인을 공제 할 수 하찮게 페르마의 방법으로 인수 분해 될 수 없음을 .NuvuvNN

작업

세미 프라임 과 양의 정수 k가 주어지면 xy 를 다음 과 같이 정의합니다 .Nkxy

y=x2kN

x=kN
y=x2kN

1 단계 -k 찾기k

y정사각형 숫자 ( 일명 완벽한 정사각형) 가 되도록 가능한 가장 작은 값을 찾아야합니다 .ky

이를 통해 Fermat의 인수 분해 방법을 단일 반복하여 을 인수 분해 할 수 있습니다 . 보다 구체적으로, 이것은 즉시 다음으로 이어집니다.kN

kN=(x+y)×(xy)

(업데이트 :이 시퀀스는 이제 A316780으로 게시됩니다 )

2 단계 -k를 분해k

그런 다음 두 개의 양의 정수 v 를 찾아야합니다 .uv

c u = x +

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

여기서 dN 의 주요 요소입니다 .cdN

요약

너의 임무는 을 입력으로 취하고 uv 를 임의의 순서와 합리적인 형식으로 인쇄하거나 출력 하는 프로그램이나 함수를 작성하는 것입니다.Nuv

N = 199163을 고려하자N=199163

1 단계

의 가장 작은 가능한 값 은 40입니다 .k40

Y=2,8232-40×199,163=7,969,329-7,966,520=2,809=532KN=(2823+53)×(2823-53)k는N=2,876×2,770

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

2 단계

분해의 정확한 K = 4 × 10 때문 :kk=4×10

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

[4,10][10,4]

규칙

  • uv
  • uvN
  • 입력은 세미 프라임이어야합니다.
  • 이것은 코드 골프이므로 바이트 단위의 최단 답변이 이깁니다.
  • 표준 허점은 금지되어 있습니다.

테스트 사례

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 ]

구현 예

fNuv

gNuvNO(1)


입력 N이 실제로 세미 프라임 일 것이라는 보장이 있습니까?
Greg Martin

@GregMartin 그렇습니다.
Arnauld

답변:


8

수학, 81 79 바이트

2 바이트를 절약 한 Martin Ender에게 감사합니다!

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

세미 프라임을 입력으로 취하고 순서가 지정된 양의 정수 쌍을 리턴하는 순수 함수. For정확한 절차 (하여 질문에 기재된 루프를 구현하는 #대신에, 입력 n으로) x매장 있지만,이 정의 j = k*n대신 k자체 z=Sqrt[y]대신 y자체. 또한 루프 p={x+z,x-z}내부 를 계산 For하여 7 바이트와 같이 1 바이트를 절약합니다. 그런 다음 두 가지 바람직한 요소는 (x+z)/GCD[#,x+z]and (x-z)/GCD[#,x-z]이며 간결한 표현식 p/#~GCD~p은 순서 쌍으로 직접 계산됩니다.

호기심 : 우리 z는 정수가 될 때까지 반복하고 싶습니다 . 그러나 우리는 Ceiling이미 코드에서 사용할 것이기 때문에 2 바이트를 저장 !IntegerQ@z하여 정의합니다 c=Ceiling(Mathematica 골퍼가 알고 있듯이 4 바이트 비용) c@z>z. 우리는 z무언가 로 초기화 해야하며, 루프가 시작될 수 있도록 무언가가 정수가 아니 어야합니다 . 다행히도 E간결한 선택입니다.


4

자바 스크립트 (ES7), 86 81 바이트

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)

편집 : @Arnauld 덕분에 4 바이트가 절약되었습니다.


4

파이썬 2 127 121 117 111 107 104 101 99 바이트

Neil 덕분에 -1 바이트, ovs 덕분에 -3 바이트

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

온라인으로 사용해보십시오!

호기심 :

p.5루프 조건이 첫 번째 반복에서 참이되도록 로 초기화됩니다 . 참고가 저장소 짧다고 p(AS x+ sqrt(y)는 각각 저장하기보다는) xy별도로.


x*x대신에 x**2?
Neil

@ 닐 물론입니다. 감사합니다
math junkie

1

공리, 131 115 바이트

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

문제를 해결하는 함수는 위의 r (n)입니다. 풀고 테스트

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.