На этой странице вы узнаете
- Как быстро работает программа?
- Есть ли смысл перебирать делители после корня?
- Что количество делителей может сказать о самом числе?
Гадание на кофейной гуще или на картах Таро? Может, на ромашке? Хотя лучше не доверять свои отношения цветку. Наша судьба — только в наших руках. А судьба чисел предопределена заранее. Сегодня мы будем предсказывать их жизнь и судьбу по делителям. Но главная проблема — найти эти делители.

Постановка проблемы. Переборное решение
Встречали ли вы странных персонажей в задачах, которым резко понадобилось купить 50 арбузов? А что подумаете, если ваш учитель математики задаст найти число, у которого 50 делителей?
Поиск делителей в математике не самый сложный процесс. Есть разные способы: разложение на простые множители, обычный перебор и так далее. Сложность задания будет зависеть от самого числа. Довольно быстро получится найти делители числа 24 — число небольшое, красивое, удобное. Нахождение делителей числа 1234567 займет гораздо больше времени.
Я предлагаю включить компьютер, открыть среду разработки и заставить код сделать за нас всю работу.
Идея в следующем:
- Создадим список, в который мы сохраним все делители числа.
- С помощью цикла for переберем все числа из диапазона от 1 до самого числа.
- Если в переборе мы нашли такое число, которое является делителем исходного — остаток от деления будет равен 0 — сохраним это число в список.
В итоге мы получим список всех делителей исходного числа.
number = 1234567
dels = []
for i in range(1, number + 1):
if number % i == 0:
dels.append(i)
print(dels)
_____________________________________________________________________
Вывод: [1, 127, 9721, 1234567]
У этого метода есть очень большая проблема — время его работы.
Программа выполняет команды очень быстро, но не бесконечно быстро.
Время работы программы можно измерить. Например, Sublime Text 3 занимается этим автоматически. И он помог посчитать, что программа выше выполнилась за 0.2 секунды. Давайте постепенно повышать ставки и смотреть, сколько времени понадобится этой же программе для поиска делителей других чисел:
— число 1234567 — 0.2 секунды;
— число 12345670 — 0.9 секунды;
— число 123456700 — 8.0 секунд;
— число 1234567000 — 115.7 секунд.
С числом 1234567 программа сделала 1234567 шагов цикла for, и справилась неимоверно быстро. Но чем больше ей придется выполнять команд, тем дольше придется работать.
Замеры времени зависят от многих факторов, например, мощности компьютера. Но мы можем повысить эффективность работы программы.
Ускоренный перебор делителей
Идея ускоренного перебора делителей заключается в том, что, найдя один делитель, мы сразу можем подобрать второй — его пару.
Возьмем число 24. Найдя его делитель 2, мы сразу можем сказать, что у 24 есть еще один делитель — 12, потому что 12 = 24 / 2. Интересная мысль? Давайте ее развивать.
Найдем по такой логике все делители числа 16.
- Самый простой делитель числа — 1. И по этой логике сразу найдем второй делитель — само число 16, так как 16 / 1 = 16.

- Проверим число 2. Это делитель, так что сразу найдем его пару: 16 / 2 = 8.

- Проверяем число 3 — это не делитель, его просто пропускаем.

- При проверке числа 4 мы столкнемся с интересной ситуацией. Его парой будет 16 / 4 = 4 — то же самое число, а мы ищем различные пары. Значит, у корня числа пары не будет: найдя корень, мы найдем только один делитель.

