Take an odd number n
. If this odd number n
has an odd divisor m
, then n/m
is also an odd number. But that means that odd divisors come in pairs, m
and n/m
. The only way the number n
can have 5 odd divisors is if some pair actually has the same numbers, i.e. m = n/m
. But that means that n = m*m
, i.e. n
must be a square of an odd number. So, you don't need to check all odd numbers in the range, just check odd numbers which are squares of an odd number.
Now consider an even number n
. Let's divide this number by 2 until we get an odd number m
(for example, from n=40
we get 40 -> 20 -> 10 -> 5
, so m = 5
). Any odd divisor of m
will be also an odd divisor of n
and vice versa. So, n
and m
have the same number of odd divisors. So, as we see above, number m
must be a square of an odd number. It means, that n
must be a square of an odd number multiplied by some power of two. It means that you don't need to check every even number in your range, check only those, which are squares of an odd number multiplied by some power of 2.
UPDATE
Below are sample implementations:
def method1(a, b):
result = []
for n in range(a, b + 1):
m = n
while (m > 1) and (m % 2 == 0):
m /= 2
root = int(m ** 0.5 + 0.5)
if root * root != m:
continue
count = 0
for i in range (3, root):
if (i % 2 == 0) or (m % i != 0):
continue
count += 1
if count > 1:
break
if count == 1:
result.append(n)
return result
def generate_primes(start, end):
result = []
for n in range(start, end + 1):
if n % 2 == 0:
continue
root = int(n ** 0.5 + 0.5)
for i in range(3, root + 1):
if n % i == 0:
break
else:
result.append(n)
return result
def method2(a, b):
result = []
primes = generate_primes(3, int(b ** 0.25 + 0.5))
for p in primes:
n = p**4
while n < a:
n *= 2
while n <= b:
result.append(n)
n *= 2
return sorted(result)
a = 45000000
b = 50000000
print(method1(a, b))
print(method2(a, b))
The first method1
uses the approach described above. The second method2
uses a more advanced approach and is about 100 times faster. The idea of the second method is to generate all prime numbers between 3 and the fourth root of the upper bound of the interval (50000000 in our case, so prime numbers must not be larger than 84). Then we make 4th power of all these prime numbers and try to multiply them by 2 until we get inside the required interval. Both methods produce the same output
[45212176, 45265984, 47458321, 48469444]
Below is a long proof that method 2 works:
To understand how method 2 works we need to continue our analysis for method 1. We know, that in order to have 5 divisors our number n
must be equal to a square of an odd number multiplied by a power of two:
n = m*m * (some power of 2)
where m
is some odd number. The number m*m
must have exactly 5 odd divisors. However, we already know 3 of them: 1, m
, and m*m
. So, there should exist just 2 more odd divisors of m*m
, only one of them will be between 1 and m
.
Let's denote the first odd divisor as p
(it should be between 1 and m
). Then the second odd divisor is m*m/p
. The number p
must be prime. If it is not, then any divisor of p
will be also a divisor of m*m
. We know that the second divisor is m*m/p
, so m*m
must be divisible by p
. But because p
is prime m
should also be divisible by p
: m = p*x
, where x is some (odd) number. But if x
is not equal to p
, then we have found another number x
between 1 and m
which is a divisor of m*m
. This is not possible, so x
must be equal to p
and m = p*p
. So, we have proven, that m*m = p^4
, i.e. our number n
must be the fourth power of a prime number multiplied by some power of 2.