Tre uni#263

Tre uni (Editoriale)

Indichiamo con il numero delle sequenze cercate di e di lunghezza . Consideriamo la costruzione della sequenza a partire dal primo carattere.

Se al primo posto c'è , allora la parte restante della sequenza può essere una qualsiasi sequenza ammissibile di lunghezza n - 1. Di conseguenza, tali varianti sono f(n - 1).

Se al primo posto c'è , consideriamo le possibili continuazioni:

In questo modo, otteniamo la relazione di ricorrenza:

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

Resta da calcolare i valori iniziali:

Esempio

Implementazione dell'algoritmo

Dichiariamo un array , in cui memorizzeremo i valori f(1), f(2), ..., f(n).

int f[100010];

Leggiamo il valore in input .

scanf("%d",&n);

Inizializziamo i valori di base dell'array.

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

Calcoliamo i valori secondo la formula ricorrente. Eseguiamo tutti i calcoli modulo .

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

Stampiamo la risposta.

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

Implementazione dell'algoritmo – ricorsione + memoizzazione

Dichiariamo un array per memorizzare i risultati intermedi:

int dp[100001];

Implementiamo la funzione , che restituisce il numero delle sequenze cercate di e di lunghezza . Utilizziamo la tecnica della memoizzazione.

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;
}

Parte principale del programma. Leggiamo il valore in input .

scanf("%d",&n);

Inizializziamo l'array .

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

Calcoliamo e stampiamo il valore .

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

Implementazione in 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();
  }
}

Implementazione in Python

Leggiamo il valore in input .

n = int(input())

Inizializziamo la lista . Nelle celle corrispondenti inseriamo i valori f(1), f(2) e .

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

Calcoliamo i valori secondo la formula ricorrente. Eseguiamo tutti i calcoli modulo .

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

Stampiamo la risposta.

print(dp[n])

Implementazione in Python – ricorsione con memoizzazione

Aumentiamo lo stack per la ricorsione.

import sys
sys.setrecursionlimit(10000)

Implementiamo la funzione , che restituisce il numero delle sequenze cercate di e di lunghezza . Utilizziamo la tecnica della memoizzazione.

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]

Parte principale del programma. Leggiamo il valore in input .

n = int(input())

Inizializziamo la lista .

dp = [-1] * 100001

Calcoliamo e stampiamo il valore .

print(f(n))