Сколько раз будет вызвана функция f def f n if n 0 return 1 return n f n 2 f 50
Перейти к содержимому

Сколько раз будет вызвана функция f def f n if n 0 return 1 return n f n 2 f 50

Сколько раз будет вызвана функция f def f n if n 0 return 1 return n f n 2 f 50

Ниже на пяти языках программирования записаны две рекурсивные функции (процедуры): F и G.

procedure F(n: integer); forward;
procedure G(n: integer); forward;

procedure F(n: integer);
begin
if n > 0 then
G(n — 1);
end;

procedure G(n: integer);
begin
writeln(‘*’);
if n > 1 then
F(n — 3);
end;

void F(int n);
void G(int n);

Сколько символов "звёздочка" будет напечатано на экране после выполнения вызова F(11)?

Источник: демоверсия ФИПИ по информатике и ИКТ 2016-го года.

В решении задания есть видеоразбор

Рекурсивная функция — это функция, вызывающая сама себя. Нам даны две процедуры со взаимной рекурсией, то есть процедура F вызывает процедуру G, а процедура G — процедуру F.

Как мы видим, символ "звёздочка" выводится на экран при вызове процедуры G, при этом "звёздочка" печатается в любом случае, независимо от условия.

То есть для решения задания нам достаточно определить, сколько раз будет вызвана процедура G при вызове F(11).

Вызовы процедур мы можем записать так:

На процедуре F(-1) рекурсия завершится, так как условие n>0 перестанет выполняться.

Осталось посчитать, сколько раз была вызвана процедура G:

F(11) -> G(10) -> F(7) -> G(6) -> F(3) -> G(2) -> F(-1)

Рекурсия — Python: Функции

"Чтобы понять рекурсию, нужно сначала понять рекурсию!" (расхожая шутка).

Рекурсия в программировании — это возможность дать определение функции, используя в процессе саму определяемую функцию. В математике многие функции определены именно таким образом, поэтому и большинство языков программирования берёт на вооружение этот подход. Python здесь не является исключением: обычно в определении функции вы можете использовать только определения, данные ранее, но есть одно исключение — функция в своём теле может вызывать себя. Выглядит это так:

Эта функция, вычисляет факториал числа n через умножение числа на факториал числа n — 1 .

Условие завершения рекурсии

Рассмотренный пример демонстрирует использование условия, прекращающего рекурсию. Если в этой функции убрать условие, проверяющее аргумент на неотрицательность, то первый же вызов этой функции заставит программу "зациклиться" — функция продолжит вызывать себя снова и снова.

В определениях рекурсивных функций практически всегда присутствует подобное условие. Оно позволяет вычислению пойти по одной из веток: по рекурсивной — в этой ветке произойдёт вызов себя (а то и не один!), и терминальной, которая закончит вычисление и вернёт результат.

Есть даже такое правило: какой-то из аргументов рекурсивной функции должен обязательно "убывать". Убывание может означать уменьшение счётчика, отбрасывание "головы" списка при движении к его хвосту, вызов себя для части исходной структуры при обработке древовидных структур данных. К сожалению, в общем случае понять, что программа не зациклится, можно только методом "пристального взгляда" и применением тестов. Особенно важно проверять срабатывание условия завершения рекурсии!

Переполнение стека

В большинстве программ, написанных на языках, которые поддерживают вызов функций, этот самый вызов устроен так: перед вызовом функции текущее место в программе запоминается в стеке, а когда функция возвращает результат, то соответствующий элемент стека отбрасывается.

Стек (stack) — абстрактный тип данных, похожий на стопку монет: монета, положенная последней, будет снята первой (при снятии монет порядок получается обратным порядку складывания).

В этом же стеке сохраняются значения аргументов функции, а иногда и другая служебная информация. При этом память, выделенная для стека при запуске программы, конечна и довольно ограничена. Что же произойдёт, если функция будет вызывать себя снова и снова и не возвращать результат? Эта память когда-нибудь закончится! Когда заканчивается память, выделенная для стека вызовов, случается так называемое "переполнение стека".

Из-за переполнения стека вы не сможете посчитать факториал для достаточно больших чисел с помощью рекурсивной функции. Но сможете посчитать с помощью итеративной — написанной с использованием циклов и переменных. К слову, вот так выглядит переполнение стека при подсчёте факториала:

Заметьте, сообщение говорит, что "превышена максимальная глубина рекурсии". Глубиной рекурсии называется количество последовательных вызовов "себя" без возврата значения. В Python максимальная длина искусственно ограничена, потому что проще считать количество вызовов, чем предсказывать окончание памяти.

Зачем рекурсия нужна

Вы можете подумать, почему же программисты не перестают использовать рекурсивные функции и не переходят на итеративные? Дело в том, что некоторые алгоритмы реализуются сильно проще, если использовать именно рекурсию, а не циклы. Часто такие алгоритмы работают с рекурсивными же структурами данных — деревьями, "словарями словарей словарей" и подобными. При реализации таких алгоритмов нужно помнить, что память для стека не бесконечна. Впрочем, обычно не бесконечны и сами обрабатываемые структуры данных, поэтому отказываться полностью от рекурсии не стоит!

