Căn bậc hai một số


13

Nhiệm vụ như sau: Cho một số nguyên dương xvà một số nguyên tố n > x, xuất ra số nguyên dương nhỏ nhất ysao cho (y * y) mod n = x. Một phần quan trọng của câu hỏi này là giới hạn thời gian được chỉ định bên dưới, loại trừ các giải pháp vũ lực.

Nếu không có giá trị như vậy ythì mã của bạn sẽ xuất ra N.

Các trường hợp thử nghiệm

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

Đầu vào và đầu ra

Bạn có thể lấy đầu vào và đưa ra đầu ra theo bất kỳ cách nào thuận tiện. Nếu bạn không muốn đầu ra Nthì bất kỳ Falseygiá trị nào cũng được.

Những hạn chế

Mã của bạn phải trả lời tất cả các trường hợp thử nghiệm dưới 1 phút trên máy tính để bàn tiêu chuẩn. Giới hạn thời gian này chỉ để ngăn chặn các câu trả lời vũ phu và tôi mong đợi các câu trả lời tốt sẽ chạy gần như ngay lập tức. Bạn không được sử dụng bất kỳ thư viện hoặc nội dung nào giải quyết vấn đề này hoặc kiểm tra nếu một số là phần dư bậc hai.


2
Vì vậy, các ngôn ngữ không có hỗ trợ cho loại dữ liệu số nguyên lớn được loại trừ. Đáng tiếc
Luis Mendo

1
@LuisMendo Không phải nếu bạn có thể mã hóa hỗ trợ cho 1267650600228229401496703205653chính mình hoặc nếu bạn có hỗ trợ 128 bit, chẳng hạn như __int128trong gcc. Ngoài ra còn có một số thư viện int 256 bit cho các ngôn ngữ khác nhau. Cuối cùng, rất nhiều ngôn ngữ có một thư viện int chính xác tùy ý.

Câu trả lời:


7

Bình thường, 83 82 byte

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

Bộ kiểm tra

Chương trình này thực hiện thuật toán Tonelli-Shanks . Tôi đã viết nó bằng cách theo sát trang Wikipedia. Nó là đầu vào (n, p).

Sự vắng mặt của một căn bậc hai được báo cáo bởi lỗi sau:

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

Đây là mã golf rất phức tạp, được viết theo phong cách bắt buộc, trái ngược với phong cách chức năng phổ biến hơn của Pyth.

Một khía cạnh tinh tế của Pyth tôi đang sử dụng là =, nếu không ngay lập tức theo sau một biến, tìm kiếm chuyển tiếp trong chương trình cho biến tiếp theo, sau đó gán kết quả của biểu thức sau cho biến đó, sau đó trả về kết quả đó. Tôi sẽ tham khảo trong suốt phần giải thích cho trang wikipedia: Thuật toán Tonelli-Shanks , vì đó là thuật toán tôi đang thực hiện.

Giải trình:

=eAQ

Amất 2 tuple như đầu vào, và gán các giá trị để GHtương ứng, và trả về đầu vào của nó. Qlà đầu vào ban đầu. etrả về phần tử cuối cùng của chuỗi Sau đoạn này, Gn, và HQp.

M.^GHQ

Mđịnh nghĩa một hàm 2 đầu vào g, trong đó các đầu vào là GH. .^là chức năng lũy ​​thừa mô-đun nhanh của Pyth. Đoạn mã này định gnghĩa mod mod lũy thừa Q.

Kf%=/H=2;1

fđịnh nghĩa lặp lại cho đến khi vòng lặp sai và trả về số lần lặp mà nó chạy, được đưa ra 1làm đầu vào của nó. Trong mỗi lần lặp của vòng lặp, chúng tôi chia Hcho 2, đặt thành Hgiá trị đó và kiểm tra xem kết quả có phải là số lẻ hay không. Một khi nó được, chúng tôi dừng lại. Klưu trữ số lần lặp này mất.

Một điều rất khó khăn là =2;bit. =tìm kiếm trước cho biến tiếp theo, đó là T, do đó Tđược thiết lập để 2. Tuy nhiên, Tbên trong một fvòng lặp là lặp truy cập, vì vậy chúng tôi sử dụng ;để có được giá trị của Ttừ môi trường toàn cầu. Điều này được thực hiện để lưu một vài byte khoảng trắng cần thiết để tách các số.

Sau đoạn này, KStừ bài viết wikipedia (wiki), và HQtừ wiki, và T2.

=gftgT/Q;1H

Bây giờ, chúng ta cần tìm một mod nonresidue bậc hai p. Chúng tôi sẽ vũ phu điều này bằng cách sử dụng tiêu chí Euler. /Q2(p-1)/2, vì /là phân chia thả nổi, vì vậy ftgT/Q;1tìm số nguyên đầu tiên Tở đâu T ^ ((p-1)/2) != 1, như mong muốn. Nhớ lại rằng ;một lần nữa kéo Ttừ môi trường toàn cầu, vẫn là 2. Kết quả này là ztừ wiki.

