What could be the simplest and time efficient logic to express n! as product of powers of prime?
I am more interested to find the powers of prime so that I can know the numbers of factors.
As n! can be expresses as p1^e1 * p2^e2 * … * pk^ek, where each p is a prime number, then the number of factors of n is (e1 + 1)(e2 + 1) … *(ek + 1)
The most efficient way to find the prime factorisation of
n!that I know of is counting how often each prime appears as a factor inn!. Obviously, no prime larger thannappears, so letp <= nbe a prime.Among the numbers
1, ..., n, there aremultiples of
p. Among these, there aremultiples of
p². Among these, there aremultiples of
p³. Etc. So the exponent ofpin the prime factorisation ofn!is(An
a = p^k*b, withbnot divisible bypcontributeskto the exponent, and appears in theklists corresponding to the countsq1, ..., qk.)We can succinctly write a function for that:
That uses
floor(log n/log p) + 1divisions, so, if the primes not exceedingnare known, that contributes approximatelydivisions and additions to the total work. (Note: since most of the primes
≤ nare> √n, and for primesp > √nobviouslyq2 = 0, it is faster to calculate their exponent directly:n/p, that reduces the number of divisions needed by about half.)Finding the primes not exceeding
nis best done with a sieve, if you already have a good implementation, the Sieve of Atkin does it in O(n) or O(n/log log n) operations (depends on the implementation, but for feasible ranges,log log ncan be considered a constant), otherwise use the Sieve of Eratosthenes, it’s simple to implement and finds the primes not exceedingnin – again depending on the implementation – O(n*log log n) or O(n) operations.The total work for that algorithm is dominated by finding the primes (but for feasible
n, the contribution of the determination of the exponents is still not negligible).On the other hand, the work needed for finding the prime factorisation of each
k ≤ nof course depends on the algorithm used for that. Using trial division for that would result in a total work of aboutc*n^1.5/log n– I haven’t done anything to determine the constantc, and depending on details, you may have a factor oflog nin the numerator or denominator, but it’s basicallyn^1.5. A better method of finding the factorisations would be first finding the smallest prime factor [or any prime factor] with a modification of the Sieve of Eratosthenes, again in O(n*log log n) operations, and then use that to find the factorisation. You can store the factorisations and then, when processingkwith the known prime divisorp, look up the factorisation ofk/p, or generate the factorisation on the fly by recursively looking up the known prime factorqofk/p, then ofk/(p*q)etc. until the factorisation is complete – that is much simpler to handle if the known prime factor is always the smallest.On average, the prime factorisation of
kcontains≈ log log kterms, so that method would lead to O(n*log log n) overall complexity. But the constant factors in this method are considerably larger than in the first, so even if the prime-finding gives the same complexity, the first is faster.