結果
| 問題 |
No.526 フィボナッチ数列の第N項をMで割った余りを求める
|
| コンテスト | |
| ユーザー |
Demystify
|
| 提出日時 | 2022-09-10 09:53:59 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 15 ms / 2,000 ms |
| コード長 | 2,228 bytes |
| コンパイル時間 | 2,009 ms |
| コンパイル使用メモリ | 204,888 KB |
| 最終ジャッジ日時 | 2025-02-07 03:51:45 |
|
ジャッジサーバーID (参考情報) |
judge2 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 12 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
// --------------------------------------------------------
#define FOR(i,l,r) for (ll i = (l); i < (r); ++i)
#define REP(i,n) FOR(i,0,n)
// --------------------------------------------------------
// 行列累乗
template<class T>
struct matrix_exponential {
public:
matrix_exponential(int d) : d(d) {}
// 単位行列を返す
// - (d^2)
vector<vector<T>> id() {
vector<vector<T>> E(d, vector<T>(d, 0));
for (int i = 0; i < d; i++) { E[i][i] = 1; }
return E;
}
// 行列積を求める
// - (d^3)
vector<vector<T>> mat_mul(const vector<vector<T>>& A, const vector<vector<T>>& B) {
vector<vector<T>> C(d, vector<T>(d, 0));
for (int i = 0; i < d; i++) {
for (int k = 0; k < d; k++) {
for (int j = 0; j < d; j++) {
C[i][j] += A[i][k] * B[k][j];
}
}
}
return C;
}
// d x d の正方行列 A に対して A^n を求める
// - O(d^3 log n)
vector<vector<T>> solve(vector<vector<T>> A, ll n) {
auto B = id();
// e.g.) n = 11, B = A^(2^3) + A^(2^1) + A^(2^0) (11 = 2^3 + 2^1 + 2^0)
while (n > 0) {
if (n & 1) { B = mat_mul(B, A); } // 欲しいタイミングで拾う
A = mat_mul(A, A);
n >>= 1;
}
return B;
}
private:
int d;
};
#if 1
#include <atcoder/modint>
using namespace atcoder;
using mint = modint;
using VM = vector<mint>;
using VVM = vector<VM>;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout << fixed << setprecision(15);
ll N, M; cin >> N >> M;
mint::set_mod(M);
// Fibonacci
// F(1) = 0
// F(2) = 1
// F(n) = F(n-1) + F(n-2)
VVM A = {{1, 1},
{1, 0}};
matrix_exponential<mint> mat_exp(A.size());
auto An = mat_exp.solve(A, N-1);
// {F(n+1), F(n)} = A^(n-1) {F(2), F(1)} = A^(n-1) {1, 0}
// ---> F(n) = A^(n-1)[1][0] * 1 + A^(n-1)[1][1] * 0
ll ans = An[1][0].val();
cout << ans << endl;
return 0;
}
// Verify: https://yukicoder.me/problems/no/526
#endif
Demystify