К содержанию

Подтема 5 из 6

Цепочки до базы и перебор n

Аргумент шагает через несколько чисел или уходит в другую функцию — считаем переходы до базы. А когда спрашивают n — перебираем.

Цепочки с шагом

Что если аргумент уменьшается не на 1, а сразу на 3?

Тогда от каждого n идёт своя цепочка аргументов. Считаем, сколько в ней переходов до базы и на каком числе она в базу попадёт. Пусть F(n) = n при n ≤ 5; F(n) = F(n − 3) + 4 при n > 5.

F(20): аргументы 20, 17, 14, 11, 8, 5 — пять переходов по 4. F(20) = F(5) + 5 · 4 = 25. А у F(21) цепочка другая: 21, 18, 15, 12, 9, 6, 3 — шесть переходов, и попадает она в 3. F(21) = 3 + 6 · 4 = 27.

Шаг −3: цепочка от 20 входит в базу n ≤ 5 ровно в 5 после 5 переходов, цепочка от 21 — в 3 после 6 переходов. Конец цепочки зависит от остатка при делении на 3.

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

Тонкости:число переходов формулой

После k переходов аргумент равен n − 3k. Нужно наименьшее k, при котором n − 3k ≤ 5, то есть k ≥ (n − 5) / 3 с округлением вверх. В Python: k = (n - 5 + 2) // 3 — прибавка 2 перед делением на 3 и даёт округление вверх. Но сначала уверенно считай переходы по цепочке: формула только сокращает понятное рассуждение.

Разность разных цепочек

Что делать с разностью, если аргументы лежат на разных цепочках? Например: F(n) = n при n ≥ 1000; F(n) = n + F(n + 2) при n < 1000. Найдём F(11) − F(10).

От 11 аргумент идёт по нечётным числам, от 10 — по чётным, и общего значения у них нет. Тогда обе суммы расписывают целиком и вычитают слагаемые парами.

F(11) = 11 + 13 + … + 999 + F(1001) = 11 + 13 + … + 999 + 1001. F(10) = 10 + 12 + … + 998 + F(1000) = 10 + 12 + … + 998 + 1000.

Под каждым слагаемым F(11) стоит слагаемое F(10), меньшее на 1. Пар 495, и базы тоже отличаются на 1.

Пар столько, сколько чисел 10, 12, …, 998: (998 − 10) / 2 + 1 = 495. Каждая пара даёт 1, и базы 1001 и 1000 — ещё 1. Ответ: 495 + 1 = 496.

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

Две функции в разные стороны

А если одна функция переходит в другую и их аргументы движутся в разные стороны?

Пройти цепочку первой функции до места, где она передаёт работу второй, и дальше идти по цепочке второй. Пусть F(n) = F(n − 4) + 20 при n ≥ 12; F(n) = 3 · (G(n − 2) − 1) при n < 12; G(n) = n при n ≥ 30; G(n) = G(n + 7) + 2 при n < 30. Найдём F(39).

  1. F идёт вниз: 39, 35, 31, 27, 23, 19, 15, 11 — семь переходов по 20, F(39) = F(11) + 140.
  2. При n = 11 правило другое: F(11) = 3 · (G(9) − 1).
  3. G идёт вверх: 9, 16, 23, 30 — три перехода по 2, G(9) = G(30) + 6 = 36.
  4. F(11) = 3 · (36 − 1) = 105, F(39) = 105 + 140 = 245.

Заметь: 140, накопленные на шагах F, не попадают под умножение на 3 — оно действует только внутри F(11).

def G(n):    if n >= 30:        return n    return G(n + 7) + 2  def F(n):    if n >= 12:        return F(n - 4) + 20    return 3 * (G(n - 2) - 1)  print(F(39))
245

Перебор n

Что если спрашивают не значение, а аргумент — сколько n подходит или какое n наименьшее?

