К содержанию

Задание 25 · Обработка целочисленной информации

Практика и итог

Вся тема на одной странице: как решилась задача темы, главное из подтем, порядок решения и частые ошибки.

Одна задача — вся тема

Задача темы — первые пять чисел больше 7 000 000, равных произведению двух простых с цифрами 1 и 6, — собиралась из функций нескольких подтем. Пролистай версии: точками отмечены строки, которых не было в предыдущей.

  1. Подтема 1, «Перебор и запись числа»: первые пять — while и счётчик. Точками отмечены новые строки.
  2. Подтема 2, «Делители парами»: делители до √n парами.
  3. Подтема 4, «Разложение»: простые множители с повторами.
  4. Подтема 4, «Задача темы»: ровно два множителя, в каждом 1 и 6. Первое число задачи темы — 7 000 421 = 61 · 114 761.

Перебор везде один — меняется проверка числа. Подтема 3 считает делители и величину M, подтема 5 перебирает по маске с шагом, равным делителю, а дополнительный урок по числу делителей узнаёт вид числа, когда отрезок слишком большой для перебора.

Карта темы

Каждая подтема дала одну проверку или способ перебора, и любое решение собирается из них. Сверху — путь от кандидатов к ответу, ниже — по блоку на подтему. Заголовок блока ведёт на подтему.

  1. Кандидатыотрезок, шаг или маска
  2. Проверкаделители, множители, запись
  3. Выводчто и в каком порядке

1Перебор и запись числа

  • первые kwhile found < k, n растёт от границы
  • '6' in str(n)цифра в записи числа

2Делители парами

  • d и n // dd только до isqrt(n)
  • кореньдобавить один раз

3Числа с нужными делителями

  • ровно klen(D) == k
  • MM = 0 — отдельный случай, проверь простые

4Простые числа и разложение

  • len(f)множители с повторами
  • len(set(f))различные простые делители

5Маски

  • кратные krange(0, limit + 1, k)
  • ? и *fnmatch или построить через product

6Вид числа по количеству делителейдополнительный урок

  • 3 делителяэто p²
  • огромный отрезокперебирать p, а не числа
Карта темы: путь к ответу сверху и главное из каждой подтемы. Номер блока — номер подтемы.

Как решать

Любое задание 25 решается одним порядком из пяти шагов. Каждому шагу ты уже учился — под ним номера подтем:

Главный шаг — проверка числа: она должна быть верной и быстрой. Прежде чем запускать её на миллионах чисел, проверь на маленьких, где ответ виден в уме.
for n in [1, 2, 12, 16, 49]:    print(n, get_divisors(n), prime_factors(n))
1 [1] [] 2 [1, 2] [2] 12 [1, 2, 3, 4, 6, 12] [2, 2, 3] 16 [1, 2, 4, 8, 16] [2, 2, 2, 2] 49 [1, 7, 49] [7, 7]

И оцени размер перебора до запуска: десять миллионов простых проверок — секунды, а миллион чисел около 10⁹ с поиском делителей до √n — 3 · 10¹⁰ шагов, слишком долго. Тогда ищи шаг, построение по маске или вид числа.

Частые ошибки

Семь ошибок встречаются чаще других, и каждую ловит один вопрос к себе. Выбери ошибку — увидишь, как её исправить, и вопрос, который её ловит:

range(L, R)
range(L, R) → range(L, R + 1). Спроси себя: проверено ли само число R?подтема 1
корень дважды
у 49 делители 1, 7, 7, 49 → корень добавляют один раз. Спроси себя: сколько делителей у 49?подтема 2
D[-1] без sorted
наибольший делитель — последний добавленный → список сортируют. Спроси себя: что получится у 30?подтема 2
M = 0
«M оканчивается на 0» пропускает простые → у простых M = 0 — тоже подходит. Спроси себя: не попало ли в ответ простое число?подтема 3
if вместо while
каждый множитель вынут один раз → while m % d == 0. Спроси себя: сколько множителей у 72?подтема 4
пустая звёздочка
вставка вместо * начата с длины 1 → * — любые цифры, даже ни одной. Спроси себя: проверено ли число без вставки?подтема 5
ноль впереди
первый ? маски получил 0 → число не начинается с нуля. Спроси себя: не стала ли запись короче маски?подтема 5

Итог

Тема пройдена: задача темы решена от перебора до пяти ответов. Вот что взять с собой.

  • ПорядокКандидаты, проверка, малые числа, размер, вывод.
  • ДелителиПарами до √n, корень один раз.
  • Множителиwhile m % d == 0; len(f) и len(set(f)).
  • МаскиШаг, равный делителю, и fnmatch.
  • Задача темыПервое число — 7 000 421 = 61 · 114 761.

Проверьте себя

Ответь сначала сам, потом открой ответ.

Вопрос 1

Почему делители ищут только до √n?

ОтветСкрыть ответ
Ответ

Делители идут парами d и n // d, и в каждой паре меньший не больше √n: найдя его, сразу получаем и второй.

Вопрос 2

prime_factors(3721) = [61, 61]. Подходит ли 3721 под «произведение ровно двух простых, не обязательно различных»?

ОтветСкрыть ответ
Ответ

Да: len(f) == 2, повторы считаются. «Различных» было бы len(set(f)).

Вопрос 3

Числа до 10⁸, делящиеся на 1301 и подходящие под маску. Как перебирать?

ОтветСкрыть ответ
Ответ

Шагом 1301: range(0, 10**8 + 1, 1301) — в 1301 раз меньше кандидатов, а маску проверяет fnmatch.

Вопрос 4

У каких чисел ровно три делителя?

ОтветСкрыть ответ
Ответ

У квадратов простых: p² делится на 1, p и p².

Практика

Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.

Найди числа с двумя делителями без 1 и n

Найди все числа на отрезке [500 035; 500 055], у которых ровно два различных натуральных делителя, не считая единицы и самого числа. Для каждого числа выведи эти делители в порядке возрастания.

Запишите все строки ответа подряд в одну строку через пробел: в каждой строке число и два его делителя по возрастанию.

Найди пять чисел с наибольшим простым делителем на 7

Пусть M — наибольший простой делитель числа, не считая самого числа. Если таких делителей нет, M = 0. Найди пять наименьших чисел, больших 1 200 000, для которых M больше нуля, не превышает 1000 и оканчивается цифрой 7. Для каждого выведи число и M.

Запишите все строки ответа подряд в одну строку через пробел: в каждой строке число и M.

Найди кратные 1301 по маске 8?4*21

Среди натуральных чисел, не превышающих 10⁸, найди все числа, соответствующие маске 8?4*21 и делящиеся на 1301. Выведи числа в порядке возрастания и частные от деления на 1301.

Запишите все строки ответа подряд в одну строку через пробел: в каждой строке число и частное от деления на 1301.

Найди произведения трёх простых с цифрой 3

Найди пять наименьших чисел, больших 1 000 000, которые представимы в виде произведения ровно трёх простых множителей, не обязательно различных, и каждый множитель содержит в записи цифру 3. Для каждого выведи число и его множители.

Запишите все строки ответа подряд в одну строку через пробел: в каждой строке число и его три множителя по неубыванию.

Найди число с наибольшим количеством делителей

Среди чисел отрезка [200 000; 200 100] найди число с наибольшим количеством натуральных делителей; если таких несколько, выбери наименьшее. Выведи количество делителей и само число.

Введите количество делителей и само число через пробел.