제곱근


13

다음과 같은 작업은 다음과 양의 정수 주어 x와 주요 n > x작은 양의 정수 출력, y그러한 (y * y) mod n = x. 이 질문의 중요한 부분은 무차별 대입 솔루션을 제외하고 아래에 지정된 시간 제한입니다.

그러한 값이 없으면 y코드가 출력되어야합니다 N.

테스트 사례

(2, 5, N), 
(3, 5, N), 
(4, 5, 2),
(524291, 1048583, N),
(529533, 1048583, N),
(534775, 1048583, 436853),
(540017, 1048583, 73675),
(536870913, 1073741827, 375394238),
(542239622, 1073741827, 267746399),
(547608331, 1073741827, N),
(552977040, 1073741827, 104595351),
(1099511627676, 1099511627791, N),
(1099511627677, 1099511627791, 269691261521),
(1099511627678, 1099511627791, 413834069585),
(1267650600228229401496703204376, 1267650600228229401496703205653, 5312823546347991512233563776),
(1267650600228229401496703204476, 1267650600228229401496703205653, N)
(1267650600228229401496703204576, 1267650600228229401496703205653, N)
(1267650600228229401496703204676, 1267650600228229401496703205653, 79905476259539917812907012931)

입력과 출력

편리한 방법으로 입력하고 출력 할 수 있습니다. 당신이 출력하고 싶지 않다면 N어떤 Falsey값 이든 할 것입니다.

제한 사항

코드는 표준 데스크톱에서 1 분 이내에 모든 테스트 사례에 응답해야합니다. 이 시간 제한은 무차별 대입 답변을 막기위한 것이며 좋은 답변이 거의 즉시 실행될 것으로 기대합니다. 이 문제를 해결하거나 숫자가 2 차 잔차인지 테스트하는 라이브러리 나 내장을 사용할 수 없습니다.


2
따라서 큰 정수 데이터 유형을 지원하지 않는 언어는 제외됩니다. 동정
Luis Mendo

1
@LuisMendo 1267650600228229401496703205653자신에 대한 지원을 코딩 할 수 있거나 __int128gcc 와 같은 128 비트 지원이있는 경우에는 아닙니다 . 다양한 언어를위한 256 비트 int 라이브러리도 많이 있습니다. 마지막으로, 많은 언어는 임의의 정밀도 int 라이브러리를 가지고 있습니다.

답변:


7

Pyth, 83 82 바이트

=eAQM.^GHQKf%=/H=2;1=gftgT/Q;1HJg~gGHh/H2WtG=*J=gT^2t-K=Kfq1gG^2T1=%*G=^T2Q;hS%_BJ

테스트 스위트

이 프로그램은 Tonelli-Shanks 알고리즘을 구현합니다 . 나는 Wikipedia 페이지를 꼼꼼히 따랐다. 입력으로 사용 (n, p)됩니다.

제곱근이 없으면 다음 오류로보고됩니다.

TypeError: pow() 3rd argument not allowed unless all arguments are integers

이것은 Pyth의보다 일반적인 기능적 스타일과 달리 명령형으로 작성된 매우 복잡한 코드입니다.

내가 사용 =하고있는 Pyth의 미묘한 측면은 바로 다음에 변수가 나오지 않으면 프로그램에서 다음 변수를 검색 한 다음 다음 표현식의 결과를 해당 변수에 할당 한 다음 결과를 반환합니다. 설명을 통해 Wikipedia 페이지 인 Tonelli-Shanks algorithm 을 참조 할 것입니다. 이것이 구현중인 알고리즘입니다.

설명:

=eAQ

A입력으로서 2- 터플을 취하고,에 값을 할당 G하고 H, 각각, 그 입력을 반환한다. Q초기 입력입니다. e시퀀스의 마지막 요소를 반환합니다. 이 스 니펫 다음 G은 is nHand Q입니다 p.

M.^GHQ

Mg입력이 G및 인 2 입력 함수를 정의합니다 H. .^Pyth의 빠른 모듈 식 지수 함수입니다. 이 스 니펫은 g지수 모드를 의미하도록 정의 합니다 Q.

Kf%=/H=2;1

ffalse 루프까지 반복을 정의 1하고 입력으로 지정된 반복 횟수를 리턴합니다 . 루프가 반복 될 때마다 H2로 나누고 H그 값으로 설정 한 후 결과가 홀수인지 확인합니다. 일단 끝나면 우리는 멈 춥니 다.K이 반복 횟수를 저장합니다.

매우 까다로운 것은 =2;비트입니다. =다음 변수 인을 검색합니다. 즉 T, T2로 설정됩니다. 그러나 루프 T내부 f에는 반복 카운터가 있으므로 전역 환경에서 ;값을 가져 오는 데 사용 T합니다. 이것은 숫자를 분리하는 데 필요한 몇 바이트의 공백을 저장하기 위해 수행됩니다.

이 조각 한 후, KS위키 피 디아 기사 (위키)에서하고 H있다 Q위키에서하고 T있습니다 2.

=gftgT/Q;1H

이제 2 차 비 잔류 모드를 찾아야합니다 p. Euler 기준을 사용하여 이것을 무차별 적용 할 것입니다. /Q2이다 (p-1)/2때문에, /바닥의 분할이며, 그래서 ftgT/Q;1제 정수 찾으면 원하는를. 리콜 다시 끌어 여전히이 결과 2 인 글로벌 환경에서는 위키에서.TT ^ ((p-1)/2) != 1;Tz

