Sia — il numero minimo di unità con cui si può rappresentare il numero . Ovviamente, f(1) = 1.
Il numero può essere rappresentato solo come somma di due unità: 2 = 1 + 1. Quindi f(2) = 2. Analogamente, il numero si rappresenta solo come somma di tre unità: 3 = 1 + 1 + 1. Quindi f(3) = 3.
Il numero può essere scritto sia come somma di quattro unità: 4 = 1 + 1 + 1 + 1, sia come prodotto: 4 = (1 + 1) \cdot (1 + 1). Tuttavia in entrambi i casi si utilizzano unità, quindi f(4) = 4.
Consideriamo un'espressione il cui valore sia uguale a .
1. Supponiamo che l'ultima operazione eseguita sia l'addizione. Sia un addendo uguale a e composto da unità, e il secondo addendo uguale a n - i e composto da f(n - i) unità. Allora il valore di va scelto in modo che la somma f(i) + f(n - i) sia minima.
In questo caso è sufficiente far variare il valore di fino a , poiché si può assumere che il primo addendo non superi il secondo. In questo modo otteniamo la seguente relazione:
2. Supponiamo che l'ultima operazione eseguita sia la moltiplicazione. Supponiamo che il primo fattore sia composto da unità, e il secondo fattore sia composto da unità. Questo caso si verifica se è divisibile per senza resto.
Il valore di va scelto in modo che la somma f(i) + f(n / i) sia minima. In questo caso è sufficiente far variare i valori di nell'intervallo da a \lfloor \sqrt{n} \rfloor. In questo modo otteniamo la seguente relazione:
Quindi
Esempio
Calcoliamo la risposta per n = 7:
Il numero può essere rappresentato con unità, precisamente:
Implementazione dell'algoritmo
Dichiariamo un array .
int res[5001];Leggiamo il valore in ingresso .
scanf("%d",&n);Inizializziamo res[1] = 1.
res[1] = 1;Di seguito calcoliamo in sequenza i valori res[2], res[3], ..., res[n] secondo la formula sopra riportata.
for (i = 2; i <= n; i++)
{
res[i] = i;
for (j = 1; 2 * j < i; j++)
if (res[j] + res[i - j] < res[i]) res[i] = res[j] + res[i - j];
for (j = 2; j * j <= i; j++)
if (i % j == 0)
if (res[j] + res[i / j] < res[i]) res[i] = res[j] + res[i / j];
}Stampiamo la risposta.
printf("%d\n",res[n]);