피보나치 수 6

Wonseok Lee·2021년 8월 20일
0

Beakjoon Online Judge

목록 보기
29/117
post-thumbnail

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

F_(n), F_(n-1)F_(n-1), F_(n_2)로 표현하는 행렬을 구하고,

행렬의 거듭제곱을 분할정복으로 구해준다.

#include <iostream>
#include <cstdint>
#include <tuple>

using namespace std;

const uint64_t kMod = 1000000007;

struct Mat
{
  uint64_t mat_[2][2];
  Mat(const uint64_t a, const uint64_t b, const uint64_t c, const uint64_t d)
  {
    mat_[0][0] = a;
    mat_[0][1] = b;
    mat_[1][0] = c;
    mat_[1][1] = d;
  }

  Mat operator*(const Mat& rhs) const
  {
    Mat ret(0, 0, 0, 0);
    for (size_t r = 0; r < 2; ++r)
    {
      for (size_t c = 0; c < 2; ++c)
      {
        for (size_t i = 0; i < 2; ++i)
        {
          ret.mat_[r][c] += mat_[r][i] * rhs.mat_[i][c];
        }

        ret.mat_[r][c] %= kMod;
      }
    }

    return ret;
  }
};

Mat GetPower(const uint64_t power)
{
  if (power == 0)
  {
    return Mat(1, 0, 0, 1);
  }

  Mat half = GetPower(power / 2);

  if (power % 2)
  {
    return Mat(1, 1, 1, 0) * half * half;
  }
  else
  {
    return half * half;
  }
}

int main(void)
{
  uint64_t n;
  cin >> n;

  Mat mat = GetPower(n - 1);

  cout << mat.mat_[0][0] << endl;

  return 0;
}
profile
Pseudo-worker

0개의 댓글