Fibonacci Sətirləri#2524

Fibonacci Sətirləri (Həll təhlili)

Fibonacci sətirləri rekursiv olaraq təyin olunur:

F_n = F_{n-2} + F_{n-1}

Bu o deməkdir ki, F_n sözü ard-arda iki hissədən ibarətdir:

Buna görə, F_n sözündə -cı simvolu tapmaq üçün bütün sözü yaratmağa ehtiyac yoxdur. Yalnız həmin simvolun hansı hissədə olduğunu müəyyən etmək kifayətdir.

F_n(k) ilə F_n sözünündəki -cı simvolunu ifadə edək.

Belə ki:

F_n(k) = F_{n-2}(k)
F_n(k) = F_{n-1}(k - |F_{n-2}|)

Bu halda, məsələ daha kiçik indeksli sözlərdə simvolun axtarılmasına çevrilir.

Misal

F_6 sözünü nəzərdən keçirək, hansı ki aşağıdakı əlaqələrə malikdir:

F_6(4) hesablayın. k = 4 \le |F_4| = 5, demək F_6(4) = F_4(4).

F_6(7) hesablayın. k = 7 > |F_4| = 5, demək F_6(7) = F_5(7 - 5) = F_5(2).

Alqoritmin realizasiyası

arrayi Fibonacci sətirlərin uzunluqlarını saxlayır:

#define MAX 44
int fib[MAX] = {1, 1};

solve funksiyası F_n sözündə -cı simvolu tam olaraq sözü yaratmadan qaytarır.

char solve(int n, int k)
{

Sadə halları fərqli şəkildə emal edirik: n = 0 və n = 1.

  if (n == 0) return 'a';
  if (n == 1) return 'b';

Bildiyimiz kimi, F_n = F_{n - 2} + F_{n - 1}.

  if (k <= fib[n-2]) return solve(n - 2, k);
  return solve(n - 1, k - fib[n-2]);
}

Programın əsas hissəsi. İlk Fibonacci ədədlərini hesablayırıq.

for (int i = 2; i < MAX; i++)
  fib[i] = fib[i-1] + fib[i-2];

Testlərin sayı oxuyuruq.

scanf("%d",&tests);
while (tests--)
{

Hər test üçün cavabı hesablayıb çap edirik.

  scanf("%d %d",&n,&k);
  printf("%c\n",solve(n,k));
}