Теorema. Fibonacci ədədləri üçün aşağıdakı forma yerinə yetirilir:
İspat. İnduksiya ilə ispat gətirək.
İnduksiya bazası. n = 0 olduğu zaman:
və ya 0 = 1 - 1, bu doğrudur.
İnduksiya addımı. Var sayaq ki:
O zaman:
Bu da ispat ediləndir.
Belə ki istənilən cəmi
əldə etmək mümkündür
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):
Buradan:
Generasiya funksiyasını sadə fraksiyonlara ayıraq. Müqavimətlərin kökünü tapın:
burada
İndi generasiya funksiyasını belə təqdim edək:
Sistemi həll edərək:
Nəzərə alaraq ki
Generasiya funksiyasını belə yaza bilərik:
Amma nəzərə alsaq ki
F_n-nin x^n əmsallarını bərabərləşdirərək:
Fibonacci ədədlərinin identiklik ilə hesablanması
Fibonacci ədədləri üçün aşağıdakı identiklik tanınır:
Bununla xüsusi halları tam göstərmək mümkündür:
m = n olduğu zaman F_{2n} = F_n \cdot F_{n + 1} + F_{n - 1} \cdot F_n
m = n + 1 olduğu zaman F_{2n + 1} = F_{n + 1} \cdot F_{n + 1} + F_n \cdot F_n
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:
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ə.
Formulları tətbiq edək:
m = n olduğu zaman F_{2n} = F_n \cdot F_{n + 1} + F_{n - 1} \cdot F_n
m = n + 1 olduğu zaman F_{2n + 1} = F_{n + 1} \cdot F_{n + 1} + F_n \cdot F_n
Alqoritm realizasiyası
MOD məsaməsi ilə hesablama məhsulunu ləğv edin.
#define MOD 1000000007Yaddaş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:
n = 2k + 1 — tək hallar: F_n = F_k^2 + F_{k + 1}^2.
n = 2k — cüt hallar: F_n = F_k \cdot F_{k + 1} + F_{k - 1} \cdot F_k.
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 1000000007Struktur -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:
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
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);