Нехай — мінімальна кількість одиниць, за допомогою яких можна представити число . Очевидно, що f(1) = 1.
Число можна представити тільки як суму двох одиниць: 2 = 1 + 1. Тому f(2) = 2. Аналогічно, число представляється тільки у вигляді суми трьох одиниць: 3 = 1 + 1 + 1. Тому f(3) = 3.
Число можна записати або як суму чотирьох одиниць: 4 = 1 + 1 + 1 + 1, або як добуток: 4 = (1 + 1) \cdot (1 + 1). Однак в обох випадках використовується одиниці, тому f(4) = 4.
Розглянемо вираз, значення якого дорівнює .
1. Припустимо, що останньою виконаною операцією є додавання. Нехай один доданок дорівнює і складається з одиниць, а другий доданок дорівнює n - i і складається з f(n - i) одиниць. Тоді значення слід вибрати так, щоб сума f(i) + f(n - i) була мінімальною.
При цьому значення достатньо перебирати до , оскільки можна вважати, що перший доданок не перевищує другий. Таким чином, отримуємо наступне співвідношення:
2. Нехай останньою виконаною операцією було множення. Припустимо, що перший множник складається з одиниць, а другий множник складається з одиниць. Цей випадок має місце, якщо ділиться на без остачі.
Значення слід вибрати так, щоб сума f(i) + f(n / i) була мінімальною. При цьому достатньо перебирати значення в діапазоні від до \lfloor \sqrt{n} \rfloor. Таким чином, отримуємо наступне співвідношення:
Таким чином
Приклад
Обчислимо відповідь для n = 7:
Число можна представити за допомогою одиниць, а саме:
Реалізація алгоритму
Оголосимо масив .
int res[5001];Зчитуємо вхідне значення .
scanf("%d",&n);Ініціалізуємо res[1] = 1.
res[1] = 1;Далі послідовно обчислимо значення res[2], res[3], ..., res[n] за наведеною вище формулою.
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];
}Виводимо відповідь.
printf("%d\n",res[n]);