Курс№25. Маски и делители0%
Теория · номер 25 из 27

Маски и делители

Ищем числа, которые подходят под маску или имеют нужные делители. Перебор на Python, главное записать условие и не считать лишнего.

6 разделов~35 минут1 первичный балл
  1. 1Что проверяет номер
  2. 2Маски
  3. 3Множители: p, good, f
  4. 4Разложение на простые множители
  5. 5Ловушки
  6. 6Домашка
Раздел 1 из 6

Что проверяет номер

Перебор чисел тут большой, поэтому важно не делать лишнего. Если число заведомо кратно какому-то значению, идём по диапазону с этим шагом: цикл станет в десятки раз короче.

Два вида условий: (1) числа, подходящие под маску (123*4?5) и делящиеся на K, с выводом числа и частного; (2) числа с особыми делителями: количество делителей, произведение двух простых, M по простым делителям.

Простыми словами

Маска это шаблон для записи числа, как поиск по файлам. Знак ? значит «ровно одна любая цифра». Знак * значит «сколько угодно любых цифр, можно и ни одной». Под маску 1*3 подходят 13 и 1503, а под 1?3 подойдёт 123, но не подойдёт 13.

Делитель это число, на которое делится без остатка. Делители ходят парами: 1099 делится на 7, значит, и на 1099 // 7 = 157. Поэтому искать делители дальше корня незачем: всех больших мы получаем как пару к маленьким. Это сильно ускоряет код.

Простое число делится только на 1 и на себя. Разложить число на простые множители значит записать его как произведение простых: 1099 = 7 · 157.

Раздел 2 из 6

Маски

Маска описывает запись числа: ? это ровно один символ, * любое их количество, в том числе ноль. Функция fnmatch делает такую проверку за нас, надо только привести число к строке.

python
from fnmatch import fnmatch
for x in range(1_000_008, 5_000_000, 17):          # шаг по кратности
    if fnmatch(str(x), '12*3?4') and x % 17 == 0:
        print(x, x // 17)
Попробуй самучебная задача

Сколько чисел, не превышающих 10⁶, подходят под маску 12?4* и делятся на 37?

Подсказка

fnmatch(str(x), '12?4*'), шаг цикла 37.

Как читать маску

маскачислоподходит?
1?3123да
1?313нет: ? требует ровно один символ
1*313да: * может быть пустой
1*31503да
1*31504нет: последняя цифра не 3
Попробуй самучебная задача

Сколько чисел, не превышающих 10⁵, подходят под маску 5*7 и делятся на 13?

Раздел 3 из 6

Множители: p, good, f

Делители идут парами: если нашли d, то x // d тоже делитель. Поэтому достаточно идти до корня из числа.

Для чисел вида «произведение двух простых, у каждого есть нужная цифра»:

python
def p(x):                                      # простое ли число
    return x > 1 and all(x % d != 0 for d in range(2, int(x ** 0.5) + 1))

def good(x):                                   # простое и ровно одна «5» в записи (в задаче подставь свою комбинацию)
    return str(x).count('5') == 1 and p(x)

def f(x):
    D = []
    for d in range(2, int(x ** 0.5) + 1):      # делители до корня
        if x % d == 0:
            if good(d) and good(x // d):       # и d, и пара к нему подходят
                D.append(d)
                D.append(x // d)
    return D

n = 0
for x in range(2000001, 10 ** 20):             # с числа, следующего за N
    D = f(x)
    if len(D) == 2:                            # ровно одна подходящая пара
        print(x, min(D))                       # если нужен наибольший, пиши max(D)
        n += 1
        if n == 5:
            break

Заменяешь '5' на комбинацию из условия и начало диапазона на N + 1. Если нужен наибольший множитель, пишешь max(D).

Разбор кода по функциям

Посмотрим на примере с цифрой 7 вместо 5. Число 1099 делится на 7, и 1099 // 7 = 157. Оба простые, в каждом одна семёрка, поэтому D = [7, 157], и его длина 2. А число 1100 делится на 2, но 2 без семёрки, и пара не подойдёт. Ни один делитель не проходит проверку, и D останется пустым.

Почему проверяем len(D) == 2? Если число это произведение ровно двух простых, такая пара одна, и в D будет два числа. У числа с большим количеством множителей делители составные, и good их отсеет.

Почему до 10 ** 20? Это просто очень далёкая граница. Цикл всё равно остановится через break, когда найдёт пять чисел. Условие обычно просит первые пять после N.

Попробуй самучебная задача

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

Почему до корня

Возьмём 1099. Его делитель 7 найдётся быстро, а пара к нему 1099 // 7 = 157 получается сразу. Если бы у числа не было делителей до корня, их не было бы и после, потому что каждый большой делитель идёт в паре с маленьким.

Попробуй самучебная задача

Сколько всего делителей у числа 1001, включая 1 и само число?

Раздел 4 из 6

Разложение на простые множители

Рекурсия отщепляет по одному наименьшему множителю, пока не останется простое число.

Для M по простым делителям:

python
def razl(x):
    for i in range(2, int(x ** 0.5) + 1):
        if x % i == 0:
            return [i] + razl(x // i)          # нашли делитель, раскладываем остаток
    return [x]                                  # простое число

razl(x) возвращает список простых множителей (с повторами). Из него берём наименьший min и наибольший max. Для простого числа в списке один элемент, делителей нет и M = 0.

python
n = 0
for x in range(1000000, 10 ** 20):
    r = razl(x)
    if len(r) == 1:                             # простое: M = 0, пропускаем
        continue
    s = set(r)
    m = max(s) - min(s)
    if str(m).count('1') >= 2 and p(m):          # условие из задачи
        print(x, m)
        n += 1
        if n == 5:
            break
Попробуй самучебная задача

Для числа x пусть M это разность наибольшего и наименьшего простых делителей. Найди первое x больше 1000, у которого M простое и больше 100. Запиши x и M через пробел.

Раздел 5 из 6

Ловушки

Ловушка

«Ровно одна комбинация цифр»: str(p).count('67') == 1 (для 67 в 6767 ответ 2).

Ловушка

Не путай «число содержит комбинацию» и «каждый из множителей содержит». Часто комбинация относится именно к множителям.

Ловушка

Множители не обязательно различны: учитывай p == q.

Ловушка

Простота: проверяй до корня, а для больших M — Миллером–Рабином.

Ловушка

Условие «в своём написании» может относиться к M, а не к самому числу: читай внимательно.

Раздел 6 из 6

Домашка

Задачи с настоящих экзаменов и из банка ФИПИ. Решай прямо здесь: кнопка «Решать здесь» открывает редактор, а код каждой задачи сохраняется.

Задачи «Попробуй сам» учебные, в домашке задачи с настоящих экзаменов и из банка ФИПИ. Код в блоках можно менять и запускать, он выполняется прямо в браузере.