Ini adalah masalah dari sesi latihan Kontes Pemrograman Collegiate Polandia 2012 . Meskipun saya dapat menemukan solusi untuk kontes utama, saya sepertinya tidak dapat menemukan solusi untuk masalah ini di mana saja.
Masalahnya adalah: Diberikan satu set bilangan bulat positif yang berbeda tidak lebih besar dari , temukan ukuran dari subset terkecil yang tidak memiliki pembagi umum selain 1. paling banyak 500, dan sebuah solusi dapat diasumsikan ada.
i ≠ j S g 2 g 3 . . . g 10 g 2 g 3 . . . g 10 ≥ 3 × 5 × 7 × 11 × . . . × 29 = 3234846615 > 10 9 , sebuah kontradiksi.
Namun, bahkan dengan ini, kekuatan kasar langsung masih terlalu lambat. Apakah ada yang punya ide lain?
algorithms
number-theory
Wakaka
sumber
sumber
Jawaban:
Masalah ini setara dengan yang berikut ini, dan sepele untuk membangun reduksi dua arah.
Diberikan daftar vektor bit, temukan jumlah minimumnya sedemikian rupa sehingga0 (∗)
and
semuanya menghasilkan vektor bit. ( ∗ )Kemudian kami tampilkan set cover reduced ke . Dengan menetapkan sampul, maksud saya diberi daftar set , temukan jumlah set minimum yang mencakup penyatuan mereka.S 1 , … , S k(∗) S1,…,Sk
Kami memerintahkan elemen dalam set menjadi . Misalkan , di mana jika , 0 sebaliknya. Perhatikan bahwa fungsi ini adalah penambangan sehingga memiliki kebalikannya. f ( S ) = ( 1 - χ sebuah 1 ( S ) , ... , 1 - χ sebuah n ( S ) ) χ x ( S ) = 1 x ∈ Sa1,…,an f(S)=(1−χa1(S),…,1−χan(S)) χx(S)=1 x∈S
Sekarang, jika kita memecahkan pada , dan solusinya adalah , lalu adalah solusi untuk mengatur penutup.f ( S 1 ) , … , f ( S k ) { f ( S b 1 ) , … , f ( S b m ) } { f - 1 ( S b 1 ) , … , f - 1 ( S b m ) }(∗) f(S1),…,f(Sk) {f(Sb1),…,f(Sbm)} {f−1(Sb1),…,f−1(Sbm) }
Jadi saya akan berpikir masalah ini menguji kemampuan seseorang untuk memangkas ruang pencarian.
sumber
Dimungkinkan untuk menyelesaikan ini secara relatif efisien dengan menghitung semua gcd berpasangan, menghapus duplikat, dan kemudian berulang. Ini tindakan menghapus duplikat sebelum Anda berulang yang membuatnya efisien.
Saya akan menjelaskan algoritma lebih terinci di bawah ini, tetapi pertama-tama, ini membantu untuk mendefinisikan operator biner . Jika adalah himpunan bilangan bulat positif, tentukanS , T⊗ S,T
Perhatikan bahwadan (dalam masalah Anda); biasanya, akan lebih kecil daripada yang disarankan, yang membantu membuat algoritma menjadi efisien. Perhatikan juga bahwa kita dapat menghitung denganoperasi gcd dengan penghitungan sederhana.| S ⊗ T | ≤ 10 9 S ⊗ T S ⊗ T | S | × | T ||S⊗T|≤|S|×|T| |S⊗T|≤109 S⊗T S⊗T |S|×|T|
Dengan notasi itu, berikut adalah algoritma. Biarkan menjadi set input angka. Hitung , lalu , lalu , dan seterusnya. Temukan terkecil sehingga tetapi . Maka Anda tahu bahwa ukuran subset terkecil seperti itu adalah . Jika Anda juga ingin menampilkan contoh konkret dari subset seperti itu, dengan mempertahankan back-pointer Anda dapat dengan mudah merekonstruksi set tersebut.S 2 = S 1 ⊗ S 1 S 3 = S 1 ⊗ S 2 S 4 = S 1 ⊗ S 3 k 1 ∈ S k 1 ∉ S k - 1 kS1 S2=S1⊗S1 S3=S1⊗S2 S4=S1⊗S3 k 1∈Sk 1∉Sk−1 k
Ini akan relatif efisien, karena tidak ada set perantara tumbuh dalam ukuran di atas (pada kenyataannya, ukurannya mungkin akan jauh lebih kecil dari itu), dan waktu berjalan membutuhkan sekitar operasi gcd. 500 × ( | S 1 | + | S 2 | + ⋯ )109 500×(|S1|+|S2|+⋯)
Berikut ini adalah pengoptimalan yang mungkin meningkatkan efisiensi lebih jauh. Pada dasarnya, Anda dapat menggunakan penggandaan iterated untuk menemukan terkecil sehingga . Khususnya, untuk setiap elemen , kami melacak subset terkecil dari yang gcdnya dan yang ukurannya . (Ketika Anda menghapus duplikat, Anda menyelesaikan ikatan yang mendukung subset yang lebih kecil.) Sekarang, daripada menghitung urutan sembilan set , kami malah menghitung urutan lima set , dengan menghitung , lalu , lalu1 ∈ S k x ∈ S i S 1 x ≤ i S 1 , S 2 , S 3 , S 4 , … , S 9 S 1 , S 2 , S 4 , S 8 , S 9 S 2 = S 1 ⊗ S 1 S 4 = S 2 ⊗ S 2 Sk 1∈Sk x∈Si S1 x ≤i S1,S2,S3,S4,…,S9 S1,S2,S4,S8,S9 S2=S1⊗S1 S4=S2⊗S2 S 9 = S 1 × S 8 k ∈ [ 1 , 2 , 4 , 8 , 9 ] 1 ∈ S k k 1 ∈ S k 1 1 S k 1 ∈ S kS8=S4⊗S4 , lalu . Saat Anda mulai, cari pertama sedemikian sehingga . Setelah Anda menemukan sedemikian sehingga , Anda dapat segera berhenti: Anda dapat menemukan subset terkecil yang gcdnya dengan melihat subset yang terkait dengan . Jadi, Anda dapat berhenti segera setelah mencapai set sedemikian rupa sehingga , yang memungkinkan Anda untuk berhenti lebih awal jika Anda menemukan subset yang lebih kecil.S9=S1×S8 k∈[1,2,4,8,9] 1∈Sk k 1∈Sk 1 1 Sk 1∈Sk
Ini harus efisien waktu dan efisien ruang. Untuk menghemat ruang, untuk setiap elemen , Anda tidak perlu menyimpan seluruh set: cukup untuk menyimpan dua backpointers (jadi dua elemen yang Anda ambil gcd dari, untuk mendapatkan ) dan secara opsional ukuran subset yang sesuai.S i , S j xx∈Sk Si,Sj x
Pada prinsipnya, Anda dapat mengganti urutan dengan rantai tambahan lainnya . Saya tidak tahu apakah beberapa rantai tambahan lain akan lebih baik. Pilihan optimal mungkin tergantung pada distribusi jawaban yang benar dan ukuran yang diharapkan dari set , yang tidak jelas bagi saya, tetapi mungkin dapat diturunkan secara empiris melalui eksperimen.S k[1,2,4,8,9] Sk
Penghargaan: Terima kasih saya kepada KWillets untuk gagasan menyimpan subset angka bersama dengan setiap elemen , yang memungkinkan penghentian lebih awal.Si
sumber
Mungkin lebih cepat melihat ini dengan cara lain ... prime terbesar kurang dari adalah 31607, untuk jumlah total 3401 bilangan prima antara 2 dan 31607, bukan jumlah yang sangat besar. Tuliskan masing-masing angka yang Anda berikan dengan faktor penuh hingga bilangan prima hingga 31607: Di sini adalah 1 atau prime yang besar. Kemudian satu set 's adalah relatif prima jika sesuai vektor bebas linear (dan mereka s berbeda atau keduanya 1), dan Anda sedang mencari rank dari matriks. ai=p n i 1 1 p n i 2 2 …PiPiainijP109---√
sumber
Jika Anda dapat menemukan subset dengan gcd (S) = 1, maka saya selalu dapat menghapus elemen redundan dari subset sampai hanya 2 elemen yang tersisa, yang memiliki gcd (S) = 1. Oleh karena itu, saya dapat mengklaim bahwa salah satu yang terkecil subset akan berisi 2 elemen atau tidak akan ada.
Sekarang, kami menggunakan rekursi untuk menyelesaikan masalah ini. Mari kita membagi array angka menjadi 2 bagian, satu dengan elemen n-1 dan satu dengan elemen 1 (elemen terakhir). Entah 2 angka akan berada di elemen n-1 pertama atau satu elemen akan ada di sana dari bagian 1 dipasangkan dengan elemen terakhir. Karenanya, kami dapat menyelesaikan masalah ini di
T (n) = T (n-1) + O (n) waktu. yang berarti T (n) = O (n ^ 2).
sumber