Тогда функцию вызывают для каждого n по очереди: считают подходящие или останавливаются на первом. Пусть F(0) = 0; F(n) = F(n // 2) + n % 2 при n > 0. Сколько чисел от 1 до 63 дают F(n) = 2?

def F(n):    if n == 0:        return 0    return F(n // 2) + n % 2  count = 0for n in range(1, 64):    if F(n) == 2:        count += 1print(count)
15

Аргумент здесь каждый раз делится пополам, поэтому вызовы короткие. Почему ответ 15, можно понять и без программы — это в дополнительном уроке.

Наименьшее n ищут циклом : он увеличивает n, пока условие не выполнено. Для функции задачи темы найдём наименьшее n, при котором F(n) > 1 000 000 000:

def F(n):    if n == 1:        return 1    return n * F(n - 1)  n = 1while F(n) <= 10**9:    n += 1print(n)
13

Цикл остановился на первом подходящем n — оно и наименьшее: F(12) = 479 001 600, а F(13) = 6 227 020 800.

Тонкости:когда можно остановиться

Останавливаться на первом n с F(n) > K можно, только если функция не убывает. У функции с ветвями из подтемы 1 F(4) = 6, а F(5) = 4: после большого значения может прийти меньшее. Если спрашивают F(n) = K, ищут первое точное совпадение, а границу перебора берут из условия, а не придумывают.

Итого

  • Шаг больше 1у каждого остатка своя цепочка, считаем переходы
  • Конец цепочкине обязательно на границе базы
  • Разные цепочкирасписать обе суммы и вычесть слагаемые парами
  • Две функциицепочка одной, потом другой; прибавки внешних шагов — вне скобок
  • Сколько nцикл со счётчиком
  • Наименьшее nwhile до первого подходящего

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

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

Вопрос 1
F(n) = n при n ≤ 5; F(n) = F(n − 3) + 4 при n > 5. Найди F(22).
ОтветСкрыть ответ
Ответ
28: аргументы 22, 19, 16, 13, 10, 7, 4 — шесть переходов по 4, а F(4) = 4.
Вопрос 2
F(n) = n при n ≥ 50; F(n) = F(n + 5) + 1 при n < 50. Найди F(13).
ОтветСкрыть ответ
Ответ
61: аргументы 13, 18, …, 48, 53 — восемь переходов, база F(53) = 53.
Вопрос 3
Почему в примере с F(11) − F(10) нельзя раскрыть F(11) до F(10) и сократить?
ОтветСкрыть ответ
Ответ
Аргумент растёт на 2: от 11 идут только нечётные числа, от 10 — чётные. Цепочки не встречаются, общего значения нет.
Вопрос 4
F(0) = 0; F(n) = F(n // 2) + n % 2 при n > 0. Сколько чисел от 1 до 15 дают F(n) = 2?
ОтветСкрыть ответ
Ответ
6: это 3, 5, 6, 9, 10, 12.
Вопрос 5
Для функции задачи темы найди наименьшее n, при котором F(n) > 1000.
ОтветСкрыть ответ
Ответ
7: F(6) = 720, F(7) = 5040.

Практика

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

Цепочки с шагом 4

F(n) = n при n ≤ 6; F(n) = F(n − 4) + 5 при n > 6. Найди F(51) − F(50).

Введите число.

Разность разных цепочек

F(n) = n при n ≥ 2000; F(n) = n + F(n + 2) при n < 2000. Найди F(21) − F(20).

Введите число.

Связанные функции в разные стороны

F(n) = F(n − 5) + 10 при n ≥ 20; F(n) = 2 · G(n + 1) при n < 20; G(n) = n при n ≥ 40; G(n) = G(n + 6) + 1 при n < 40. Найди F(48).

Введите число.

Сколько аргументов подходит

F(0) = 0; F(n) = F(n // 2) + n % 2 при n > 0. Сколько чисел n от 1 до 100 дают F(n) = 3?

Введите число.

Задача в формате экзамена: сколько n

Алгоритм вычисления значения функции F(n), где n — целое неотрицательное число, задан следующими соотношениями: F(0) = 0; F(n) = F(n − 1) + 1, если n нечётно; F(n) = F(n / 2), если n > 0 и при этом n чётно. Сколько существует чисел n, для которых 1 ≤ n ≤ 700 и F(n) = 4?

Введите число.

Задача в формате экзамена: наименьшее n

Функция F(n), где n — натуральное число, задана следующими соотношениями: F(n) = n, если n < 100; F(n) = n + F(n / 3), если n ≥ 100 и n делится на 3; F(n) = F(n − 1) + 5, если n ≥ 100 и n не делится на 3. Найди наименьшее значение n, для которого F(n) > 2000.

Введите число.