The Chinese Remainder Theorem memberitahu kita bahwa kita selalu dapat menemukan sejumlah yang menghasilkan setiap sisanya diperlukan bawah modulus prima yang berbeda. Tujuan Anda adalah menulis kode untuk menghasilkan angka seperti itu dalam waktu polinomial. Kode terpendek menang.
Misalnya, kita diberi batasan ini ( %
mewakili mod):
n % 7 == 2
n % 5 == 4
n % 11 == 0
Salah satu solusinya adalah n=44
. Batasan pertama dipenuhi karena 44 = 6*7 + 2
, dan 44
masih ada 2
ketika dibagi oleh 7
, dan dengan demikian 44 % 7 == 2
. Dua kendala lainnya terpenuhi juga. Ada solusi lain, seperti n=814
dan n=-341
.
Memasukkan
Daftar pasangan yang tidak kosong (p_i,a_i)
, di mana setiap modulus p_i
adalah bilangan prima yang berbeda dan setiap target a_i
adalah bilangan alami dalam kisaran 0 <= a_i < p_i
. Anda dapat mengambil input dalam bentuk apa pun yang nyaman; itu tidak harus benar-benar menjadi daftar pasangan. Anda tidak boleh berasumsi bahwa input diurutkan.
Keluaran
Integer n
sedemikian rupa sehingga n % p_i == a_i
untuk setiap indeks i
. Itu tidak harus menjadi nilai terkecil, dan mungkin negatif.
Pembatasan waktu polinomial
Untuk mencegah solusi murah yang hanya mencoba n=0
, n=1
, n=2
, dan sebagainya, kode Anda harus berjalan dalam waktu polinomial dalam panjang input . Perhatikan bahwa angka m
dalam input memiliki panjang Θ(log m)
, jadi m
itu sendiri tidak polinomial dalam panjangnya. Ini berarti bahwa Anda tidak dapat menghitung hingga m
atau melakukan waktu operasi m
, tetapi Anda dapat menghitung operasi aritmatika pada nilai-nilai.
Anda tidak boleh menggunakan format input yang tidak efisien seperti unary untuk menyiasati ini.
Larangan lainnya
Built-in untuk melakukan hal-hal berikut tidak diperbolehkan: Menerapkan teorema Sisa Cina, menyelesaikan persamaan, atau nomor faktor.
Anda dapat menggunakan built-in untuk menemukan mod dan melakukan penambahan, pengurangan, penggandaan, dan eksponensial modular (dengan eksponen angka alami). Anda tidak boleh menggunakan operasi modular bawaan lainnya, termasuk pembalikan modular, pembagian, dan pencarian pesanan.
Uji kasus
Ini memberikan solusi non-negatif terkecil. Jawaban Anda mungkin berbeda. Mungkin lebih baik jika Anda memeriksa secara langsung bahwa output Anda memenuhi setiap kendala.
[(5, 3)]
3
[(7, 2), (5, 4), (11, 0)]
44
[(5, 1), (73, 4), (59, 30), (701, 53), (139, 112)]
1770977011
[(982451653, 778102454), (452930477, 133039003)]
68121500720666070
sumber
Jawaban:
Mathematica,
555145Pembalikan modular dilarang, tetapi eksponensial modular diizinkan. Dengan teorema kecil Fermat
n^(-1) % p == n^(p-2) % p
,.Contoh:
Hanya untuk bersenang-senang:
sumber
PowerMod[#2,#-2,#]
dan saya juga tidak berpikir ada persyaratan untuk fungsi yang akan dinamai, membawanya ke 48.Python 2,
165101999885 byteMenggunakan teorema kecil Fermat seperti jawaban lainnya. Jangan repot-repot menjaga jumlah akhir dalam jangkauan modular, karena kami tidak tertarik dengan solusi terkecil. Terima kasih Volatilitas untuk menghemat 13 byte.
sumber
for
.x/a*b*pow(x/a,a-2,a)for a,b in l
harus bekerja.Pyth,
40373629Menggunakan teorema kecil Fermat, terima kasih kepada alephalpha. Menghitung menggunakan rumus ini .
sumber
Ruby, 129
Nah, kawan-kawan, sepertinya solusi Ruby harus lebih panjang karena eksponensial modular tidak tersedia tanpa memuat perpustakaan openssl dan melakukan konversi ke OpenSSL :: BN. Tetap saja senang menulisnya:
sumber
require
,eval
atauputs
.Python 2, 61
Ini menggunakan variasi konstruksi produk yang digunakan jawaban lain.
Idenya adalah untuk mengulangi kendala dan memperbarui solusi
n
untuk memenuhi kendala saat ini tanpa mengacaukan yang sebelumnya. Untuk melakukannya, kami melacak produkP
bilangan prima yang terlihat sampai sekarang, dan mengamati bahwa menambahkan kelipatanP
tidak memiliki efek modulo pada prime yang sudah terlihat.Jadi, kita hanya perlu mengubah
n
untuk memuaskann%p == a
dengan menambahkan kelipatan yang tepatP
. Kami memecahkan untuk koefisienc
:(n + P*c) % p == a
Ini mengharuskan
c = (a-n) * P^(-1)
, di mana invers diambil modulop
. Seperti yang dicatat orang lain, kebalikannya dapat dihitung oleh Teorema Kecil Fermat sebagaiP^(-1) = pow(P,p-2,p)
. Jadi,,c = (a-n) * pow(P,p-2,p)
dan kami memperbaruin
olehn+= P * (a-n) * pow(P,p-2,p)
.sumber
Haskell,
68100 bytePenggunaan:
f [(5,1), (73,4), (59,30), (701,53), (139,112)]
->142360350966
.Edit: sekarang dengan fungsi "power / mod" yang cepat. Versi lama (68 byte) dengan fungsi daya bawaan:
sumber