Terkecil Non-Pembagi


11

Pada dasarnya, masalahnya adalah: Untuk himpunan dari angka positif, cari angka minimal yang bukan merupakan pembagi elemen , yaitu .SdSxS, dx

Nyatakan n=|S|dan C=max(S) . Pertimbangkan fungsi F(x)= bilangan prima terkecil yang tidak membagi x . Sangat mudah untuk melihat bahwa F(x)logx . Dan untuk satu set S , biarkan F(S)= yang paling utama yang tidak membagi setiap elemen dari S . Kami memiliki batas atas

F(S)F(lcm(S))F(Cn)nlogC.

Oleh karena itu algoritma brute-force sederhana, yang menghitung semua angka dari 1 hingga nlogC dan memeriksa jika tidak membagi elemen S , bersifat polinomial dan memiliki kompleksitas waktu O(n2logC) .

Cara lain untuk memecahkan masalah adalah menghitung semua faktor untuk setiap elemen S dan menggunakannya dalam algoritma brute-force untuk memeriksa apakah x adalah jawaban dalam waktu O(1) . Algoritma ini memiliki kompleksitas waktu O(nmin(C,nlogC)+nlogC) dan menggunakan memori O(nlogC) , karena kita tidak perlu menghitung dan faktor toko lebih besar dari nlogC . Untuk n dan C berkinerja lebih baik.

Secara rinci, algoritme terdiri dari dua bagian:

  1. Buat himpunan S^ terdiri dari semua faktor semua elemen S , yaitu

    xS fnlogC, (fxfS^)
    Ini dapat dilakukan dalam waktu O(nmin(C,nlogC)) dan memori O(nlogC) . (Dari mana asalnya? Untuk elemen S , kita dapat memfaktorkannya menggunakan faktorisasi percobaan dengan semua angka hingga C atau semua bilangan prima hingga nlogC , mana yang lebih kecil, sehingga setiap elemen S dapat difaktorkan dalam waktu O(min(C,nlogC)) .)
  2. Temukan angka minimal . Langkah ini membutuhkan waktu , jika memeriksa apakah dapat dilakukan dalam waktu . O ( | S | ) = O ( n log C ) x S O ( 1 )dS^O(|S^|)=O(nlogC)xS^O(1)

Saya punya dua pertanyaan yang saya minati:

  1. Apakah ada algoritma yang lebih cepat untuk menyelesaikan masalah?
  2. Untuk dan diberikan , bagaimana kita dapat membangun himpunan dengan maksimal-non-pembagi paling umum?C SnCS

1. Dengan "precompute" yang saya maksudkan sebelum memulai algoritma brute-force. 2. Kompleksitas anjak piutang memang subexponential, melihat definiton of . C
SkyterX

@ DW pada poin 2, kompleksitas anjak piutang adalah subeksponensial pada panjang bitstring yang mewakili angka, tetapi SkyterX dengan benar mengatakan bahwa itu adalah , yaitu, sebanding dengan akar kuadrat dari ukuran nomor. O(C)
Lieuwe Vinkhuijzen

