Note that the problem is equivalent to finding the highest power of base which divides n!.
If the base was prime (let's call it p), we could use a theorem from number theory to compute the highest power of p that divides n!:
Let's extract the part of your code that does this into a function:
int maximum_power_of_p_in_fac(int p, int n) {
int mu = 0;
while (n/p > 0) {
mu += n/p;
n /= p;
}
return mu;
}
Now what happens if base is a prime power? Let's say we have base = pq. Then if μ is the highest power of p which divides n! and r = floor(μ/q), we have
(p^q)^r = p^(qr) divides p^μ divides n!
and
(p^q)^(r+1) = p^(q(r+1)) >= p^(μ+1) does not divide n!
So r is the maximum power of p^q in n!. Let's write a function for that as well:
int maximum_power_of_pq_in_fac(int p, int q, int n) {
return maximum_power_of_p_in_fac(p, n) / q;
}
So what if base is general number? Let's say
base = p1q1 p2q2 ... pmqm
(this is the unique prime factorization of base). Then we just solve the problem for all piqi and take the minimum of those:
int maximum_power_of_base_in_fac(int base, int n) {
int res = infinity;
for every factor p^q in the prime factorization in base:
res = min(res, maximum_power_of_pq_in_fac(p,q,n));
return res;
}
How to factorize base? Well we can just use trial division, like your example code does. We start by checking whether 2 is a prime factor. If it is, we compute maximum_power_of_pq_in_fac
and divide base by 2 until it is no longer divisible by 2. Then we proceed with the next candidate factor:
void factorize(int base) {
for (int p = 2; p <= base; ++p) {
if (base % p == 0) { // if base is divisible by p, p is a prime factor
int q = 0;
while (base % p == 0) { // compute q and get rid of all the p factors
q++;
base /= p;
}
// do something with factor p^q
}
// proceed with next candidate divisor
}
}
By examining the code carefully, you will find that it contains all the above elements, only put together in a single loop, which is a bit confusing.
UPDATE: In case you are interested, the algorithm you presented has complexity O(base * log n). You can easily make it O(sqrt(base) * log n) by adapting the prime factorization routine slightly:
void factorize(int base) {
for (int p = 2; p*p <= base; ++p) { // only check prime factors up to sqrt(base)
// ... same as before
}
if (base) {
// there is exactly one prime factor > sqrt(base).
// It certainly has multiplicity 1.
// process prime factor base^1
}
}
And of course you can use any other more sophisticated prime factorization algorithm if you want to speed things up even more.
j % 1
will neer have a remainder. – Cheeryp
counts the number of times that the value of variablej
is divisible by the value of variablei
, and it does so only for prime values of variablei
(due to thej /= i
). The loop starts from 2 because this is the smallest prime factor. – Tiliaceous