Рекурсия прямая, косвенная, линейная, каскадная

Видов рекурсии существует несколько. Если функция вызывает себя непосредственно, то мы имеем дело с прямой рекурсией. Если же функция вызывает внутри себя другую, которая когда-то вызовет первую, то это уже косвенная рекурсия.

Если при вычислении результата функции нужно вызвать себя один раз, как в примере с factorial , то рекурсия называется линейной. Только имейте в виду, что "один раз" ничего не говорит про общее количество вызовов функции в теле! Речь идёт именно о количестве вызовов, результаты которых потребуются для одного общего вычисления.

Рассмотрим два разных примера: в одном рекурсия будет линейной, а в другом каскадной — так называют рекурсию с "несколькими вызовами себя".

Рекурсия в этой функции (которая проверяет Гипотезу Коллатца) — линейная:

Здесь в теле функции рекурсивных вызова два, но в каждом конкретном "заходе" используется только один.

А вот рекурсия в этой функции (которая вычисляет очередное Число Фибоначчи) — каскадная:

Здесь функция всегда вызывает себя два раза. Сначала будет два вызова себя, которые превратятся в четыре (два раза по два вызова), затем в восемь — количество вызовов растёт "каскадно", отсюда и название рекурсии.

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

ЕГЭ по информатике 2022 — Задание 16 (Рекурсия)

Шестнадцатое задание из ЕГЭ по информатике 2022 даётся на рекурсию.

Это задание нужно делать с помощью компьютера.

В программировании рекурсией называется процесс, когда функция вызывает сама себя или, когда две функции попарно вызывают друг друга.

Мы будем писать все программы на языке программирования Python.

Что такое Функция в языке программирования Python ?

Рассмотрим пример функции, которая суммирует два числа!

Здесь функция F, которая суммирует два числа.

В главной части программы запрашиваются два числа с клавиатуры: a и b! Эти два числа передаются в функцию F. В функции эти числа кладутся в локальные переменные x и y. Сумма переменных x и y записывается в переменную s. Переменная s возвращается, как результат работы функции F.

Результат работы функции будет помещён в переменную r (в строке r = F(a, b)) в основной части программы.

Таким образом, в переменной r будет сумма двух переменных a и b.

Функции позволяют сократить программный код для однотипных расчётов.

Тренировочные задачи 16 задания из ЕГЭ по информатике 2022

Алгоритм вычисления значения функции F(n), где n – натуральное число, задан следующими соотношениями:

F(n) = 1 при n = 1;
F(n) = n + F(n − 1), если n – чётно,
F(n) = 3 × F(n − 2), если n > 1 и при этом n – нечётно.

Чему равно значение функции F(25)?

Напишем программу для решения данной задачи. В начале опишем все правила, которые даны в условии задачи для функции. В основной части программы запустим эту функцию.

После запуска рекурсивной функции программа выведет ответ 531441.

Выражение n%2 != 0 (остаток от деления на «2» не равен нулю) обозначает нечётное число. Выражение n%2==0 обозначает чётное число.

Ответ: 531441

Продолжаем тренировку по подготовке к 16 заданию ЕГЭ по информатике 2022.

Задача (Продолжаем подготовку)

Алгоритм вычисления значения функции F(n), где n – натуральное число, задан следующими соотношениями:

F(1) = 1
F(2) = 3
F(n) = F(n–1) * n + F(n–2) * (n – 1) , при n > 2

Чему равно значение функции F(8)? В ответе запишите только натуральное число.

Ответ получается 148329.

Ответ: 148329

Закрепляющий пример на рекурсию 16 задания из ЕГЭ по информатике 2022.

Алгоритм вычисления значения функций F(n) и G(n), где n — натуральное число, задан следующими соотношениями:

F(n) = 0, если n 2

Чему равно значение функции F(8)? В ответе запишите только натуральное число.

Получается ответ 9.

Задача (Количество значений)

Алгоритм вычисления значения функции F(n), где n – натуральное число, задан следующими соотношениями:

F(n) = 2*n*n*n + 1, при n > 25
F(n) = F(n+2) + 2*F(n+3), при n ≤ 25

Определите количество натуральных значений n из отрезка [1; 1000], для которых значение F(n) кратно 11.

В начале формируем функцию F. Затем перебираем числа из диапазона от 1 до 1000. Каждое число подставляем в функцию F. Если значение функции F делится на 11, то мы зачитываем такое значение i.

В ответе получается 91.

ЕГЭ по информатике - задание 16 (Глобальная переменная)

Задача (Используем глобальную переменную)

Решение:

При решении этой задачи можно применить глобальную переменную.

Здесь внутри функции заводим глобальную переменную s, которая будет подсчитывать количество напечатанных звёздочек. Теперь эту переменную видно при любом вызове функции, и при каждом вызове функции она будет одна и та же переменная. Вместо печати звёздочек пишем конструкцию s=s+1.

В основной части программы перед первым запуском функции переменной s присваиваем 0.

Программа может немного медленно работать из-за большой глубины рекурсии, но через минуту выведет число 96631265.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *