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:
se al secondo posto c'è , allora le rimanenti n - 2 posizioni formano una sequenza ammissibile arbitraria di lunghezza n - 2, cioè f(n - 2) varianti;
se al secondo posto c'è , allora per non permettere tre uni consecutivi, al terzo posto deve necessariamente esserci . Dopo di che restano n - 3 posizioni, che possono essere riempite con una sequenza ammissibile arbitraria, cioè f(n - 3) varianti.
In questo modo, otteniamo la relazione di ricorrenza:
Resta da calcolare i valori iniziali:
f(1) = 2, poiché esistono due sequenze di lunghezza : e .
f(2) = 4, poiché esistono quattro sequenze di lunghezza : e .
f(3) = 7, poiché esistono sette sequenze di lunghezza : 000, 001, 010, 011, 100, 101 e .
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:
conterrà il valore
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, 7Calcoliamo 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] * 100001Calcoliamo e stampiamo il valore .
print(f(n))