Tiếp theo, để tạo ctừ wiki, chúng tôi cần z^Q, vì vậy chúng tôi gói phần trên g ... Hvà gán kết quả cho T. Bây giờ Tctừ wiki.

Jg~gGHh/H2

Chúng ta hãy tách ra điều này : ~gGH. ~giống như =, nhưng trả về giá trị ban đầu của biến, không phải giá trị mới của nó. Vì vậy, nó trả về G, đó là ntừ wiki.

Điều này gán Jgiá trị của n^((Q+1)/2), là Rtừ wiki.

Bây giờ, những điều sau đây có hiệu lực:

~gGH

Điều này gán Ggiá trị n^Q, là ttừ wiki.

Bây giờ, chúng ta có các biến vòng lặp được thiết lập. M, c, t, Rtừ wiki là K, T, G, J.

Phần thân của vòng lặp rất phức tạp, vì vậy tôi sẽ trình bày nó với khoảng trắng, như cách tôi đã viết:

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

Đầu tiên, chúng tôi kiểm tra xem có phải Glà 1. Nếu vậy, chúng tôi thoát khỏi vòng lặp.

Mã tiếp theo chạy là:

=Kfq1gG^2T1

Ở đây, chúng tôi tìm kiếm giá trị đầu tiên inhư vậy G^(2^i) mod Q = 1, bắt đầu từ 1. Kết quả được lưu vào K.

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

Ở đây, chúng ta lấy giá trị cũ của K, trừ đi giá trị mới của K, trừ 1, tăng 2 lên lũy thừa đó, rồi nâng Tlên mod công suất đó Q, rồi gán kết quả cho T. Điều này làm cho Tbằng với bwiki.

Đây cũng là dòng kết thúc vòng lặp và thất bại nếu không có giải pháp, bởi vì trong trường hợp đó, giá trị mới Ksẽ bằng giá trị cũ của K, 2 sẽ được nâng lên -1và lũy thừa mô-đun sẽ gây ra lỗi.

=*J

Tiếp theo, chúng tôi nhân Jvới kết quả trên và lưu trữ lại J, tiếp tục Rcập nhật.

=^T2

Sau đó, chúng tôi vuông Tvà lưu trữ kết quả trở lại T, thiết lập Tlại ctừ wiki.

=%*G=^T2Q

Sau đó, chúng tôi nhân Gvới kết quả đó, lấy mod Qvà lưu lại kết quả G.

;

Và chúng tôi chấm dứt vòng lặp.

Sau khi vòng lặp kết thúc, Jlà một căn bậc hai của nmod p. Để tìm cái nhỏ nhất, chúng tôi sử dụng mã sau:

hS%_BJ

_BJtạo danh sách Jvà phủ định của nó, %mặc nhiên lấy Qlàm đối số thứ hai của nó và sử dụng hành vi mặc định của Pyth để áp dụng % ... Qcho từng thành viên của chuỗi. Sau đó Ssắp xếp danh sách và hlấy thành viên đầu tiên của nó, mức tối thiểu.


11

Python 2, 166 byte

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
Thật là một câu trả lời tuyệt vời! Bạn đã khôi phục niềm tin của tôi vào PPCG.

5
Xin hỏi câu hỏi của người mới, nhưng PPCG là gì? Tập đoàn Python Coders Ba Lan?
Kỹ sư đảo ngược

@DaveBoltman Lập trình Câu đố & Code Golf.
orlp


3

Haskell , 326 byte

Thông thường tôi thích câu trả lời vũ phu .. Vì điều này bị hạn chế mạnh mẽ bởi giới hạn thời gian, đây là cách hiệu quả nhất mà tôi biết:

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)

Hãy thử trực tuyến!

Tôi chắc chắn rằng điều này có thể được chơi golf hơn nữa, nhưng điều này nên làm ngay bây giờ.


Bạn có thể sửa đổi mã TIO để nó đưa ra câu trả lời là đầu ra không? Tôi chỉ nhận được "Đúng" vào lúc này.


@Lembik Bạn cần thay thế testCasesbằng những người từ TIO ban đầu, nó hầu như không phù hợp với một nhận xét ngay cả khi không có họ.
Ørjan Johansen

@ RjanJohansen Cảm ơn rất nhiều! Tôi điều chỉnh câu trả lời của tôi với mã của bạn và thay thế testCases.
ბიმო

Huh, tôi thấy một lỗi kỳ lạ với liên kết TIO đó - nếu tôi nhấp vào nó có mã nhưng không chạy cũng không nhận được URL từ các tùy chọn menu hoạt động - nhưng nếu tôi sao chép URL từ thanh địa chỉ và dán nó vào tab khác nhau, sau đó nó hoạt động.
Ørjan Johansen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.