Apa yang akan menjadi algoritma paling optimal (kinerja-bijaksana) untuk menghitung jumlah pembagi nomor yang diberikan?
Akan sangat bagus jika Anda bisa memberikan pseudocode atau tautan ke beberapa contoh.
EDIT: Semua jawaban sangat membantu, terima kasih. Saya menerapkan Saringan Atkin dan kemudian saya akan menggunakan sesuatu yang mirip dengan apa yang ditunjukkan Jonathan Leffler. Tautan yang diposting oleh Justin Bozonier memiliki informasi lebih lanjut tentang apa yang saya inginkan.
performance
algorithm
pseudocode
pemain ski
sumber
sumber
Jawaban:
Dmitriy benar bahwa Anda ingin Saringan Atkin untuk menghasilkan daftar utama tetapi saya tidak percaya bahwa mengurus seluruh masalah. Sekarang Anda memiliki daftar bilangan prima, Anda perlu melihat berapa banyak bilangan prima yang bertindak sebagai pembagi (dan seberapa sering).
Inilah beberapa python untuk algo.Lihat di sini dan cari "Subjek: matematika - perlu pembagi algoritma". Hanya menghitung jumlah item dalam daftar alih-alih mengembalikannya.Ini adalah Dr. Math yang menjelaskan apa sebenarnya yang perlu Anda lakukan secara matematis.
Intinya
n
adalah angka jika angka Anda adalah:n = a^x * b^y * c^z
(di mana a, b, dan c adalah pembagi utama n dan x, y, dan z adalah berapa kali pembagi diulang) maka jumlah total untuk semua pembagi adalah:
(x + 1) * (y + 1) * (z + 1)
.Sunting: BTW, untuk menemukan a, b, c, dll. Anda akan ingin melakukan apa yang menjadi jumlah algo serakah jika saya memahami ini dengan benar. Mulailah dengan pembagi utama terbesar Anda dan kalikan dengan sendirinya sampai perkalian lebih lanjut akan melebihi angka n. Kemudian pindah ke faktor terendah berikutnya dan kalikan bilangan prima sebelumnya ^ kali dikalikan dengan bilangan prima saat ini dan teruskan mengalikan dengan bilangan prima sampai yang berikutnya akan melebihi n ... dll. Lacak berapa kali Anda mengalikan pembagi bersama dan menerapkan angka-angka itu ke dalam rumus di atas.
Tidak 100% yakin tentang deskripsi algo saya tetapi jika itu bukan sesuatu yang mirip.
sumber
n = (a^x * b^y * c^z)-(x + 1) * (y + 1) * (z + 1)
juga aturannyaAda lebih banyak teknik untuk memfaktorkan daripada saringan Atkin. Sebagai contoh misalkan kita ingin memfaktorkan 5893. Yah, sqrt-nya adalah 76,76 ... Sekarang kita akan mencoba menulis 5893 sebagai produk kotak. Nah (77 * 77 - 5893) = 36 yang 6 kuadrat, jadi 5893 = 77 * 77 - 6 * 6 = (77 + 6) (77-6) = 83 * 71. Jika itu tidak berhasil, kita akan melihat apakah 78 * 78 - 5893 kotak yang sempurna. Dan seterusnya. Dengan teknik ini Anda dapat dengan cepat menguji faktor-faktor di dekat akar kuadrat dari n jauh lebih cepat daripada dengan menguji masing-masing bilangan prima. Jika Anda menggabungkan teknik ini untuk mengesampingkan bilangan prima besar dengan ayakan, Anda akan memiliki metode anjak jauh lebih baik daripada dengan ayakan saja.
Dan ini hanyalah salah satu dari sejumlah besar teknik yang telah dikembangkan. Ini cukup sederhana. Butuh waktu lama untuk belajar, katakanlah, cukup banyak teori untuk memahami teknik anjak piutang berdasarkan kurva eliptik. (Saya tahu mereka ada. Saya tidak mengerti mereka.)
Karena itu, kecuali jika Anda berurusan dengan bilangan bulat kecil, saya tidak akan mencoba menyelesaikan masalah itu sendiri. Sebaliknya saya akan mencoba mencari cara untuk menggunakan sesuatu seperti perpustakaan PARI yang sudah memiliki solusi yang sangat efisien diimplementasikan. Dengan itu saya dapat memasukkan 40 angka acak seperti 124321342332143213122323434312213424231341 dalam sekitar 0,05 detik. (Faktorisasi, jika Anda bertanya-tanya, adalah 29 * 439 * 1321 * 157907 * 284749 * 33843676813 * 4857795469949. Saya cukup yakin bahwa itu tidak mengetahui hal ini menggunakan saringan Atkin ...)
sumber
@Yasky
Fungsi pembagi Anda memiliki bug karena tidak berfungsi dengan benar untuk kuadrat sempurna.
Mencoba:
sumber
Saya tidak setuju bahwa ayakan Atkin adalah jalan yang harus ditempuh, karena bisa dengan mudah membutuhkan waktu lebih lama untuk memeriksa setiap angka di [1, n] untuk mengetahui keaslian daripada mengurangi jumlah berdasarkan divisi.
Berikut beberapa kode yang, meskipun sedikit peretasan, umumnya jauh lebih cepat:
ps Itu kode python yang berfungsi untuk memecahkan masalah ini.
sumber
Berikut ini adalah algoritma O ke depan (sqrt (n)). Saya menggunakan ini untuk memecahkan proyek euler
sumber
Pertanyaan yang menarik ini jauh lebih sulit daripada yang terlihat, dan belum dijawab. Pertanyaan tersebut dapat diperhitungkan menjadi 2 pertanyaan yang sangat berbeda.
1 diberikan N, temukan daftar L faktor prima N
2 diberikan L, hitung jumlah kombinasi unik
Semua jawaban yang saya lihat sejauh ini merujuk ke # 1 dan gagal menyebutkannya tidak dapat ditelusuri untuk jumlah yang sangat besar. Untuk N berukuran sedang, bahkan angka 64-bit, itu mudah; untuk N yang sangat besar, masalah anjak piutang bisa memakan waktu "selamanya". Enkripsi kunci publik tergantung pada ini.
Pertanyaan # 2 perlu diskusi lebih lanjut. Jika L hanya berisi angka unik, ini adalah perhitungan sederhana menggunakan rumus kombinasi untuk memilih objek k dari n item. Sebenarnya, Anda perlu menjumlahkan hasil dari menerapkan formula sambil memvariasikan k dari 1 hingga sizeof (L). Namun, L biasanya akan berisi banyak kejadian beberapa bilangan prima. Sebagai contoh, L = {2,2,2,3,3,5} adalah faktorisasi dari N = 360. Sekarang masalah ini cukup sulit!
Menyatakan ulang 2, diberikan koleksi C yang mengandung k item, sehingga item a memiliki 'duplikat, dan item b memiliki duplikat b, dll. Berapa banyak kombinasi unik dari item 1 hingga k-1 yang ada? Misalnya, {2}, {2,2}, {2,2,2}, {2,3}, {2,2,3,3} masing-masing harus terjadi sekali dan hanya sekali jika L = {2,2 , 2,3,3,5}. Setiap sub-koleksi unik tersebut adalah pembagi unik N dengan mengalikan item dalam sub-koleksi.
sumber
p_i
merupakan faktor utama dari suatu angka dengank_i
multiplisitas, jumlah total pembagi dari angka tersebut adalah(k_1+1)*(k_2+1)*...*(k_n+1)
. Saya kira Anda sudah tahu ini sekarang, tetapi saya tulis ini untuk keuntungan jika pembaca acak di sini.Jawaban atas pertanyaan Anda sangat tergantung pada ukuran bilangan bulat. Metode untuk angka kecil, misalnya kurang dari 100 bit, dan untuk angka ~ 1000 bit (seperti yang digunakan dalam kriptografi) sangat berbeda.
gambaran umum: http://en.wikipedia.org/wiki/Divisor_function
nilai untuk
n
referensi kecil dan bermanfaat: A000005: d (n) (juga disebut tau (n) atau sigma_0 (n)), jumlah pembagi n.contoh dunia nyata: faktorisasi bilangan bulat
sumber
HANYA satu baris
Saya telah memikirkan dengan sangat hati-hati tentang pertanyaan Anda dan saya telah mencoba untuk menulis sepotong kode yang sangat efisien dan berkinerja tinggi. Untuk mencetak semua pembagi nomor yang diberikan pada layar, kita hanya perlu satu baris kode! (gunakan opsi -std = c99 saat kompilasi melalui gcc)
untuk menemukan jumlah pembagi, Anda dapat menggunakan fungsi sangat sangat cepat berikut (berfungsi dengan benar untuk semua bilangan bulat kecuali 1 dan 2)
atau jika Anda memperlakukan nomor yang diberikan sebagai pembagi (berfungsi dengan benar untuk semua nomor bilangan bulat kecuali 1 dan 2)
CATATAN: dua fungsi di atas bekerja dengan benar untuk semua angka bilangan bulat positif kecuali angka 1 dan 2 sehingga berfungsi untuk semua angka yang lebih besar dari 2 tetapi jika Anda harus mencakup 1 dan 2, Anda dapat menggunakan salah satu fungsi berikut (sedikit lebih lambat)
ATAU
kecil itu indah :)
sumber
Saringan Atkin adalah versi yang dioptimalkan dari saringan Eratosthenes yang memberikan semua bilangan prima hingga bilangan bulat yang diberikan. Anda harus dapat google ini untuk lebih detail.
Setelah Anda memiliki daftar itu, adalah masalah sederhana untuk membagi nomor Anda dengan setiap perdana untuk melihat apakah itu pembagi yang tepat (yaitu, sisanya adalah nol).
Langkah-langkah dasar menghitung pembagi untuk angka (n) adalah [ini adalah pseudocode yang dikonversi dari kode asli jadi saya harap saya belum memperkenalkan kesalahan]:
sumber
Anda dapat mencoba yang ini. Agak sedikit retas, tapi cukup cepat.
sumber
Setelah Anda memiliki faktorisasi utama, ada cara untuk menemukan jumlah pembagi. Tambahkan satu ke masing-masing eksponen pada masing-masing faktor dan kemudian gandakan eksponen bersama.
Misalnya: 36 Faktorisasi Utama: 2 ^ 2 * 3 ^ 2 Pembagi: 1, 2, 3, 4, 6, 9, 12, 18, 36 Jumlah Pembagi: 9
Tambahkan satu ke setiap eksponen 2 ^ 3 * 3 ^ 3 Eksponen gandakan: 3 * 3 = 9
sumber
Sebelum Anda berkomitmen pada solusi, pertimbangkan bahwa pendekatan Saringan mungkin bukan jawaban yang baik dalam kasus biasa.
Beberapa waktu lalu ada pertanyaan utama dan saya melakukan tes waktu - untuk bilangan bulat 32-bit setidaknya menentukan apakah bilangan prima lebih lambat daripada kekuatan kasar. Ada dua faktor yang terjadi:
1) Sementara seorang manusia membutuhkan waktu untuk melakukan pembagian, mereka sangat cepat di komputer - mirip dengan biaya mencari jawabannya.
2) Jika Anda tidak memiliki tabel utama, Anda dapat membuat loop yang sepenuhnya berjalan di cache L1. Ini membuatnya lebih cepat.
sumber
Ini adalah solusi yang efisien:
sumber
Pembagi melakukan sesuatu yang spektakuler: mereka membelah sepenuhnya. Jika Anda ingin memeriksa jumlah pembagi untuk suatu bilangan
n
, itu jelas berlebihan untuk menjangkau seluruh spektrum1...n
,. Saya belum melakukan penelitian mendalam untuk ini, tetapi saya memecahkan masalah Project Euler 12 pada Nomor Segitiga . Solusi saya untuk tes pembagi 500 yang lebih besar berlari selama 309504 mikrodetik (~ 0,3 detik). Saya menulis fungsi pembagi ini untuk solusinya.Untuk setiap algoritma, ada titik lemahnya. Saya pikir ini lemah terhadap bilangan prima. Tetapi karena angka segitiga tidak dicetak, ia melayani tujuannya dengan sempurna. Dari profil saya, saya pikir itu cukup baik.
Selamat berlibur.
sumber
numberOfDivisors
dan iterator pada 1; ini harus menyingkirkan kesenjangan dengan kesalahan nolAnda ingin Saringan Atkin, dijelaskan di sini: http://en.wikipedia.org/wiki/Sieve_of_Atkin
sumber
metode bilangan prima sangat jelas di sini. P [] adalah daftar bilangan prima kurang dari atau sama dengan sq = sqrt (n);
sumber
Buku teks teori angka menyebut fungsi penghitung-pembagi tau. Fakta menarik pertama adalah bahwa itu multiplikatif, yaitu. τ (ab) = τ (a) τ (b), ketika a dan b tidak memiliki faktor umum. (Bukti: setiap pasangan pembagi a dan b memberikan pembagi ab yang berbeda).
Sekarang perhatikan bahwa untuk pa prime, τ (p ** k) = k + 1 (kekuatan p). Dengan demikian Anda dapat dengan mudah menghitung τ (n) dari factorisation-nya.
Namun memfaktorkan jumlah besar bisa lambat (keamanan cryptraphy RSA tergantung pada produk dari dua bilangan prima besar yang sulit untuk difaktorkan). Itu menunjukkan algoritma yang dioptimalkan ini
sumber
Berikut ini adalah program C untuk menemukan jumlah pembagi nomor yang diberikan.
Kompleksitas dari algoritma di atas adalah O (sqrt (n)).
Algoritma ini akan bekerja dengan benar untuk angka yang kuadrat sempurna serta angka yang bukan kuadrat sempurna.
Perhatikan bahwa batas atas dari loop diatur ke akar kuadrat angka untuk memiliki algoritma yang paling efisien.
Perhatikan bahwa menyimpan batas atas dalam variabel terpisah juga menghemat waktu, Anda tidak boleh memanggil fungsi sqrt di bagian kondisi loop for, ini juga menghemat waktu komputasi Anda.
Alih-alih di atas untuk loop Anda juga dapat menggunakan loop berikut yang bahkan lebih efisien karena ini menghilangkan kebutuhan untuk menemukan akar kuadrat dari angka tersebut.
sumber
Berikut adalah fungsi yang saya tulis. kompleksitas waktu terburuknya adalah O (sqrt (n)), waktu terbaik di sisi lain adalah O (log (n)). Ini memberi Anda semua pembagi utama bersama dengan jumlah kemunculannya.
sumber
Ini adalah cara paling dasar untuk menghitung jumlah divisi:
sumber
@ Kendall
Saya menguji kode Anda dan membuat beberapa perbaikan, sekarang bahkan lebih cepat. Saya juga diuji dengan kode @ هومن جاویدپور, ini juga lebih cepat daripada kodenya.
sumber
Bukankah ini hanya pertanyaan tentang memfaktorkan angka - menentukan semua faktor angka? Anda kemudian dapat memutuskan apakah Anda memerlukan semua kombinasi dari satu faktor atau lebih.
Jadi, satu algoritma yang mungkin adalah:
Terserah Anda untuk menggabungkan faktor-faktor untuk menentukan sisa jawaban.
sumber
Ini adalah sesuatu yang saya buat berdasarkan jawaban Justin. Mungkin perlu beberapa optimasi.
sumber
Saya pikir inilah yang Anda cari. Saya melakukan persis seperti yang Anda minta. Salin dan tempel di Notepad. Simpan sebagai * .bat.Jalankan. Masukkan Nomor. Gandakan proses dengan 2 dan itulah jumlah pembagi. Saya sengaja membuatnya sehingga menentukan pembagi pembagi lebih cepat:
Harap dicatat bahwa varriable CMD tidak dapat mendukung nilai lebih dari 999999999
sumber
Saya kira yang satu ini akan berguna dan juga tepat
script.pyton
>>>factors=[ x for x in range (1,n+1) if n%x==0] print len(factors)
sumber
Cobalah sesuatu seperti ini:
sumber
Saya tidak tahu metode paling efisien, tetapi saya akan melakukan hal berikut:
Harus bekerja \ o /
Jika Anda perlu, saya dapat membuat kode besok di C untuk menunjukkan.
sumber