関数の形がフィボナッチ数列にそっくりであることに注目してみましょう。
フィボナッチ数列の第 項は、行列累乗を用いることで で求めることができます。
また、 として、 から順番に計算してみましょう。
とフィボナッチ数列の値が係数として現れることが分かります。
よって、フィボナッチ数列の第 項 の値を とすると、
と求められます。
したがって、この問題を十分高速に解くことができました。
#include<bits/stdc++.h> using namespace std; const long long MOD = 998244353; // 行列の積を計算 vector<vector<long long>> mul(vector<vector<long long>> a, vector<vector<long long>> b){ vector<vector<long long>> res((int) a.size(), vector<long long>(b[0].size())); for(int i = 0; i < (int) a.size(); i++){ for(int j = 0; j < (int) b[0].size(); j++){ for(int k = 0; k < (int) b.size(); k++){ res[i][j] += a[i][k] * b[k][j]; res[i][j] %= MOD; } } } return res; } // 繰り返し二乗法 long long calc(long long n){ vector<vector<long long>> a(2, vector<long long>(2)); a[0][0] = 1; a[0][1] = 1; a[1][0] = 1; a[1][1] = 0; vector<vector<long long>> b(2, vector<long long>(2, 0)); for(int i = 0; i < 2; i++) b[i][i] = 1; while(n > 0){ if(n & 1) b = mul(a, b); a = mul(a, a); n >>= 1; } return b[1][0]; } int main(){ long long n; cin >> n; if(n == 0){ cout << 8 << endl; }else if(n == 1){ cout << 88 << endl; }else{ long long ans = 88 * calc(n) + 8 * calc(n - 1); ans %= MOD; cout << ans << endl; } }