#include #include #include #include #include using namespace std; template struct Component { int i; int j; T elem; Component() {} Component(int i, int j, T elem) :i(i), j(j), elem(elem) {} }; template // mod は 2^30-1 以下 struct ModMatrix { using SparseMat = vector>; using Vector = array; array d; uint64_t& at(const size_t i, const size_t j) { return d[i * mat_size + j]; } const uint64_t& at(const size_t i, const size_t j) const { return d[i * mat_size + j]; } void sparse_pow(long long n, ModMatrix& res, SparseMat& sparse_notation) { if (n == 0) { identity(res); return; } ModMatrix tmp; sparse_pow(n / 2, tmp, sparse_notation); if (n & 1) { ModMatrix tmp2; mul(tmp, tmp, tmp2); mul(tmp2, sparse_notation, res); } else { mul(tmp, tmp, res); } } void sparse_pow(long long n, ModMatrix& res) { SparseMat sparse; as_sparse(sparse); sparse_pow(n, res, sparse); } ModMatrix sparse_pow(long long n) { ModMatrix res; sparse_pow(n, res); return res; } void as_sparse(SparseMat& res) { res.clear(); for (int i = 0; i < mat_size; i++) { for (int j = 0; j < mat_size; j++) { if (at(i, j)) res.emplace_back(i, j, at(i, j)); } } } SparseMat as_sparse() { SparseMat res; as_sparse(res); return res; } // 参考: https://ameblo.jp/morimoridiary/entry-10630261646.html static void mul(const ModMatrix& A, const ModMatrix& B, ModMatrix& res) { const int BLOCK = 16; uint64_t temp = 0, * ptemp = 0, partSum[8] = {}; res.d.fill(0); const uint64_t* ptempc = 0; for (int i0 = 0; i0 < mat_size; i0 += BLOCK) { for (int j0 = 0; j0 < mat_size; j0 += BLOCK) { for (int k0 = 0; k0 < mat_size; k0 += BLOCK) { for (int i = i0; i < i0 + BLOCK; i++) { for (int j = j0; j < j0 + BLOCK; j += 8) { partSum[0] = 0; partSum[1] = 0; partSum[2] = 0; partSum[3] = 0; partSum[4] = 0; partSum[5] = 0; partSum[6] = 0; partSum[7] = 0; ptempc = &B.d[k0 * mat_size + j]; for (int k = k0; k < k0 + BLOCK; k++) { temp = A.d[i * mat_size + k]; partSum[0] += temp * ptempc[0]; partSum[1] += temp * ptempc[1]; partSum[2] += temp * ptempc[2]; partSum[3] += temp * ptempc[3]; partSum[4] += temp * ptempc[4]; partSum[5] += temp * ptempc[5]; partSum[6] += temp * ptempc[6]; partSum[7] += temp * ptempc[7]; ptempc = &ptempc[mat_size]; } ptemp = &res.d[i * mat_size + j]; (ptemp[0] += partSum[0]) %= mod; (ptemp[1] += partSum[1]) %= mod; (ptemp[2] += partSum[2]) %= mod; (ptemp[3] += partSum[3]) %= mod; (ptemp[4] += partSum[4]) %= mod; (ptemp[5] += partSum[5]) %= mod; (ptemp[6] += partSum[6]) %= mod; (ptemp[7] += partSum[7]) %= mod; } } } } } } static ModMatrix mul(const ModMatrix& A, const ModMatrix& B) { ModMatrix res; mul(A, B, res); return res; } static void mul(const ModMatrix& A, const SparseMat& B, ModMatrix& res) { res.d.fill(0); for (auto&& [j, k, elem] : B) { for (int i = 0; i < mat_size; i++) { res.at(i, k) += A.at(i, j) * elem; res.at(i, k) %= mod; } } } static ModMatrix mul(const ModMatrix& A, const SparseMat& B) { ModMatrix res; mul(A, B, res); return res; } static void mul(const ModMatrix& A, const Vector& B, Vector& res) { for (int i = 0; i < mat_size; i++) { for (int j = 0; j < mat_size; j++) { auto mul = A.at(i, j) * B[j]; res[i] += mul; } } } static Vector mul(const ModMatrix& A, const Vector& B) { Vector res; mul(A, B, res); return res; } static void identity(ModMatrix& id) { for (int i = 0; i < mat_size; i++) id.at(i, i) = 1; } static ModMatrix identity() { ModMatrix res; identity(res); return res; } }; const int max_k = 5; const int mat_size = max_k * max_k * max_k; const int MOD = 998244353; using Mat = ModMatrix; int main() { int64_t n, k; cin >> n >> k; Mat mat{}; for (int i = 0; i < k; i++) { for (int j = 0; j < k; j++) { for (int l = 0; l < k; l++) { mat.at((i + 1) % k * k * k + j * k + l, i * k * k + j * k + l)++; mat.at(i * k * k + (j + i) % k * k + l, i * k * k + j * k + l)++; mat.at(i * k * k + j * k + (l + j) % k, i * k * k + j * k + l)++; } } } Mat::Vector iv; iv[0] = 1; auto res_vec = Mat::mul(mat.sparse_pow(n), iv); int64_t res = 0; for (int i = 0; i < k; i++) { for (int j = 0; j < k; j++) { res += res_vec.at(i * k * k + j * k); } } cout << res % MOD << endl; }