Алгоритм перебора чисел
Назовём нетривиальным делителем натурального числа его делитель, не равный единице и самому числу. Например, у числа 6 есть два нетривиальных делителя: 2 и 3. Найдите все натуральные числа, принадлежащие отрезку [123456789; 223456789] и имеющие ровно три нетривиальных делителя. Для каждого найденного числа запишите в ответе его наибольший нетривиальный делитель. Ответы расположите в порядке возрастания.
maxi = 0
for i in range(123456789, 223456790):
sqrti = i**0.5
numdel = 0
if round(sqrti) == sqrti:
maxdel = 1
for j in range(2, round(sqrti) - 1):
if i % j == 0:
if maxdel == 1: maxdel = i // j
numdel += 2
if numdel == 2: print(i, maxdel)
отрезок большой и программа работает эффективно из-за строки
if round(sqrti) == sqrti:
как это работает с математической точки зрения?
Ответы (1 шт):
Если рассмотреть разложение n = p1e1p2e2p3e3... (где pi - различные простые), то можно догадаться что общее число делителей n равно (e1 + 1)(e2 + 1)(e3 + 1).... В это число входят единица и само n, конечно.
В задаче требуется найти числа с тремя нетривиальными делителями. Всего делителей тогда будет пять. Пять - простое число, единственный способ представить его в виде произведения - это оно само. Следовательно число с тремя нетривиальными делителями (с пятью делителями вообще) имеет разложение вида p4. То есть, мы ищем четвертые степени простых чисел, а максимальным нетривиальным делителем будет куб p3.
Условие round(sqrti) == sqrti выполняется только для целых чисел, которые являются квадратами других целых чисел. А так как нам интересны четвёртые степени (которые и квадраты тоже), то условие эффективно сужает число кандидатов.
Ваш пример работает у меня около сорока секунд. Но можно сделать лучше.
Код который перебирает четвёртые степени простых работает 0.05с. Проверка простоты кандидатов написана просто и не эффективно, так как самое большое число, которое надо будет проверять на простоту - 122 (корень четвёртой степени из правого конца диапазона):
m = 2
while True:
n = m ** 4
if 223456789 < n:
break
if 123456789 <= n:
# is m prime?
if all(m % i != 0 for i in range(2, m)):
print(n, m ** 3)
m += 1
$ time python nums.py 131079601 1225043 141158161 1295029 163047361 1442897 real 0m0.047s user 0m0.032s sys 0m0.012s