— verilmiş ədədini ifadə etmək üçün istifadə oluna bilən minimal vahidlərin (bir ədədlərin) sayı olsun. Aydındır ki, f(1) = 1.
ədədini yalnız iki vahidin cəmi kimi göstərmək olar: 2 = 1 + 1. Buna görə f(2) = 2. Eynilə, ədədi yalnız üç vahidin cəmi şəklində göstərilir: 3 = 1 + 1 + 1. Buna görə f(3) = 3.
ədədini ya dörd vahidin cəmi kimi: 4 = 1 + 1 + 1 + 1, ya da hasil kimi yazmaq olar: 4 = (1 + 1) \cdot (1 + 1). Lakin hər iki halda vahid istifadə olunur, buna görə f(4) = 4.
Dəyəri -ə bərabər olan ifadəyə baxaq.
1. Fərz edək ki, son yerinə yetirilən əməliyyat toplamadır. Tutaq ki, bir toplanan -yə bərabərdir və vahiddən ibarətdir, ikinci toplanan isə n - i-yə bərabərdir və f(n - i) vahiddən ibarətdir. Onda qiymətini elə seçmək lazımdır ki, f(i) + f(n - i) cəmi minimal olsun.
Bu zaman qiymətini -yə qədər perebirat etmək kifayətdir, çünki birinci toplananın ikincidən böyük olmadığını fərz etmək olar. Beləliklə, aşağıdakı münasibəti alırıq:
2. Fərz edək ki, son yerinə yetirilən əməliyyat vurmadır. Tutaq ki, birinci vuruq vahiddən, ikinci vuruq isə vahiddən ibarətdir. Bu hal o zaman baş verir ki, -yə qalıqsız bölünsün.
qiymətini elə seçmək lazımdır ki, f(i) + f(n / i) cəmi minimal olsun. Bu zaman qiymətlərini -dən \lfloor \sqrt{n} \rfloor-ə qədər olan diapazonda perebirat etmək kifayətdir. Beləliklə, aşağıdakı münasibəti alırıq:
Beləliklə
Nümunə
n = 7 üçün cavabı hesablayaq:
ədədini vahid vasitəsilə göstərmək olar, məhz:
Alqoritmin realizasiyası
massivini elan edək.
int res[5001];giriş qiymətini oxuyuruq.
scanf("%d",&n);res[1] = 1 inisializasiya edirik.
res[1] = 1;Sonra yuxarıda verilmiş düstura əsasən res[2], res[3], ..., res[n] qiymətlərini ardıcıl olaraq hesablayırıq.
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];
}Cavabı çap edirik.
printf("%d\n",res[n]);