Вычисление чисел Фибоначчи за O(log n) через возведение матрицы в степень
def mat_mult(A, B):
return [
[A[0][0]*B[0][0] + A[0][1]*B[1][0], A[0][0]*B[0][1] + A[0][1]*B[1][1]],
[A[1][0]*B[0][0] + A[1][1]*B[1][0], A[1][0]*B[0][1] + A[1][1]*B[1][1]]
]
def mat_pow(M, n):
result = [[1, 0], [0, 1]]
while n > 0:
if n & 1:
result = mat_mult(result, M)
M = mat_mult(M, M)
n >>= 1
return result
def fib(n):
if n <= 1:
return n
M = [[1, 1], [1, 0]]
return mat_pow(M, n-1)[0][0]
n = int(input())
print(fib(n))
#include <bits/stdc++.h>
using namespace std;
struct Matrix {
long long a, b, c, d;
Matrix(long long a=1, long long b=0, long long c=0, long long d=1)
: a(a), b(b), c(c), d(d) {}
};
Matrix multiply(const Matrix& A, const Matrix& B) {
return Matrix(
A.a*B.a + A.b*B.c,
A.a*B.b + A.b*B.d,
A.c*B.a + A.d*B.c,
A.c*B.b + A.d*B.d
);
}
Matrix power(Matrix M, long long n) {
Matrix result;
while (n > 0) {
if (n & 1) result = multiply(result, M);
M = multiply(M, M);
n >>= 1;
}
return result;
}
long long fib(long long n) {
if (n <= 1) return n;
Matrix M(1, 1, 1, 0);
return power(M, n-1).a;
}
int main() {
long long n;
cin >> n;
cout << fib(n) << endl;
return 0;
}
Числа Фибоначчи можно вычислить с помощью возведения матрицы в степень:
Таким образом, F(n) равно элементу в левом верхнем углу матрицы, возведённой в степень n-1.
Матрица M = [[1, 1], [1, 0]] обладает свойством:
Возведение в степень n даёт Mⁿ, которая умножает начальный вектор [F(1), F(0)] = [1, 0].
Бинарное возведение в степень выполняется за O(log n) умножений матриц 2×2, что значительно быстрее O(n) итеративного метода для больших n.
Временная сложность: O(log n)
Ввод: n — номер числа Фибоначчи (0-индексация)
Вывод: F(n)
10
Вывод: 55
Ряд Фибоначчи: F(0)=0, F(1)=1, F(2)=1, F(3)=2, F(4)=3, F(5)=5, F(6)=8, F(7)=13, F(8)=21, F(9)=34, F(10)=55