Kennen Sie einen Algorithmus, der die Fakultät nach dem Modul effizient berechnet?
Zum Beispiel möchte ich programmieren:
for(i=0; i<5; i++)
sum += factorial(p-i) % p;
Ist p
aber eine große Zahl (Primzahl), um Fakultät direkt anzuwenden .
In Python ist diese Aufgabe wirklich einfach, aber ich möchte wirklich wissen, wie man optimiert.
algorithms
efficiency
integers
Jonaprieto
quelle
quelle
(X!) (mod (X+1))
, oder die allgemeinere(X!) (mod Y)
? Und ich nehme an, dasfactorial(100!)
heißt nicht, dass Sie die Fakultätsfunktion zweimal anwenden möchten.Antworten:
(Diese Antwort wurde ursprünglich vom Fragesteller jonaprieto in der Frage gepostet .)
Ich erinnere mich an Wilsons Theorem und bemerkte kleine Dinge:
Im obigen Programm ist es besser, wenn ich schreibe:
Und Sie können weil gcd ( p , p - i ) = 1 ist. Mit dem erweiterten Euklidian-Algorithmus können Sie also den Wert von ( p - i ) - 1 finden , dh den inversen Modul.(p−i)−1 gcd(p,p−i)=1 (p−i)−1
Sie können die gleichen Kongruenzen wie folgt anzeigen:
quelle
The example that you are posting is very closely related to Euler problem #381. So I will post an answer that doesn't solve the Euler problem. I will post how you can calculate factorials modulo a prime.
So: How to calculate n! modulo p?
Quick observation: If n ≥ p, then n! has a factor p, so the result is 0. Very quick. And if we ignore the requirement that p should be a prime then let q be the smallest prime factor of p, and n! modulo p is 0 if n ≥ q. There's also not much reason to require that p is a prime to answer your question.
Now in your example (n - i)! for 1 ≤ i ≤ 5 came up. You don't have to calculate five factorials: You calculate (n - 5)!, multiply by (n - 4) go get (n - 4)!, multiply by (n - 3) to get (n - 3)! etc. This reduces the work by almost a factor 5. Don't solve the problem literally.
The question is how to calculate n! modulo m. The obvious way is to calculate n!, a number with roughly n log n decimal digits, and calculate the remainder modulo p. That's hard work. Question: How can we get this result quicker? By not doing the obvious thing.
We know that ((a * b * c) modulo p = (((a * b) modulo p) * c) modulo p.
To calculate n!, we would normally start with x = 1, then multiply x by 1, 2, 3, ... n. Using the modulo formula, we calculate n! modulo p without calculating n!, by starting with x = 1, and then for i = 1, 2, 3, .., n we replace x with (x * i) modulo p.
We always have x < p and i < n, so we only need enough precision to calculate x * p, not the much higher precision to calculate n!. So to calculate n! modulo p for p ≥ 2 we take the following steps:
(Some answers mention Wilson's theorem, which only answers the question in the very special case of the example given, and is very useful to solve Euler problem #381, but in general isn't useful to solve the question that was asked).
quelle
Dies ist meine Implementierungsanwendung des Wilson-Theorems:
Die factMOD-Funktion ist diejenige, die aufgerufen wird, um (n!)% MOD zu berechnen, wenn MOD-n gegen n klein ist.
Kennt jemand einen anderen effizienten Ansatz, wenn dies nicht der Fall ist (z. B .: n = 1e6 und MOD = 1e9 + 7)?
quelle