結果

問題 No.658 テトラナッチ数列 Hard
ユーザー @abcde@abcde
提出日時 2019-03-30 12:40:39
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 125 ms / 2,000 ms
コード長 5,633 bytes
コンパイル時間 2,147 ms
コンパイル使用メモリ 155,416 KB
実行使用メモリ 4,380 KB
最終ジャッジ日時 2023-08-08 13:11:35
合計ジャッジ時間 3,044 ms
ジャッジサーバーID
(参考情報)
judge12 / judge15
このコードへのチャレンジ(β)

テストケース

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

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;

// 参照サイト.
// 動的計画法でフィボナッチ数列の計算を速くする。
// https://yosuke-furukawa.hatenablog.com/entry/20120120/1327056359
typedef long long LL;
// const LL MOD = 1e9 + 7;
const LL MOD = 1e1 + 7;

// 行列積のロジックを一部抽出した版.
// @param p1 ~ q4: 行列の要素.
// @return ret: 行列積の計算結果.
LL matrixProduct(LL p1, LL p2, LL p3, LL p4, LL q1, LL q2, LL q3, LL q4){

    LL ret = 0;
    ret += p1 * q1, ret %= MOD;
    ret += p2 * q2, ret %= MOD;
    ret += p3 * q3, ret %= MOD;
    ret += p4 * q4, ret %= MOD;
    return ret;
}

