Apakah Anda tahu algoritma yang menghitung faktorial setelah modulus secara efisien?
Misalnya, saya ingin memprogram:
for(i=0; i<5; i++)
sum += factorial(p-i) % p;
Tetapi, p
adalah angka besar (prima) untuk menerapkan faktorial secara langsung .
Dengan Python, tugas ini sangat mudah, tetapi saya benar-benar ingin tahu cara mengoptimalkan.
algorithms
efficiency
integers
Jonaprieto
sumber
sumber
(X!) (mod (X+1))
, atau lebih umum(X!) (mod Y)
? Dan saya kira itufactorial(100!)
tidak berarti Anda ingin menerapkan fungsi faktorial dua kali.Jawaban:
(Jawaban ini awalnya diposting oleh penanya jonaprieto di dalam pertanyaan.)
Saya ingat teorema Wilson , dan saya memperhatikan hal-hal kecil:
Dalam program di atas, lebih baik jika saya menulis:
Dan Anda dapat menemukan karena , jadi dengan algoritma Euclidian yang diperluas, Anda dapat menemukan nilai , yaitu modulus kebalikan. gcd ( p , p - i ) = 1 ( p - i ) - 1(p−i)−1 gcd(p,p−i)=1 (p−i)−1
Anda juga dapat melihat kongruensi yang sama, seperti: jadi, jumlahnya sama: dan jika Anda membuat faktor pada awalnya faktorial Anda mendapatkan Dan, voila, invers modulus lebih efisien daripada faktorial. (-24)-1+(6)-1+(-2
sumber
Contoh yang Anda posting sangat terkait dengan masalah Euler # 381. Jadi saya akan mengirim jawaban yang tidak memecahkan masalah Euler. Saya akan memposting bagaimana Anda dapat menghitung faktorial modulo prima.
Jadi: Bagaimana cara menghitung n! modulo p?
Pengamatan cepat: Jika n ≥ p, maka n! memiliki faktor p, jadi hasilnya 0. Sangat cepat. Dan jika kita mengabaikan persyaratan bahwa p harus menjadi prima maka biarkan q menjadi faktor prima terkecil dari p, dan n! modulo p adalah 0 jika n ≥ q. Tidak ada banyak alasan untuk meminta p sebagai jawaban utama untuk menjawab pertanyaan Anda.
Sekarang dalam contoh Anda (n - i)! untuk 1 ≤ i ≤ 5 muncul. Anda tidak harus menghitung lima faktorial: Anda menghitung (n - 5) !, dikalikan dengan (n - 4), dapatkan (n - 4)!, Kalikan dengan (n - 3) untuk mendapatkan (n - 3)! dll. Ini mengurangi pekerjaan hampir faktor 5. Jangan memecahkan masalah secara harfiah.
Pertanyaannya adalah bagaimana cara menghitung n! modulo m. Cara yang jelas adalah menghitung n !, suatu angka dengan kira-kira n log dan angka desimal, dan menghitung modulo p sisanya. Itu kerja keras. Pertanyaan: Bagaimana kita bisa mendapatkan hasil ini lebih cepat? Dengan tidak melakukan hal yang jelas.
Kita tahu bahwa ((a * b * c) modulo p = (((a * b) modulo p) * c) modulo p.
Untuk menghitung n !, kita biasanya mulai dengan x = 1, lalu kalikan x dengan 1, 2, 3, ... n. Menggunakan rumus modulo, kami menghitung n! modulo p tanpa menghitung n !, dengan memulai dengan x = 1, dan kemudian untuk i = 1, 2, 3, .., n kita ganti x dengan (x * i) modulo p.
Kami selalu memiliki x <p dan i <n, jadi kami hanya membutuhkan cukup presisi untuk menghitung x * p, bukan presisi yang jauh lebih tinggi untuk menghitung n !. Jadi untuk menghitung n! modulo p untuk p ≥ 2 kita mengambil langkah-langkah berikut:
(Beberapa jawaban menyebutkan teorema Wilson, yang hanya menjawab pertanyaan dalam kasus yang sangat khusus dari contoh yang diberikan, dan sangat berguna untuk menyelesaikan masalah Euler # 381, tetapi secara umum tidak berguna untuk menyelesaikan pertanyaan yang diajukan).
sumber
Ini adalah implementasi penerapan teorema wilson saya:
Fungsi factMOD adalah fungsi untuk memanggil untuk menghitung (n!)% MOD ketika MOD-n sedikit terhadap n.
Apakah ada yang tahu pendekatan efisien lain ketika itu tidak terjadi (mis: n = 1e6 dan MOD = 1e9 + 7)?
sumber