@LieuweVinkhuijzen, Itu tidak cocok untuk saya. Kompleksitas anjak menggunakan GNFS akan menjadi sesuatu seperti , yang secara signifikan kurang dari . Lihat en.wikipedia.org/wiki/… . O ( O(exp{1.9(logC)1/3(loglogC)2/3})O(C)
DW

Pernyataan bahwa metode kedua berkinerja lebih baik "untuk kecil dan " tidak tepat. Berkinerja lebih baik hanya jika . Jadi harus besar untuk metode kedua agar kinerjanya lebih baik (tidak kecil). C n nCnnC/log(C)n
DW

@ WD Anda benar, saya tidak mengetahui kompleksitas GNFS.
Lieuwe Vinkhuijzen

Jawaban:


6

Dimungkinkan untuk meningkatkan algoritma kedua Anda dengan menggunakan algoritma yang lebih baik untuk faktorisasi bilangan bulat.

Ada dua algoritma untuk faktorisasi bilangan bulat yang relevan di sini:

  • GNFS dapat memasukkan faktor integer dengan waktu berjalan .O ( L C [ 0,33 , 1.92 ] )CO(LC[0.33,1.92])

  • ECM dapat menemukan faktor (jika ada) dengan waktu berjalan ; menemukan semua faktor akan memakan waktu kali lebih lama (yang relatif kecil dibandingkan dengan waktu berjalan ECM).O ( L n log C [ 0,5 , 1.41 ] ) O ( log C / log ( n log C ) )nlogCO(LnlogC[0.5,1.41])O(logC/log(nlogC))

Di sini .Ln[α,c]=exp{c(logn)α(loglogn)1α}

Itu adalah ekspresi yang tampak mengerikan untuk waktu yang berjalan, tetapi fakta penting adalah bahwa ini lebih cepat daripada metode yang Anda sebutkan. Secara khusus, secara asimptot jauh lebih kecil dari , yaitu, GNFS jauh lebih cepat daripada mencoba semua faktor yang mungkin . Juga adalah asimtotik jauh lebih kecil dari , yaitu, ECM jauh lebih cepat daripada mencoba semua faktor yang mungkin .LC[0.33,1.92]C L n log C [0,5,1.41]nlogCnlogCCLnlogC[0.5,1.41]nlogCnlogC

Jadi, total waktu berjalan untuk metode ini kira-kira , dan ini secara asimptotik lebih baik daripada Anda Metode pertama dan asimtotik lebih baik daripada metode kedua Anda. Saya tidak tahu apakah mungkin untuk melakukan yang lebih baik lagi.O~(nmin(LC[0.33,1.92],LnlogC[0.5,1.41]))


Saya kira, bahwa setiap algoritma cepat untuk masalah ini harus mencakup beberapa jenis faktorisasi masukan set . Saya akan memeriksa algoritma faktorisasi tersebut, tetapi masih ada masalah dengan benar mengujinya, yang menimbulkan masalah kedua yang saya sebutkan membangun set dengan jawaban maksimal. SS
SkyterX

ECM menemukan satu faktor dalam waktu yang Anda berikan. Jika semua faktor angka adalah ≤ n log C maka Anda perlu mengulangi algoritme, hingga mencatat C / log (n log C) kali.
gnasher729

3

Non-pembagi paling umum mungkin sebesar N log C, tetapi jika nomor N didistribusikan secara acak maka non-pembagi paling umum mungkin jauh lebih kecil, mungkin jauh lebih sedikit daripada N. Saya akan membuat tabel yang bilangan prima adalah pembagi nomor yang mana.

Untuk setiap bilangan prima p kita memiliki indeks yang berarti semua bilangan hingga indeks tersebut telah diperiksa untuk dapat dibagi oleh p, dan kami memiliki daftar semua bilangan tersebut yang dapat dibagi dengan.kp

Kemudian untuk d = 2, 3, 4, ... kami mencoba mencari angka yang dapat dibagi dengan d, atau menunjukkan tidak ada. Kami mengambil faktor prima p terbesar d. Kemudian kami memeriksa semua angka yang dapat dibagi dengan p apakah mereka juga dapat dibagi dengan d. Jika tidak ada yang ditemukan, maka kami memeriksa nomor lebih lanjut dengan indeks> untuk dapat dibagi dengan p, memperbarui dan daftar angka yang dapat dibagi dengan p, dan memeriksa apakah setiap nomor dapat dibagi oleh d.kpkp

Untuk memeriksa apakah ada nomor yang dapat dibagi dengan p, kami memeriksa rata-rata nomor p. Kemudian jika kita memeriksa apakah ada angka yang dapat dibagi 2p, ada kemungkinan 50% bahwa kita perlu memeriksa hanya satu nomor (yang bisa dibagi dengan p), dan peluang 50% untuk memeriksa rata-rata 2p lebih banyak angka. Menemukan nomor yang dapat dibagi dengan 3p kemungkinan besar cepat dan sebagainya, dan kami tidak pernah memeriksa lebih dari angka N untuk dapat dibagi dengan p, karena hanya ada nomor N.

Saya berharap ini berhasil dengan tentang pemeriksaan keterbagianN2/logN

PS. Seberapa besar hasilnya untuk angka acak?

Asumsikan saya memiliki nomor acak N. Probabilitas bahwa salah satu angka N dapat dibagi dengan d adalah 1 - (1 - 1 / d) ^ N. Saya berasumsi probabilitas bahwa masing-masing angka 1 ≤ d ≤ k adalah faktor dari salah satu angka acak dihitung dengan mengalikan probabilitas ini (Ok, itu agak cerdik, karena probabilitas ini kemungkinan tidak terlalu independen).

Dengan asumsi itu, dengan N = 1000, ada kemungkinan 50% bahwa salah satu angka 1..244 tidak membagi angka apa pun, dan satu dalam satu miliar bahwa setiap angka hingga 507 membagi salah satu angka. Dengan N = 10.000 ada kemungkinan 50% bahwa salah satu angka 1..1726 tidak membagi angka apa pun, dan satu dalam satu miliar bahwa setiap angka hingga 2979 membagi salah satu angka.

Saya akan mengusulkan bahwa untuk input acak N, ukuran hasilnya sedikit lebih besar dari N / ln N; mungkin sesuatu seperti N / ln N * (ln ln N) ^ 2. Inilah alasannya:

Probabilitas bahwa setidaknya salah satu dari angka acak N habis dibagi oleh d acak . Jika d adalah sekitar N, maka adalah sekitar 1 - exp (-1) ≈ 0,6321. Itu untuk pembagi tunggal; kemungkinan bahwa masing-masing dari beberapa angka d ≈ N adalah pembagi setidaknya satu dari angka N cukup tipis, sehingga maksimum d akan secara signifikan lebih kecil dari N. 1 - ( 1 - 1 / d ) N1(11/d)N1(11/d)N

Jika d << N, maka .1(11/d)N1exp(N/d)

Jika d ≈ N / ln N kemudian .1exp(N/d)1exp(lnN)=11/N

Kami akan menambahkan probabilitas ini untuk sekitar N / ln N nilai d, tetapi untuk sebagian besar d hasilnya akan secara signifikan lebih besar, sehingga d terbesar akan entah bagaimana lebih besar dari N / ln N tetapi secara signifikan lebih kecil dari N.

PS. Menemukan nomor yang dapat dibagi oleh d:

Kami memilih faktor prima p terbesar dari d, dan kemudian kami pertama-tama memeriksa angka-angka yang sudah diketahui dapat habis dibagi oleh p. Katakan d = kp. Kemudian secara rata-rata kita hanya memeriksa k angka-angka yang dapat dibagi dengan p saat memeriksa d khusus ini, dan kami memeriksa paling banyak semua nilai N untuk dapat dibagi oleh p keseluruhan, untuk semua d habis dibagi dengan p. Sebenarnya, kami kemungkinan besar memeriksa kurang dari nilai N untuk sebagian besar bilangan prima, karena setelah memeriksa semua nilai N algoritma kemungkinan besar berakhir. Jadi jika hasilnya adalah R, maka saya berharap kurang dari nilai N yang dibagi oleh setiap prime kurang dari R. Dengan asumsi R ≤ N, itu tentang N ^ 2 / log N cek.

PS. Menjalankan beberapa tes

Saya menjalankan algoritma ini beberapa kali dengan N = 1.000.000 angka acak> 0. Non-pembagi paling umum adalah antara 68.000 dan 128.000 dengan mayoritas besar berjalan antara 100.000 dan 120.000. Jumlah divisi adalah antara 520 juta dan 1800 juta yang jauh lebih kecil dari (N / ln N) ^ 2; sebagian besar kasus digunakan antara 1000 dan 1500 juta divisi.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.