다음으로 c위키에서 생성 하려면을 필요 z^Q로하므로 위의 내용을 감싸서 g ... H결과를에 할당합니다 T. 이제 T입니다 c위키에서.

Jg~gGHh/H2

이것을 분리하자 : ~gGH. ~=같지만 새 값이 아닌 변수의 원래 값을 반환합니다. 따라서을 반환합니다 G.n 위키에서.

이 할당 J의 값 n^((Q+1)/2)이며, R위키에서합니다.

이제 다음이 적용됩니다.

~gGH

이 할당 Gn^Q이며, t위키에서합니다.

이제 루프 변수가 설정되었습니다. M, c, t, R위키에서 K, T, G, J입니다.

루프의 몸체는 복잡하므로 공백을 쓴 방식으로 제시합니다.

WtG
  =*J
    =
      gT^2
        t-
          K
          =Kfq1gG^2T1
  =%*G=^T2Q;

먼저 1인지 확인합니다 G. 그렇다면 루프를 종료합니다.

다음으로 실행되는 코드는 다음과 같습니다.

=Kfq1gG^2T1

여기, 우리의 첫 번째 값을 검색 i등 그 G^(2^i) mod Q = 1결과는 저장 1.부터 시작 K.

=gT^2t-K=Kfq1gG^2T1

여기서 우리는 이전 값인 K, 새로운 값 K빼기, 1 빼기, 2를 그 거듭 제곱으로 올린 다음 T그 거듭 제곱 모드 로 올린 Q다음 결과를에 할당합니다 T. 이것은 위키와 T동일합니다 b.

또한이 경우에 새로운 값이 있기 때문에, 루프를 종료하고, 솔루션이 없을 경우 실패 라인 K의 이전 값과 같아야한다 K받는 발생한다 (2), -1및 모듈러 지수화는 에러를 발생한다.

=*J

다음으로, 우리는 다중 J위의 결과에 의해 다음 다시 보관 J유지, R업데이트되었습니다.

=^T2

그런 다음 Wiki에서 다시 설정 T하여 결과를 정사각형 으로 저장합니다 .TTc

=%*G=^T2Q

그런 다음 G그 결과를 곱하고 mod를 가져 와서 Q결과를 다시 저장합니다 G.

;

그리고 우리는 루프를 종료합니다.

루프가 끝나면 mod의 J제곱근입니다 . 가장 작은 것을 찾으려면 다음 코드를 사용하십시오.np

hS%_BJ

_BJ목록 J과 해당 부정을 작성하고 %내재적 Q으로 두 번째 인수로 사용하며 Pyth의 기본 동작을 사용 % ... Q하여 시퀀스의 각 구성원에 적용 합니다. 그런 다음 S목록을 정렬 h하고 첫 번째 구성원 인 최소값을 가져옵니다.


11

파이썬 2, 166 바이트

def Q(x,n,a=0):
 e=n/2
 while pow(a*a-x,e,n)<2:a+=1
 w=a*a-x;b=r=a;c=s=1
 while e:
    if e%2:r,s=(r*b+s*c*w)%n,r*c+s*b
    b,c=(b*b+c*c*w)%n,2*b*c;e/=2
 return min(r,-r%n)

%timeit Q(1267650600228229401496703204676,1267650600228229401496703205653) 100 loops, best of 3: 2.83 ms per loop :)

3
정말 좋은 답변입니다! PPCG에 대한 나의 믿음을 회복했습니다.

5
초보자 질문을 실례하지만 PPCG는 무엇입니까? 폴란드어 파이썬 코더 그룹?
리버스 엔지니어

@DaveBoltman 프로그래밍 퍼즐 및 코드 골프.
orlp


3

하스켈 , 326 바이트

일반적으로 나는 무차별 대항 답변을 좋아한다. 이것은 시간 제한에 의해 강력히 권장되지 않기 때문에 내가 아는 가장 효율적인 방법은 다음과 같다.

r p=((\r->min(mod(-r)p)r)$).f p
f p x|p==2=x|q x=f 0 0|mod p 4==3=x&div(p+1)4|let(r,s)=foldl i(p-1,0)[1..t 1o]=m$x&(d$r+1)*(b&d s)where q a=1/=a&o;m=(`mod`p);a&0=1;a&e|even e=m$a&d e^2|0<1=m$(a&(e-1))*a;b=[n|n<-[2..],q n]!!0;i(a,b)_|m(x&d a*b&d b)==p-1=(d a,d b+o)|0<1=(d a,d b);o=d p;t y x|even x=t(y+1)(d x)|0<1=y;d=(`div`2)

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

나는 이것이 더 골프화 될 수 있다고 확신하지만, 지금은 그렇게해야합니다.


출력으로 답변을 제공하도록 TIO 코드를 수정할 수 있습니까? 나는 단지 지금 "참"을 얻는다.


@Lembik 당신 testCases은 원래 TIO의 것들 로 교체해야하며 , 그것들이 없어도 주석에 거의 맞지 않습니다.
Ørjan Johansen

@ ØrjanJohansen 감사합니다! 귀하의 코드로 답변을 조정하고 교체했습니다 testCases.
ბიმო

허, 그 TIO 링크에 이상한 버그가 있습니다. 클릭하면 코드가 있지만 실행 중이거나 메뉴 옵션에서 URL을 가져 오는 것은 작동하지 않습니다. 그러나 주소 표시 줄에서 URL을 복사하여 붙여 넣으면 다른 탭을 사용하면 작동합니다.
Ørjan Johansen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.