結果

問題 No.526 フィボナッチ数列の第N項をMで割った余りを求める
ユーザー nawawannawawan
提出日時 2021-02-09 20:15:22
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 2 ms / 2,000 ms
コード長 6,143 bytes
コンパイル時間 787 ms
コンパイル使用メモリ 80,784 KB
実行使用メモリ 4,380 KB
最終ジャッジ日時 2023-09-21 07:57:20
合計ジャッジ時間 1,673 ms
ジャッジサーバーID
(参考情報)
judge15 / judge12
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,376 KB
testcase_01 AC 1 ms
4,380 KB
testcase_02 AC 2 ms
4,380 KB
testcase_03 AC 1 ms
4,376 KB
testcase_04 AC 2 ms
4,376 KB
testcase_05 AC 1 ms
4,376 KB
testcase_06 AC 1 ms
4,376 KB
testcase_07 AC 2 ms
4,376 KB
testcase_08 AC 1 ms
4,376 KB
testcase_09 AC 2 ms
4,376 KB
testcase_10 AC 2 ms
4,376 KB
testcase_11 AC 2 ms
4,380 KB
testcase_12 AC 2 ms
4,376 KB
testcase_13 AC 1 ms
4,376 KB
testcase_14 AC 2 ms
4,380 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>
using namespace std;
template<typename T> struct mat{
    int N, M;//N x Mの行列(通常はN = M)
    vector<vector<T>> matrix;//行列
    mat() : N(0), M(0), matrix(0){}
    mat(int n, int m){
        N = n;
        M = m;
        matrix.resize(N, vector<T>(M));
    }
    mat(vector<vector<T>> m){
        N = m.size();
        M = m[0].size();
        matrix = m;
    }
    mat(int n, int m, vector<vector<T>> m1){
        N = n;
        M = m;
        matrix = m1;
    }
    void init(vector<vector<T>> m){
        N = m.size();
        M = m[0].size();
        matrix = m; 
    }
    mat mulmod(const mat &mat2, const T MOD){
        mat res(N, M);
        for(int i = 0; i < N; i++){
            for(int j = 0; j < N; j++){
                for(int k = 0; k < M; k++){
                    res.matrix[i][j] += (*this).matrix[i][k] * mat2.matrix[k][j] % MOD;
                    if(res.matrix[i][j] >= MOD) res -= MOD;
                }
            }
        }
        return res;
    }
    vector<T> operate(vector<T> vec){
        assert(vec.size() == M);
        vector<T> res(N);
        for(int i = 0; i < N; i++){
            for(int j = 0; j < M; j++) res[i] += matrix[i][j] * vec[j];
        }
        return res;
    }
    vector<T> operate(vector<T> vec, const T MOD){
        assert(vec.size() == M);
        vector<T> res(N);
        for(int i = 0; i < N; i++){
            for(int j = 0; j < M; j++){
                res[i] += matrix[i][j] * vec[j] % MOD;
                if(res[i] >= MOD) res[i] -= MOD;
            }
        }
        return res;
    }
    vector<T> repow(T K, vector<T> vec){//行列累乗(MODなし)
        assert(N == M);//正方行列である必要あり
        while(K > 0){
            if(K & 1) vec = operate(vec);
            vector<vector<T>> temp(N, vector<T>(M));
            for(int i = 0; i < N; i++){
                for(int j = 0; j < N; j++){
                    for(int k = 0; k < N; k++){
                        temp[i][j] += matrix[i][k] * matrix[k][j];
                    }
                }
            }
            matrix.swap(temp);
            K >>= 1;
        }
        return vec;
    }
    vector<T> repow(T K, vector<T> vec, const T MOD){//行列累乗(MODあり)
        assert(N == M);
        while(K > 0){
            if(K & 1) vec = operate(vec, MOD);
            vector<vector<T>> temp(N, vector<T>(M));
            for(int i = 0; i < N; i++){
                for(int j = 0; j < N; j++){
                    for(int k = 0; k < N; k++){
                        temp[i][j] += matrix[i][k] * matrix[k][j] % MOD;
                        if(temp[i][j] >= MOD) temp[i][j] -= MOD;
                    }
                }
            }
            matrix.swap(temp);
            K >>= 1;
        }
        return vec;
    }
    vector<vector<T>> repow(T K, vector<vector<T>> m, const T MOD){//行列累乗(MODあり)単位行列とかとかける
        assert(N == M && m.size() == N && m[0].size() == M);
        mat m1(m);
        while(K > 0){
            if(K & 1) m1 = mulmod(m1, MOD);
            vector<vector<T>> temp(N, vector<T>(M));
            for(int i = 0; i < N; i++){
                for(int j = 0; j < N; j++){
                    for(int k = 0; k < N; k++){
                        temp[i][j] += matrix[i][k] * matrix[k][j] % MOD;
                        if(temp[i][j] >= MOD) temp[i][j] -= MOD;
                    }
                }
            }
            matrix.swap(temp);
            K >>= 1;
        }
        return m1.matrix;
    }
    mat operator+(const vector<vector<T>> &mat2){
        mat res(N, M);
        for(int i = 0; i < N; i++){
            for(int j = 0; j < M; j++) res.matrix[i][j] = (*this).matrix[i][j] + mat2[i][j]; 
        }
        return res;
    }
    mat operator+(const mat &mat1){
        mat res(N, M);
        for(int i = 0; i < N; i++){
            for(int j = 0; j < M; j++) res.matrix[i][j] = (*this).matrix[i][j] + mat1.matrix[i][j]; 
        }
        return res;
    }
    mat operator-(const mat &mat1){
        mat res(N, M);
        for(int i = 0; i < N; i++){
            for(int j = 0; j < M; j++) res.matrix[i][j] = (*this).matrix[i][j] - mat1.matrix[i][j]; 
        }
        return res;
    }
    mat operator-( const vector<vector<T>> &mat2){
        mat res(N, M);
        for(int i = 0; i < N; i++){
            for(int j = 0; j < M; j++) res.matrix[i][j] = (*this).matrix[i][j] - mat2[i][j]; 
        }
        return res;
    }
    mat operator*(const mat &mat2){
        mat res(N, M);
        for(int i = 0; i < N; i++){
            for(int j = 0; j < N; j++){
                for(int k = 0; k < M; k++){
                    res.matrix[i][j] += (*this).matrix[i][k] * mat2.matrix[k][j];
                }
            }
        }
        return res;
    }
    mat& operator+=(const mat &mat2){
        assert(N == mat2.N && M == mat2.M);
        for(int i = 0; i < N; i++){
            for(int j = 0; j < M; j++) (*this).matrix[i][j] += mat2.matrix[i][j];
        }
        return *this;
    }
    mat& operator-=(const mat &mat2){
        assert(N == mat2.N && M == mat2.M);
        for(int i = 0; i < N; i++){
            for(int j = 0; j < M; j++) (*this).matrix[i][j] -= mat2.matrix[i][j];
        }
        return *this;
    }
    mat& operator+=(const vector<vector<T>> &mat2){
        assert(N == mat2.size() && M == mat2[0].size());
        for(int i = 0; i < N; i++){
            for(int j = 0; j < M; j++) (*this).matrix[i][j] += mat2[i][j];
        }
        return *this;
    }
    mat& operator-=(const vector<vector<T>> &mat2){
        assert(N == mat2.size() && M == mat2[0].size());
        for(int i = 0; i < N; i++){
            for(int j = 0; j < M; j++) (*this).matrix[i][j] -= mat2[i][j];
        }
        return *this;
    }
};
int main(){
    long long N, M;
    cin >> N >> M;
    mat<long long> m1;
    vector<vector<long long>> gyo = {{1, 1}, {1, 0}};
    m1.init(gyo);
    vector<long long> fir = {1, 0};
    vector<long long> ans = m1.repow(N - 1, fir, M);
    cout << ans[1] << endl;
}
0