Если мы продолжим перебор, числа 5, 6 и 7 — не будут делителями. А за ними — 8, делитель, который мы уже нашли.
Нет. Найдя “маленький” делитель, при ускоренном переборе мы можем найти его пару, которая будет “большим” делителем. Перебирая делители, рано или поздно мы дойдем до корня числа, у которого нет пары. Перебирая числа после корня, мы будем находить только “большие” делители, которые уже нашли в паре с “маленькими”.
Если у числа целого корня нет, перебираем до его округленного вниз значения.
Нам нет смысла перебирать числа после корня, так что будем перебирать до предельно близкого к нему значения, но не больше.
Логика программы будет такой:
- Перебираем числа от 1 до корня исходного числа.
- Если мы нашли корень числа, добавляем в список делителей только его.
- Если мы нашли не корень, а обычный делитель — добавляем в список сразу пару делителей.
Пример реализации ускоренного перебора делителей для числа 1234567000:
number = 1234567000
dels = []
for i in range(1, int(number ** 0.5) + 1):
if i * i == number:
dels.append(i)
elif number % i == 0:
dels.append(i)
dels.append(number // i)
print(len(dels))
_____________________________________________________________________
Вывод: 64
Эта программа нашла все делители числа и выдала их количество — 64. А на ее работу ушло меньше секунды.
Но и это не панацея. Что, если нам придется проверить делители сразу нескольких чисел? Например, мы хотим найти все числа, у которых ровно 7 делителей, в диапазоне от 1 до 10000.
Программу надо немного модифицировать:
- заведем переменную-счетчик, которая будет считать подходящие числа;
- number сделаем перебираемой переменной по нужному диапазону с помощью цикла for;
- ускоренный перебор будет внутри перебора number;
- в конце каждого шага цикла проверяем — если делителей у числа ровно 7, то увеличиваем наш счетчик на 1.
Теперь программа будет выглядеть следующим образом:
count = 0
for number in range(1, 10000):
dels = []
for i in range(1, int(number ** 0.5) + 1):
if i * i == number:
dels.append(i)
elif number % i == 0:
dels.append(i)
dels.append(number // i)
if len(dels) == 7:
count += 1
print(count)
_____________________________________________________________________
Вывод: 2
Эта программа работала всего 0.2 секунды. Звучит неплохо, но давайте снова поднимать ставки:
- диапазон 1 — 10000 — 0.2 секунды;
- диапазон 1 — 100000 — 2.6 секунды;
- диапазон 1 — 1000000 — 80.2 секунды.
Время снова увеличивается очень быстро. Что можно с этим сделать?
Еще более ускоренный перебор делителей
Не считаем, что не нужно
Обратите внимание — программа выше нашла среди чисел 1–10000 всего 2 числа, имеющих ровно 7 делителей. А сколько же у остальных? Может быть и больше, может быть и меньше. Например, у числа 9864 делителей аж 24 штуки. Стоило ли тратить время на поиск их всех, если количество делителей больше 7?
Конечно, нет. Как только мы нашли 8 штук, мы уже можем понять, что анализировать число далее нам неинтересно. Значит, нужно остановить работу цикла.
Команда break полностью останавливает работу цикла.
Мы можем модернизировать нашу последнюю программу: если в переборе делителей мы увидим, что их больше семи, завершаем цикл командой break.
count = 0
for number in range(1, 10000):
dels = []
for i in range(1, int(number ** 0.5) + 1):
if i * i == number:
dels.append(i)
elif number % i == 0:
dels.append(i)
dels.append(number // i)
if len(dels) > 7:
break
if len(dels) == 7:
count += 1
print(count)
При этом завершится именно цикл перебора делителей i, так как break находится именно в нем, а цикл перебора number продолжит свою работу.
Давайте произведем замеры еще раз:
- диапазон 1-10000 — 0.2 секунды;
- диапазон 1-100000 — 2.1 секунды;
- диапазон 1-1000000 — 53.5 секунды.
В последнем случае мы сэкономили около трети от времени работы программы. Но и это не предел.
Не считаем, что не нужно 2.0
Вернемся на несколько абзацев выше, когда мы искали делители числа 16. Мы нашли 5 делителей — 2 пары и 1 корень, который не даст пару. Это справедливо для любого числа: целый корень не будет давать пару ни с каким другим числом, а все остальные делители — будут.
Если у числа есть целый корень, количество делителей числа будет нечетным, так как корень не даст пару ни с кем.
Если же у числа целого корня нет — количество его делителей будет четным, так как все делители будут иметь пару.
Нам нужны числа, у которых ровно 7 делителей. Следовательно, нам нужны числа, у которых есть целый корень. Это можно проверить, вычислив точный корень числа и его округленное значение. Если они совпадут, значит, округлять корень было некуда и он целый.
Но как пропускать числа, которые нам не нужны?
Команда continue останавливает работу текущего шага цикла и сразу переходит к следующему.
Если мы найдем число number, у которого нет целого корня, мы можем применить команду continue: данный шаг цикла перебора number завершается, и мы сразу перейдем к следующему.
Включить эту проверку в программу можно следующим образом:
count = 0
for number in range(1, 10000):
if number ** 0.5 != int(number ** 0.5):
continue
dels = []
for i in range(1, int(number ** 0.5) + 1):
if i * i == number:
dels.append(i)
elif number % i == 0:
dels.append(i)
dels.append(number // i)
if len(dels) > 7:
break
if len(dels) == 7:
count += 1
print(count)
Снова посмотрим на время работы программы при разных диапазонах:
- диапазон 1-100000 — 0.1 секунды;
- диапазон 1-1000000 — 0.5 секунды;
- диапазон 1-10000000 — 4.5 секунды;
- диапазон 1-100000000 — 44.4 секунды.
А делители — это вообще для чего? А таблицы со временем — это точно важно? Может, подождать проще, чем учить все это?
Нахождению делителей чисел посвящена задача 25 ЕГЭ, и без этих теоретических знаний решить ее крайне сложно. Что же касается времени работы, то за ним приходится следить внимательнейшим образом, ведь в задачах могут встречаться ситуации, когда надо найти делители для сотен миллионов чисел за раз!
Зная все особенности ускорения перебора делителей и поиска чисел с конкретными делителями, за считанные секунды можно решать задачи огромных диапазонов.
Фактчек
- Ускоренный перебор делителей подразумевает нахождение делителей попарно, при этом перебирать делители достаточно только до корня числа.
- Команда break полностью останавливает работу цикла, а команда continue завершает работу лишь текущего шага цикла, перенося нас сразу на следующий.
- Если у числа есть целый корень, количество делителей числа будет нечетным, так как корень не даст пару ни с кем. Если же у числа целого корня нет — количество его делителей будет четным, так как все делители будут иметь пару.
Проверь себя
Задание 1.
Для чего нужен ускоренный перебор делителей?
- Обычный перебор слишком скучный
- Для большей точности вычислений
- Для ускорения работы программы
Задание 2.
Найдите количество делителей числа 2568568668.
- 5
- 6
- 7
- 8
Задание 3.
Найдите, сколько чисел из диапазона от 2000 до 1002000 имеют ровно 5 делителей.
- Ни одного
- 1
- 10
- 8
Ответы: 1. — 3; 2. — 3; 3. — 4.
If your PC has tons of memory, a brute single line can be fast enough with numpy:
N = 10000000; tst = np.arange(1, N); tst[np.mod(N, tst) == 0]
Out:
array([ 1, 2, 4, 5, 8, 10, 16,
20, 25, 32, 40, 50, 64, 80,
100, 125, 128, 160, 200, 250, 320,
400, 500, 625, 640, 800, 1000, 1250,
1600, 2000, 2500, 3125, 3200, 4000, 5000,
6250, 8000, 10000, 12500, 15625, 16000, 20000,
25000, 31250, 40000, 50000, 62500, 78125, 80000,
100000, 125000, 156250, 200000, 250000, 312500, 400000,
500000, 625000, 1000000, 1250000, 2000000, 2500000, 5000000])
Takes less than 1s on my slow PC.
Более быстрый способ нахождения всех делителей числа?
Хочу узнать, какой наиболее быстрый способ нахождения всех делителей числа есть?( в среднем случае )
Пользовался всегда данным(указанным ниже) куском кода, но решал простые задачи. Когда дело пришло к большим цифрам, понял, что он не самый эффективный.
Код:
import collections
import itertools
def get_prime_divisors(n):
i = 2
while i * i <= n:
if n % i == 0:
n /= i
yield i
else:
i += 1
if n > 1:
yield n
def calc_product(iterable):
acc = 1
for i in iterable:
acc *= i
return acc
def get_all_divisors(n):
primes = get_prime_divisors(n)
primes_counted = collections.Counter(primes)
divisors_exponentiated = [
[div ** i for i in range(count + 1)]
for div, count in primes_counted.items()
]
for prime_exp_combination in itertools.product(*divisors_exponentiated):
yield calc_product(prime_exp_combination)
P.s: Сам код взял из интернета, ибо в первый раз не было времени придумывать свой велосипед.
-
Вопрос задан11 сент. 2022
-
312 просмотров
Пригласить эксперта
Суть вопроса — алгоритм факторизации.
Чтобы ускорить факторизацию есть много путей. Во первых — отказаться от языка Python в пользу C++ или Rust.
Во вторых — запоминать найденные primes и использовать их для следующего шага. Грубо говоря факторизация требует эффективного генератора primes. А он в свою очередь… Саморекурсивен. Требует такого-же генератора меньшей мощности.
И step надо делать не по 1 элементу а по нечётным начиная с 3.
Есть ещё алгоритм Эратосфена. Обрати внимание.
И есть очень глобальная задача, такая как доказательство простоты. Для нее есть целый список алгоритмов. Они сложные и интересные. Часть из них — вероятностные. Используются в критпографии.
Это самый быстрый способ факторизации одного числа. Если не хватает, то может в задаче можно факторизовать все числа сразу. Каким нибудь решетом можно найти минимальный делитель для всех чисел до n за O(n). Дальше каждое число раскладывается на множители моментально.
Я нахожу все делители числа в SageMath (https://www.sagemath.org):
sage: 256893450689.divisors()
[1, 19, 13520707931, 256893450689]
sage: 252323674611367475532285533.divisors()
[1, 110933, 2267937467, 1002919711403, 251589107026711, 111256892345068999, 2274559189883690836201, 252323674611367475532285533]
-
Показать ещё
Загружается…
25 мая 2023, в 02:38
1000 руб./за проект
25 мая 2023, в 02:31
800 руб./за проект
25 мая 2023, в 01:56
1200 руб./за проект
Минуточку внимания
Загрузить PDF
Загрузить PDF
Число называется делителем (или множителем) другого числа в том случае, если при делении на него получается целый результат без остатка.[1]
Для малого числа (например, 6) определить количество делителей довольно легко: достаточно выписать все возможные произведения двух целых чисел, которые дают заданное число. При работе с большими числами определить количество делителей становится сложнее. Тем не менее, если вы разложите целое число на простые множители, то легко сможете определить число делителей с помощью простой формулы.
-
1
Запишите заданное целое число вверху страницы. Вам понадобится достаточно места для того, чтобы расположить ниже числа дерево множителей. Для разложения числа на простые множители можно использовать и другие методы, которые вы найдете в статье Как разложить число на множители.
- Например, если вы хотите узнать, сколько делителей, или множителей имеет число 24, запишите
вверху страницы.
- Например, если вы хотите узнать, сколько делителей, или множителей имеет число 24, запишите
-
2
Найдите два числа (помимо 1), при перемножении которых получается заданное число. Таким образом вы найдете два делителя, или множителя данного числа. Проведите от данного числа две ветки вниз и запишите на их концах полученные множители.
-
3
Поищите простые множители. Простым множителем называется такое число, которое делится без остатка лишь на само себя и на 1.[2]
Например, число 7 является простым множителем, так как оно делится без остатка лишь на 1 и 7. Для удобства обводите найденные простые множители кружком.- Например, 2 является простым числом, поэтому обведите
кружком.
- Например, 2 является простым числом, поэтому обведите
-
4
Продолжайте раскладывать составные (не простые) числа на множители. Проводите следующие ветки от составных чисел до тех пор, пока все множители не станут простыми. Не забывайте обводить простые числа кружками.
-
5
Представьте каждый простой множитель в степенной форме. Для этого подсчитайте, сколько раз встречается каждый простой множитель в нарисованном дереве множителей. Это число и будет степенью, в которую необходимо возвести данный простой множитель.[3]
-
6
Запишите разложение числа на простые множители. Первоначально заданное число равно произведению простых множителей в соответствующих степенях.
- В нашем примере
.
Реклама
- В нашем примере
-
1
-
2
Подставьте в формулу величины степеней. Будьте внимательны и используйте степени при простых множителях, а не сами множители.
-
3
Сложите величины в скобках. Просто прибавьте 1 к каждой степени.
-
4
Перемножьте полученные величины. В результате вы определите количество делителей, или множителей данного числа
.
Реклама
Советы
- Если число представляет собой квадрат целого числа (например, 36 является квадратом числа 6), то оно имеет нечетное количество делителей. Если же число не является квадратом другого целого числа, количество его делителей четно.
Реклама
Похожие статьи
Об этой статье
Эту страницу просматривали 120 968 раз.
Была ли эта статья полезной?
На чтение 6 мин Просмотров 2.1к. Опубликовано
При работе с числами в программировании зачастую бывает нужно найти количество делителей для данного числа. Например, при работе с задачами на поиск простых чисел или при вычислении наибольшего общего делителя. В этой статье мы рассмотрим несколько способов, как найти количество делителей числа в языке программирования Python.
Содержание
- Что такое делители числа
- Нахождение количества делителей числа с помощью цикла и проверки на остаток от деления
- Нахождение количества делителей числа с помощью математических свойств чисел
- Используем свойство: Если число n имеет делитель d, то оно также имеет делитель n/d
- Используем разложение на простые множители
Что такое делители числа
В математике делителем натурального числа называют все числа, на которые это число делится без остатка. Например, делителями числа 12 являются числа 1, 2, 3, 4, 6 и 12, так как 12 делится на каждое из этих чисел без остатка. Количество делителей числа может быть разным в зависимости от самого числа. Например, у числа 12 имеется 6 делителей, а у числа 17 только 2 делителя (1 и само число).
Нахождение количества делителей числа с помощью цикла и проверки на остаток от деления
Для нахождения количества делителей числа можно использовать цикл и проверку на остаток от деления. Идея заключается в том, что мы перебираем все числа от 1 до самого числа и проверяем, делится ли число на каждое из этих чисел без остатка. Если да, то это число является делителем и мы увеличиваем счетчик делителей на 1.
Вот пример кода на Python, который иллюстрирует этот подход:
num = int(input("Введите число: "))
count = 0
for i in range(1, num+1):
if num % i == 0:
count += 1
print("Количество делителей числа", num, "равно", count)
В этом примере мы сначала запрашиваем у пользователя число, затем проходим по всем целым числам от 1 до введенного числа (включительно) с помощью цикла for. Для каждого числа в этом диапазоне мы проверяем, является ли оно делителем введенного числа (то есть, делится ли число нацело на i). Если да, то увеличиваем счетчик делителей на 1. В конце выводим количество найденных делителей на экран.
Такой подход работает для любых чисел, включая большие числа. Однако, при больших числах он может работать медленно, поскольку требует перебора всех чисел от 1 до n. Далее мы рассмотрим более эффективные способы нахождения количества делителей числа.
Нахождение количества делителей числа с помощью математических свойств чисел
Используем свойство: Если число n имеет делитель d, то оно также имеет делитель n/d
Данный способ основан на математическом свойстве, что если число n имеет делитель d, то оно также имеет делитель n/d. Исходя из этого свойства, можно заметить, что достаточно искать делители только до квадратного корня числа n, так как все остальные делители можно получить путем деления n на найденный делитель до квадратного корня.
Таким образом, для нахождения всех делителей числа n, мы можем использовать цикл от 1 до int(sqrt(n))+1, и проверять, является ли i делителем n, если да, то добавлять i и n/i в список делителей.
Например, для числа n=100, квадратный корень из него равен 10. Поэтому, достаточно проверить делители от 1 до 11 (включая 10). Если делитель найден, то мы можем добавить его и соответствующий делитель, найденный путем деления n на найденный делитель, в список делителей. Таким образом, делители числа 100 будут: [1, 2, 4, 5, 10, 20, 25, 50, 100].
Вот пример кода на Python, который использует данный подход
import math
def count_divisors(num):
# Инициализация счетчика делителей
div_count = 0
# Находим квадратный корень из числа
sqrt_num = int(math.sqrt(num))
# Проверяем числа от 1 до квадратного корня num
for i in range(1, sqrt_num + 1):
if num % i == 0:
# Если i является делителем, увеличиваем счетчик на 1
div_count += 1
# Проверяем, является ли num/i также делителем (чтобы избежать дублирования)
if i != num // i:
div_count += 1
# Возвращаем общее количество делителей
return div_count
Эта функция принимает один аргумент num, который является целым числом. Она использует функцию sqrt() из модуля math, чтобы найти квадратный корень из числа, и затем проверяет все числа от 1 до этого корня на предмет деления на num. Если число делится без остатка, оно добавляется к счетчику делителей div_count. Затем функция проверяет, является ли num делителем num/i, чтобы избежать дублирования. Наконец, функция возвращает общее количество делителей.
Данный способ эффективнее, чем перебор всех чисел до n-1, так как число проверок уменьшается в два раза. Однако, при использовании больших чисел, лучше использовать другие методы, например, разложение на простые множители.
Используем разложение на простые множители
Другой способ нахождения количества делителей числа заключается в использовании его математических свойств. Если мы знаем разложение числа на простые множители, то количество делителей числа можно легко вычислить.
Действительно, пусть дано число n = p_1^k_1 * p_2^k_2 * … * p_m^k_m, где p_1, p_2, …, p_m — простые числа, а k_1, k_2, …, k_m — их степени. Тогда каждый делитель числа n можно представить в виде d = p_1^i_1 * p_2^i_2 * … * p_m^i_m, где 0 <= i_j <= k_j для всех j от 1 до m. Таким образом, общее количество делителей числа n равно произведению (k_1 + 1) * (k_2 + 1) * … * (k_m + 1).
Для примера, давайте рассмотрим число 24. Его разложение на простые множители выглядит так: 24 = 2^3 * 3^1. Тогда количество делителей числа 24 равно (3 + 1) * (1 + 1) = 8. Это означает, что у числа 24 есть 8 делителей, а именно: 1, 2, 3, 4, 6, 8, 12 и 24.
Для вычисления количества делителей числа с помощью его разложения на простые множители в Python, нам необходимо воспользоваться функцией factorize() из библиотеки sympy. Она разлагает число на простые множители и возвращает список кортежей, каждый из которых содержит простой множитель и его степень. Затем мы можем вычислить количество делителей по формуле, описанной выше, и вернуть результат.
Вот пример кода, использующий функцию factorize() из библиотеки sympy для нахождения количества делителей числа:
from sympy import factorint
def count_divisors(n):
factors = factorint(n)
count = 1
for factor in factors.values():
count *= (factor + 1)
return count
n = 24
print(f"Количество делителей числа {n}: {count_divisors(n)}")
Здесь мы сначала импортируем функцию factorint() из библиотеки sympy. Затем определяем функцию count_divisors(), которая принимает на вход число n и возвращает количество его делителей. Внутри функции мы используем функцию factorint() для разложения числа на простые множители и получаем словарь, где ключами являются простые множители, а значениями — их степени. Далее мы вычисляем количество делителей числа с помощью формулы, основанной на свойствах простых множителей, и возвращаем результат.
Затем мы просто вызываем функцию count_divisors() для числа 24 и выводим результат на экран. В данном случае результат будет равен 8, что соответствует количеству делителей числа 24 (1, 2, 3, 4, 6, 8, 12 и 24).

