Сколько n-значных чисел можно составить,
используя только цифры 5 и 9, так
чтобы никакие три одинаковые цифры не стояли подряд?
Вход. Одно целое число
n (n ≤ 30).
Выход. Выведите
количество таких n-значных чисел.
|
Пример входа |
Пример выхода |
|
3 |
6 |
динамическое
программирование
Решение
задачи начнём с рассмотрения базовых случаев:
·
для n = 1 искомых чисел всего два: 5 и 9.
·
для n = 2 искомых
чисел всего четыре: 55, 59, 95 и 99.
Обозначим
через f(n) количество искомых n-значных чисел. Тогда:
·
f(1) = 2;
·
f(2) = 4;
Далее будем
строить n-значные числа, опираясь на уже построенные числа меньшей
длины.
·
Добавление одной цифры. Возьмем
все построенные (n – 1)-значные числа
и припишем к каждому из них цифру, отличную от его последней цифры. Таким
образом, получим n-значные числа, оканчивающиеся
на 559, 595, 959 и 995. Всего таких чисел f(n – 1).

·
Добавление двух одинаковых цифр. К n-значным числам также отнесем те,
которые можно получить из (n – 2)-значных,
приписав к ним две пятёрки или две девятки так, чтобы в конце не оказалось трёх
одинаковых цифр подряд. То есть к n-значным
числам добавляются также числа, оканчивающиеся на 599 и 955. Таким образом, получаем ещё f(n − 2) допустимых чисел.
Таким
образом, получим следующую рекуррентную формулу:
f(n) = f(n – 1) + f(n – 2),
f(1) = 2, f(2) = 4
Пример
Искомых
двузначных чисел четыре: 55, 59, 95 и 99.
Искомых
трехзначных чисел шесть: 559, 595, 959, 995, 599 и 955. Они получаются:
·
из двузначных чисел: 55 → 559, 59 → 595, 95 → 959, 99 → 995
·
из однозначных чисел: 5 → 599, 9 → 955
Все
искомые четырёхзначные числа получаются:
·
из трёхзначных чисел, приписыванием цифры, отличной от
последней: 5595, 5959, 9595, 9959, 5995 и 9559.
·
из двузначных чисел, приписыванием 55 или 99 так, чтобы
не получить три одинаковые цифры подряд: 5599, 5955, 9599 и 9955.

Реализация алгоритма
Значения f(i) будем хранить в ячейках массива m[i].
int m[31];
Читаем входное значение n.
scanf("%d", &n);
Задаём начальные значения f(1) = 2 и
f(2) = 4.
m[1] = 2; m[2] = 4;
Вычисляем значения m[i] (3 ≤ i ≤ n) по рекуррентной формуле.
for(i = 3; i <= n; i++)
m[i] = m[i-1] +
m[i-2];
Выводим ответ – значение m[n].
printf("%d\n",m[n]);
Java реализация
import java.util.*;
public class Main
{
public
static int MAX = 32;
static int m[] = new int[MAX];
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
int n = con.nextInt();
m[1] = 2; m[2] = 4;
for(int i = 3; i <= n; i++) m[i] = m[i-1] + m[i-2];
System.out.println(m[n]);
}
}
Python реализация
Читаем входное значение n.
n = int(input())
Инициализируем список m.
m = [0] * 31
Задаём начальные значения f(1) = 2 и
f(2) = 4.
m[1] = 2
m[2] = 4
Вычисляем значения m[i] (3 ≤ i ≤ n)
по рекуррентной формуле.
for i in range(3, n + 1):
m[i] = m[i - 1] + m[i - 2]
Выводим ответ – значение m[n].
print(m[n])