본문 바로가기

백준/수학

백준 11444 - 피보나치 수 6

728x90
728x90

https://www.acmicpc.net/problem/11444

 

최대 $10^{18}$ 번째 피보나치 항을 구해야 한다.

 

피보나치 수의 n번째 항 $F_{n}$은 다음과 같은 행렬 제곱으로 나타낼 수 있음이 알려져있다.

 

$\begin{pmatrix} F_{n + 1} & F_{n} \\ F_{n} & F_{n - 1} \end{pmatrix}^{n}$

 

분할 정복을 이용한 거듭제곱을 활용하여 원하는 항을 빠르게 구하면 된다.

 

전체 코드

더보기
#include <bits/stdc++.h>

using namespace std;
using ll = long long;

ll mod = 1e9 + 7;
ll n;

struct mat_fibo
{
    vector<vector<ll>> mat;
    
    mat_fibo(): mat(2, vector<ll>(2)) {}

    mat_fibo operator * (mat_fibo &arg)
    {
        mat_fibo ret;

        for (int i = 0; i < 2; ++i)
            for (int j = 0; j < 2; ++j)
                for (int k = 0; k < 2; ++k)
                    ret.mat[i][j] = (ret.mat[i][j] + mat[i][k] * arg.mat[k][j]) % mod;

        return ret;
    }
};

mat_fibo po(mat_fibo x, ll p)
{
    if (p == 1)
        return x;
    
    if (p & 1)
        return po(x, p - 1) * x;
    
    return po(x * x, p / 2);
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> n;
    
    if (n <= 1)
    {
        cout << n;
        return 0;
    }

    mat_fibo fib;
    fib.mat[0][0] = fib.mat[0][1] = fib.mat[1][0] = 1;
    fib.mat[1][1] = 0;

    auto res = po(fib, n);

    cout << res.mat[0][1];
}

728x90
728x90

'백준 > 수학' 카테고리의 다른 글

백준 4375 - 1  (0) 2021.07.08
백준 13172 - Σ  (0) 2021.07.04
백준 1413 - 박스 안의 열쇠  (0) 2021.01.17
백준 1146 - 지그재그 서기  (0) 2021.01.02
[ICPC] 백준 3948 - 홍준이의 친위대  (0) 2021.01.02