// Tetranacci sequence の 第N項 を計算.
// A000078 Tetranacci numbers:
// https://oeis.org/A000078
// ex.
// MOD = 1e9 + 7 とすれば, 
// N = 20 なら tetranacciByMatrix(20) = 20569 % MOD      = 20569     のように計算できる.
// N = 37 なら tetranacciByMatrix(37) = 1439975216 % MOD = 439975209 のように計算できる.
// @param N: 第N項.
// @return ans: Tetranacci sequence の 第N項.
LL tetranacciByMatrix(LL N){

    // 0. N が 4以下ならば, 返却.
    if(N < 4)  return 0;
    if(N == 4) return 1;

    // 1. N を 2で割っていく.
    // ex. N = 5以降で, はじめて, 行列積を適用する必要が出てくる.
    N -= 4;
    map<LL, LL> m;
    while(N){
        LL q = N >> 1;
        LL r = N & 1;
        m[q] = r;
        N >>= 1;
    }
    // for(auto &p : m) cout << p.first << " " << p.second << endl;

    // 2. 1. の 結果から, 逆算.
    // 第 0成分(1行1列): 1, 第 1成分(1行2列): 1, 第 2成分(1行3列): 1, 第 3成分(1行4列): 1
    // 第 4成分(2行1列): 1, 第 5成分(2行2列): 0, 第 6成分(2行3列): 0, 第 7成分(2行4列): 0
    // 第 8成分(3行1列): 0, 第 9成分(3行2列): 1, 第10成分(3行3列): 0, 第11成分(3行4列): 0
    // 第12成分(4行1列): 0, 第13成分(4行2列): 0, 第14成分(4行3列): 1, 第15成分(4行4列): 0
    LL ans[16] = {1, 0, 0, 0, 
                  0, 1, 0, 0, 
                  0, 0, 1, 0, 
                  0, 0, 0, 1};
    for(auto &p : m){
        if(p.first != 0){
            LL t11 = ans[0],  t12 = ans[1],  t13 = ans[2],  t14 = ans[3],
               t21 = ans[4],  t22 = ans[5],  t23 = ans[6],  t24 = ans[7],
               t31 = ans[8],  t32 = ans[9],  t33 = ans[10], t34 = ans[11],
               t41 = ans[12], t42 = ans[13], t43 = ans[14], t44 = ans[15];
            ans[0] =  matrixProduct(t11, t12, t13, t14, t11, t21, t31, t41);
            ans[1] =  matrixProduct(t11, t12, t13, t14, t12, t22, t32, t42);
            ans[2] =  matrixProduct(t11, t12, t13, t14, t13, t23, t33, t43);
            ans[3] =  matrixProduct(t11, t12, t13, t14, t14, t24, t34, t44);
            ans[4] =  matrixProduct(t21, t22, t23, t24, t11, t21, t31, t41);
            ans[5] =  matrixProduct(t21, t22, t23, t24, t12, t22, t32, t42);
            ans[6] =  matrixProduct(t21, t22, t23, t24, t13, t23, t33, t43);
            ans[7] =  matrixProduct(t21, t22, t23, t24, t14, t24, t34, t44);
            ans[8] =  matrixProduct(t31, t32, t33, t34, t11, t21, t31, t41);
            ans[9] =  matrixProduct(t31, t32, t33, t34, t12, t22, t32, t42);
            ans[10] = matrixProduct(t31, t32, t33, t34, t13, t23, t33, t43);
            ans[11] = matrixProduct(t31, t32, t33, t34, t14, t24, t34, t44);
            ans[12] = matrixProduct(t41, t42, t43, t44, t11, t21, t31, t41);
            ans[13] = matrixProduct(t41, t42, t43, t44, t12, t22, t32, t42);
            ans[14] = matrixProduct(t41, t42, t43, t44, t13, t23, t33, t43);
            ans[15] = matrixProduct(t41, t42, t43, t44, t14, t24, t34, t44);
        }
        if(p.second == 1){
            LL t11 = ans[0],  t12 = ans[1],  t13 = ans[2],  t14 = ans[3],
               t21 = ans[4],  t22 = ans[5],  t23 = ans[6],  t24 = ans[7],
               t31 = ans[8],  t32 = ans[9],  t33 = ans[10], t34 = ans[11],
               t41 = ans[12], t42 = ans[13], t43 = ans[14], t44 = ans[15];
            ans[0] =  matrixProduct(t11, t12, t13, t14, 1, 1, 0, 0);
            ans[1] =  matrixProduct(t11, t12, t13, t14, 1, 0, 1, 0);
            ans[2] =  matrixProduct(t11, t12, t13, t14, 1, 0, 0, 1);
            ans[3] =  matrixProduct(t11, t12, t13, t14, 1, 0, 0, 0);
            ans[4] =  matrixProduct(t21, t22, t23, t24, 1, 1, 0, 0);
            ans[5] =  matrixProduct(t21, t22, t23, t24, 1, 0, 1, 0);
            ans[6] =  matrixProduct(t21, t22, t23, t24, 1, 0, 0, 1);
            ans[7] =  matrixProduct(t21, t22, t23, t24, 1, 0, 0, 0);
            ans[8] =  matrixProduct(t31, t32, t33, t34, 1, 1, 0, 0);
            ans[9] =  matrixProduct(t31, t32, t33, t34, 1, 0, 1, 0);
            ans[10] = matrixProduct(t31, t32, t33, t34, 1, 0, 0, 1);
            ans[11] = matrixProduct(t31, t32, t33, t34, 1, 0, 0, 0);
            ans[12] = matrixProduct(t41, t42, t43, t44, 1, 1, 0, 0);
            ans[13] = matrixProduct(t41, t42, t43, t44, 1, 0, 1, 0);
            ans[14] = matrixProduct(t41, t42, t43, t44, 1, 0, 0, 1);
            ans[15] = matrixProduct(t41, t42, t43, t44, 1, 0, 0, 0);
        }
    }
    
    // 3. 計算後の 第0成分(1行1列) を 返却.
    // for(int i = 0; i < 16; i++) cout << ans[i] << " ";
    return ans[0];

}

int main() {
    
    // 1. 入力情報取得.
    LL Q;
    cin >> Q;
    
    // 2. 各クエリごとに, Tetranacci数列 を 17 で割った余りを出力.
    for(LL i = 0; i < Q; i++){
        LL q;
        cin >> q;
        LL t = tetranacciByMatrix(q);
        cout << t << endl;
    }

    // 3. 後処理.
    return 0;
    
}
0