Yenə də Fibonacçi ədədləri#1250

Yenə də Fibonacçi ədədləri (Həll təhlili)

Теorema. Fibonacci ədədləri üçün aşağıdakı forma yerinə yetirilir:

S(n) = F(0) + F(1) + ... + F(n) = F(n + 2) - 1

İspat. İnduksiya ilə ispat gətirək.

F(0) = F(2) - 1,

və ya 0 = 1 - 1, bu doğrudur.

S(n) = F(n + 2) - 1

O zaman:

S(n + 1) = F(0) + F(1) + ... + F(n) + F(n + 1) = \\ (F(n + 2) - 1) + F(n + 1) = F(n + 3) - 1,

Bu da ispat ediləndir.

Belə ki istənilən cəmi

S = F(a) + F(a + 1) + ... + F(b)

əldə etmək mümkündür

S = S(b) - S(a - 1)

Binet formula ilə Fibonacci saylarının hesablanması

Fibonacci ədədləri üçün generasiya funksiyasını nəzərdən keçirək (F_0 = 0, F_1 = 1):

G(x) = \sum_{n = 0}^∞ F_n x^n = F_0 + F_1x + \sum_{n = 2}^∞ F_n x^n = \\ F_0 + F_1x + \sum_{n = 2}^∞ (F_{n - 1} + F_{n - 2}) x^n = \\ x + \sum_{n = 2}^∞ F_{n - 1} x^n + \sum_{n = 2}^∞ F_{n - 2} x^n = \\ x + x \sum_{n = 1}^∞ F_n x^n + x^2 \sum_{n = 0}^∞ F_n x^n = \\ x + xG(x) + x^2G(x)

Buradan:

G(x) (1 - x - x^2) = x, \\ G(x) = \frac{x}{1 - x - x^2}

Generasiya funksiyasını sadə fraksiyonlara ayıraq. Müqavimətlərin kökünü tapın:

1 - x - x^2 = (1 - φx) (1 - ψx),

burada

φ = \frac{1 + \sqrt{5}}{2}, ψ = \frac{1 - \sqrt{5}}{2}

İndi generasiya funksiyasını belə təqdim edək:

\frac{x}{1 - x - x^2} = \frac{A}{1 - φx} + \frac{B}{1 - ψx}

Sistemi həll edərək:

A = \frac{1}{\sqrt{5}}, B = -\frac{1}{\sqrt{5}}

Nəzərə alaraq ki

\frac{1}{1 - rx} = \sum_{n = 0}^∞ r^n x^n,

Generasiya funksiyasını belə yaza bilərik:

G(x) = \frac{1}{\sqrt{5}} \left( \frac{1}{1 - φx} + \frac{1}{1 - ψx} \right) = \frac{1}{\sqrt{5}} \sum_{n = 0}^∞ (φ^n - ψ^n) x^n

Amma nəzərə alsaq ki

G(x) = \sum_{n = 0}^∞ F_n x^n

F_n-nin x^n əmsallarını bərabərləşdirərək:

F_n = \frac{φ^n - ψ^n}{\sqrt{5}} = \frac{1}{\sqrt{5}} \left( \left( \frac{1 + \sqrt{5}}{2} \right)^n - \left( \frac{1 - \sqrt{5}}{2} \right)^n \right) = \frac{(1 + \sqrt{5})^n - (1 - \sqrt{5})^n}{2^n \sqrt{5}}

Fibonacci ədədlərinin identiklik ilə hesablanması

Fibonacci ədədləri üçün aşağıdakı identiklik tanınır:

F_{n + m} = F_m \cdot F_{n+1} + F_{m - 1} \cdot F_n

Bununla xüsusi halları tam göstərmək mümkündür:

Bu formulalar Fibonacci ədədlərini "böl və hökm sür" metoduyla hesablamağa, F_n hesabını təxminən iki qat kiçik indeks dəyərlərinə salmağa imkan verir.

Əsas halları ayrıca emal edərək:

F_0 = 0, F_1 = F_2 = 1

Bu yanaşma ilə rekursiyanın dərinliyi log_2n-ə proporisonal olur və alqoritmin vaxt kompleksliyi O(log_2n) təşkil edir.

Nümunə

Binet formuluna görə bir neçə Fibonacci ədədi hesablayaq, böyük modlla Z_p (\sqrt{5}) geniş alanında işlə.

F_2 = \frac{1}{\sqrt{5}} \left( \left( \frac{1 + \sqrt{5}}{2} \right)^2 - \left( \frac{1 - \sqrt{5}}{2} \right)^2 \right) = \frac{(1 + \sqrt{5})^2 - (1 - \sqrt{5})^2}{2^2 \sqrt{5}} = \frac{(6 + 2\sqrt{5}) - (6 - 2\sqrt{5})}{2^2 \sqrt{5}} = \frac{4\sqrt{5}}{4\sqrt{5}} = 1 \\ F_3 = \frac{1}{\sqrt{5}} \left( \left( \frac{1 + \sqrt{5}}{2} \right)^3 - \left( \frac{1 - \sqrt{5}}{2} \right)^3 \right) = \frac{(1 + \sqrt{5})^3 - (1 - \sqrt{5})^3}{2^3 \sqrt{5}} = \frac{(16 + 8\sqrt{5}) - (16 - 8\sqrt{5})}{2^3 \sqrt{5}} = \frac{16\sqrt{5}}{8\sqrt{5}} = 2 \\ F_4 = \frac{1}{\sqrt{5}} \left( \left( \frac{1 + \sqrt{5}}{2} \right)^4 - \left( \frac{1 - \sqrt{5}}{2} \right)^4 \right) = \frac{(6 + 2\sqrt{5})^2 - (6 - 2\sqrt{5})^2}{2^4 \sqrt{5}} = \frac{(56 + 24\sqrt{5}) - (56 - 24\sqrt{5})}{2^4 \sqrt{5}} = \frac{48\sqrt{5}}{16\sqrt{5}} = 3

