Instead of counting the divisors directly, you can use this formula (taken from Wikipedia):
This will help you find the number of divisors for all square/cube/to the power of k
numbers (nk) while using O(n)
memory.
// Stores the number of divisors for n^k
count[n + 1]
// Count number of divisors for 1^k, 2^k, ..., n^k
function countDivisors(n, k) {
// Note: You can actually merge sieve function with the loop below
prime[] = sieve(n)
count[0] = 0
count[1..n] = 1 // Set count[i] to count[n] to 1
for all primes p <= n {
for (i = 1; p^i <= n; i++) {
// You can cache the value of p^i for next loop
pi = p^i
for (m = pi; m <= n; m += pi) {
// We "replace" the previous count with current count
count[m] = count[m] / ((i - 1) * k + 1) * (i * k + 1)
}
}
}
}
To extend it to a*nk, find the prime factorization of a, and record the prime numbers along with the corresponding power.
- If any prime is larger than n, you can take them away and reduce them to a multiplier according to the divisor function.
If any prime is smaller than n, supply it to the
countDivisors
function above, and modify the function a bit:for all primes p <= n { // Note: You are free to optimize this in actual code let e be maximal power of p in a if (e > 0) { // Update all number with the factors from a for (i = 1; i <= n; i++) { count[i] *= (e + 1) } } for (i = 1; p^i <= n; i++) { // You can cache the value of p^i for next loop pi = p^i for (m = pi; m <= n; m += pi) { // We "replace" the previous count with current count count[m] = count[m] / ((i - 1) * k + e + 1) * (i * k + e + 1) } } }
As you can see, the time and space complexity does not depend on the power k
, and only depends on n
, the number of numbers whose number of divisors you want to find.