Tugasnya adalah sebagai berikut: Diberikan bilangan bulat positif x
dan bilangan prima n > x
, menghasilkan bilangan bulat positif terkecil y
sehingga (y * y) mod n = x
. Bagian penting dari pertanyaan ini adalah batas waktu yang ditentukan di bawah ini yang tidak termasuk solusi brute force.
Jika tidak ada nilai seperti itu y
maka kode Anda akan ditampilkan N
.
Uji kasus
(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)
Masukan dan keluaran
Anda dapat mengambil input dan memberikan output dengan cara apa pun yang nyaman. Jika Anda tidak suka output N
maka Falsey
nilai apa pun akan dilakukan.
Batasan
Kode Anda harus menjawab semua kotak uji dalam waktu kurang dari 1 menit pada desktop standar. Batas waktu ini hanya untuk mencegah jawaban kasar dan saya berharap jawaban yang baik berjalan hampir secara instan. Anda tidak boleh menggunakan pustaka atau builtin apa pun yang memecahkan masalah ini atau yang menguji jika angka adalah residu kuadratik.
1267650600228229401496703205653
diri sendiri atau jika Anda memiliki dukungan 128 bit seperti__int128
di gcc. Ada juga sejumlah 256 bit int libraries di luar sana untuk berbagai bahasa. Terakhir, banyak bahasa memiliki perpustakaan int presisi yang sewenang-wenang.Jawaban:
Pyth,
8382 byteSuite uji
Program ini mengimplementasikan algoritma Tonelli-Shanks . Saya menulisnya dengan cermat mengikuti halaman Wikipedia. Dibutuhkan sebagai input
(n, p)
.Tidak adanya akar kuadrat dilaporkan oleh kesalahan berikut:
Ini adalah kode golf yang sangat rumit, ditulis dengan gaya imperatif, berbeda dengan gaya fungsional Pyth yang lebih umum.
Aspek halus Pyth yang saya gunakan adalah
=
, yang, jika tidak segera diikuti oleh variabel, mencari maju dalam program untuk variabel berikutnya, kemudian memberikan hasil dari ekspresi berikut untuk variabel itu, kemudian mengembalikan hasil itu. Saya akan merujuk seluruh penjelasan ke halaman wikipedia: Algoritma Tonelli-Shanks , karena itulah algoritma yang saya terapkan.Penjelasan:
A
mengambil 2-tuple sebagai input, dan memberikan nilai masingG
-H
masing, dan mengembalikan inputnya.Q
adalah input awal.e
mengembalikan elemen terakhir dari suatu urutan. Setelah cuplikan ini,G
adalahn
, danH
danQ
sedangp
.M
mendefinisikan fungsi input 2g
, di mana input beradaG
danH
..^
adalah fungsi eksponensial modular cepat Pyth. Cuplikan ini didefinisikang
sebagai mod eksponensialQ
.f
mendefinisikan pengulangan sampai false loop, dan mengembalikan jumlah iterasi yang dijalankannya, diberikan1
sebagai inputnya. Selama setiap iterasi loop, kami membaginyaH
dengan 2, setH
ke nilai itu, dan memeriksa apakah hasilnya aneh. Setelah itu, kita berhenti.K
menyimpan jumlah iterasi yang dibutuhkan.Satu hal yang sangat sulit adalah
=2;
bagiannya.=
mencari di depan untuk variabel berikutnya, yaituT
, jadiT
diatur ke 2. Namun,T
di dalamf
loop adalah penghitung iterasi, jadi kami gunakan;
untuk mendapatkan nilai dariT
lingkungan global. Ini dilakukan untuk menyimpan beberapa byte spasi putih yang jika tidak akan diperlukan untuk memisahkan angka.Setelah potongan ini,
K
adalahS
dari artikel wikipedia (wiki), danH
adalahQ
dari wiki, danT
ini2
.Sekarang, kita perlu menemukan mod nonresid kuadratik
p
. Kami akan memaksa ini menggunakan kriteria Euler./Q2
adalah(p-1)/2
, karena/
adalah divisi lantai, sehinggaftgT/Q;1
menemukan bilangan bulat pertama diT
manaT ^ ((p-1)/2) != 1
, seperti yang diinginkan. Ingat itu;
lagi menarikT
dari lingkungan global, yang masih 2. Hasil iniz
dari wiki.Selanjutnya, untuk membuat
c
dari wiki, kita perluz^Q
, jadi kita bungkus di atasg ... H
dan tetapkan hasilnyaT
. SekarangT
adalahc
dari wiki.Mari kita memisahkan ini:
~gGH
.~
seperti=
, tetapi mengembalikan nilai asli variabel, bukan nilai baru. Jadi, ia kembaliG
, yangn
dari wiki.Ini memberikan
J
nilain^((Q+1)/2)
, yaituR
dari wiki.Sekarang, yang berikut ini berlaku:
Ini memberikan
G
nilain^Q
, yang berasalt
dari wiki.Sekarang, kita telah mengatur variabel loop kami.
M, c, t, R
dari wiki adalahK, T, G, J
.Tubuh loop rumit, jadi saya akan menyajikannya dengan spasi putih, cara saya menulisnya:
Pertama, kita periksa apakah
G
1. Jika demikian, kita keluar dari loop.Kode berikutnya yang berjalan adalah:
Di sini, kami mencari nilai pertama
i
sedemikian rupaG^(2^i) mod Q = 1
, mulai dari 1. Hasilnya disimpanK
.Di sini, kita mengambil nilai lama
K
, kurangi nilai baruK
, kurangi 1, naikkan 2 ke daya itu, lalu naikkanT
ke mod daya ituQ
, lalu tetapkan hasilnyaT
. IniT
sama denganb
dari wiki.Ini juga merupakan garis yang mengakhiri loop dan gagal jika tidak ada solusi, karena dalam hal ini nilai baru
K
akan sama dengan nilai lamaK
, 2 akan dinaikkan ke-1
, dan eksponensial modular akan menimbulkan kesalahan.Selanjutnya, kita kalikan
J
dengan hasil di atas dan simpan kembaliJ
, tetapR
perbarui.Lalu kami menyiku
T
dan menyimpan hasilnya kembaliT
, mengaturT
kembali kec
dari wiki.Lalu kita kalikan
G
dengan hasil itu, ambil modnyaQ
dan simpan hasilnya kembaliG
.Dan kami mengakhiri loop.
Setelah loop selesai,
J
adalah akar kuadrat darin
modp
. Untuk menemukan yang terkecil, kami menggunakan kode berikut:_BJ
membuat daftarJ
dan negasinya,%
secara implisit mengambilQ
sebagai argumen kedua, dan menggunakan perilaku default Pyth untuk diterapkan% ... Q
ke setiap anggota urutan. KemudianS
mengurutkan daftar danh
mengambil anggota pertamanya, minimum.sumber
Python 2, 166 byte
sumber
%timeit Q(1267650600228229401496703204676,1267650600228229401496703205653) 100 loops, best of 3: 2.83 ms per loop
:)SageMath , 93 byte
Dengan mengurangi masalah yang jauh lebih sulit yang kebetulan SageMath memiliki builtin cukup cepat.
Cobalah di SageMathCell
sumber
Haskell , 326 byte
Biasanya saya suka jawaban brute force .. Karena ini sangat tidak disarankan oleh batas waktu, inilah cara paling efisien yang saya tahu:
Cobalah online!
Saya yakin ini bisa diturunkan lebih jauh, tetapi ini harus dilakukan untuk saat ini.
sumber
testCases
dengan yang dari TIO asli, itu hampir tidak cocok menjadi komentar bahkan tanpa mereka.testCases
.