Formulları tətbiq edək:

F_6 = F_3 \cdot F_4 + F_2 \cdot F_3 = 2 \cdot 3 + 1 \cdot 2 = 6 + 2 = 8, \\ F_7 = F_4^2 + F_3^2 = 3^2 + 2^2 = 9 + 4 = 13

Alqoritm realizasiyası

MOD məsaməsi ilə hesablama məhsulunu ləğv edin.

#define MOD 1000000007

Yaddaşda artıq hesablanmış Fibonacci ədədlərini saxlamaq üçün olan tip olan dəyişənini təyinn edin.

map<long long, long long> fib;

f funksiyası -ci Fibonacci ədədini MOD üzərindən hesablamaq üçün.

long long f(long long n)
{
  if (n == 0) return 0;
  if (n == 1) return 1;
  if (n == 2) return 1;

Əgər -ci Fibonacci ədəd daha öncə hesablanıbsa və -də saxlanıbsa, dərhal geri qaytarılır, yenidən hesablama olmadan.

  if (fib[n]) return fib[n];

Sonra ədədi istifadə edərək parçalama:

  long long k = n / 2;

Nəticəni yadda saxlayın və geri qaytarın.

  if (n % 2 == 1) // n = 2*k + 1
    return fib[n] = (f(k) * f(k) + f(k + 1) * f(k + 1)) % MOD;
  else // n = 2*k
    return fib[n] = (f(k) * f(k + 1) + f(k - 1) * f(k)) % MOD;
}

Proqramın əsas hissəsi. Hər test üçün giriş məlumatlarını oxuyub cavabını çıxarır.

while (scanf("%lld %lld", &a, &b) == 2)
  printf("%lld\n", (f(b + 2) - f(a + 1) + MOD) % MOD);

Alqoritm realizasiyası – Binet formulu

MOD məsaməsi ilə hesablama məhsulunu ləğv edin.

#define MOD 1000000007

Struktur -u x + y \sqrt{5} formulu olan ədədin saxlanması üçün təyin edin.

struct Num
{
  long long x, y; // x + y*sqrt(c)
  Num(long long x_ = 0, long long y_ = 0) : x(x_), y(y_) {}
};

Z_p (\sqrt{5}) sahəsində vurmağı həyata keçirək. mult funksiyası və ədədlərinin hasilini geri qaytarır.

Num mult(Num& a, Num& b)
{
  Num res;
  res.x = (a.x * b.x + 5 * a.y % MOD * b.y) % MOD;
   res.y = (a.x * b.y + a.y * b.x) % MOD;
   return res;
}

pow funksiyası base^n olan sahəsində Z_p (\sqrt{5}) hasilini verir.

Num pow(Num base, long long n)
{
  Num res = { 1, 0 }; // sahənin birliyi
  while (n > 0)
  {
    if (n & 1)
      res = mult(res, base);
    base = mult(base, base);
    n >>= 1;
  }
  return res;
}

modpow funksiyası a^k~mod~p dəyərini geri qaytarır.

long long pow(long long x, long long n)
{
  long long res = 1;
  x %= MOD;
  while (n > 0)
  {
    if (n & 1) res = res * x % MOD;
    x = x * x % MOD;
    n >>= 1;
  }
  return res;
}

fib funksiyası -ci Fibonacci ədədini hesablamaq üçün.

long long fib(long long n)
{

φ və ψ üçün məhsulların başlanğıcını təyin edin φ = 1 + \sqrt{5} və ψ = 1 - \sqrt{5}.

  Num phi(1, 1);
  Num psi(1, MOD - 1);

A = φ^n və B = ψ^n sonu na hesablama.

  Num A = pow(phi, n);
  Num B = pow(psi, n);

Çünki:

F_n = \frac{1}{\sqrt{5}} \left( \left( \frac{1 + \sqrt{5}}{2} \right)^n - \left( \frac{1 - \sqrt{5}}{2} \right)^n \right) = \frac{(1 + \sqrt{5})^n - (1 - \sqrt{5})^n}{2^n \sqrt{5}} = \frac{(A_x + A_y \sqrt{5}) - (B_x + B_y \sqrt{5})}{2^n \sqrt{5}},

Ayrı yazılış numeratorsunu , və denominatoru hesabla.

Qeyd edək ki, burada A_x = B_x (bu səbəbdən A_x - B_x = 0) və \sqrt{5}-nin numeratorunda əmsal A_y - B_y-ə bərabərdir.

  long long numerator = (A.y - B.y + MOD) % MOD;

2^n-i denominatoru içərisində hesablama.

  long long denom = pow(2, n);

Numerator və denominator \sqrt{5} mürəkkəbi saxlayır. Bu fraksiyanı salın və ən son nəticəni hesablamaq üçün

(A_y - B_y) \cdot (2^n)^{-1} = numerator \cdot denom^{-1}
  long long denom_inv = pow(denom, MOD - 2);
  return numerator * denom_inv % MOD;
}

Proqramın əsas hissəsi. Hər test üçün giriş məlumatlarını oxuyub cavabını çıxarır.

while (scanf("%lld %lld", &a, &b) == 2)
  printf("%lld\n", (fib(b + 2) - fib(a + 1) + MOD) % MOD);