Три одиниці#263

Три одиниці (Розбір)

Позначимо через кількість шуканих послідовностей з та довжини . Розглянемо побудову послідовності за першим символом.

Якщо на першому місці стоїть , то решта частина послідовності може бути будь-якою допустимою послідовністю довжини n - 1. Отже, таких варіантів f(n - 1).

Якщо на першому місці стоїть , то розглянемо можливі продовження:

Таким чином, отримуємо рекурентне співвідношення:

f(n) = f(n - 1) + f(n - 2) + f(n - 3)

Залишається обчислити початкові значення:

Приклад

Реалізація алгоритму

Оголосимо масив , у якому будемо зберігати значення f(1), f(2), ..., f(n).

int f[100010];

Зчитуємо вхідне значення .

scanf("%d",&n);

Ініціалізуємо базові значення масиву.

f[1] = 2; f[2] = 4; f[3] = 7;

Обчислюємо значення за рекурентною формулою. Усі обчислення виконуємо за модулем .

for(i = 4; i <= n; i++)
  f[i] = (f[i-1] + f[i-2] + f[i-3]) % 12345;

Виводимо відповідь.

printf("%d\n",f[n]);

Реалізація алгоритму – рекурсія + запам'ятовування

Оголосимо масив для зберігання проміжних результатів:

int dp[100001];

Реалізуємо функцію , яка повертає кількість шуканих послідовностей з та довжини . Використовуємо техніку мемоізації.

int f(int n)
{
  if (n == 1) return 2;
  if (n == 2) return 4;
  if (n == 3) return 7;
  if (dp[n] != -1) return dp[n];
  return dp[n] = (f(n-1) + f(n-2) + f(n-3)) % 12345;
}

Основна частина програми. Зчитуємо вхідне значення .

scanf("%d",&n);

Ініціалізуємо масив .

memset(dp,-1,sizeof(dp));

Обчислюємо та виводимо значення .

printf("%d\n",f(n));

Java реалізація

import java.util.*;

public class Main
{
  public static int MAX = 100010;
  static int f[] = new int[MAX];

  public static void main(String[] args)
  {
    Scanner con = new Scanner(System.in);
    int n = con.nextInt();
    f[1] = 2; f[2] = 4; f[3] = 7;
    for(int i = 4; i <= n; i++)
      f[i] = (f[i-1] + f[i-2] + f[i-3]) % 12345;
    System.out.println(f[n]);
    con.close();
  }
}

Python реалізація

Зчитуємо вхідне значення .

n = int(input())

Ініціалізуємо список . У відповідні комірки заносимо значення f(1), f(2) та .

dp = [0] * (n + 4)
dp[1], dp[2], dp[3] = 2, 4, 7

Обчислюємо значення за рекурентною формулою. Усі обчислення виконуємо за модулем .

for i in range(4, n + 1):
  dp[i] = (dp[i-1] + dp[i-2] + dp[i-3]) % 12345;

Виводимо відповідь.

print(dp[n])

Python реалізація – рекурсія з запам'ятовуванням

Збільшимо стек для рекурсії.

import sys
sys.setrecursionlimit(10000)

Реалізуємо функцію , яка повертає кількість шуканих послідовностей з та довжини . Використовуємо техніку мемоізації.

def f(n):
  if n == 1: return 2
  if n == 2: return 4
  if n == 3: return 7
  if dp[n] != -1: return dp[n]

  dp[n] = (f(n - 1) + f(n - 2) + f(n - 3)) % 12345
  return dp[n]

Основна частина програми. Зчитуємо вхідне значення .

n = int(input())

Ініціалізуємо список .

dp = [-1] * 100001

Обчислюємо та виводимо значення .

print(f(n))