結果
問題 | No.840 ほむほむほむら |
ユーザー | keymoon |
提出日時 | 2022-04-09 00:23:00 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
RE
|
実行時間 | - |
コード長 | 5,234 bytes |
コンパイル時間 | 1,202 ms |
コンパイル使用メモリ | 85,092 KB |
実行使用メモリ | 5,376 KB |
最終ジャッジ日時 | 2024-05-06 10:02:49 |
合計ジャッジ時間 | 5,680 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | RE | - |
testcase_01 | RE | - |
testcase_02 | RE | - |
testcase_03 | RE | - |
testcase_04 | RE | - |
testcase_05 | RE | - |
testcase_06 | RE | - |
testcase_07 | RE | - |
testcase_08 | RE | - |
testcase_09 | RE | - |
testcase_10 | RE | - |
testcase_11 | RE | - |
testcase_12 | RE | - |
testcase_13 | RE | - |
testcase_14 | RE | - |
testcase_15 | RE | - |
testcase_16 | RE | - |
testcase_17 | RE | - |
testcase_18 | RE | - |
testcase_19 | RE | - |
testcase_20 | RE | - |
testcase_21 | RE | - |
testcase_22 | RE | - |
testcase_23 | RE | - |
testcase_24 | RE | - |
testcase_25 | RE | - |
testcase_26 | RE | - |
testcase_27 | RE | - |
ソースコード
#include <iostream> #include <algorithm> #include <vector> #include <array> #include <set> using namespace std; template<typename T> struct Component { int i; int j; T elem; Component() {} Component(int i, int j, T elem) :i(i), j(j), elem(elem) {} }; template<size_t mat_size, uint32_t mod> // mod は 2^30-1 以下 struct ModMatrix { using SparseMat = vector<Component<uint64_t>>; using Vector = array<uint64_t, mat_size>; array<uint64_t, mat_size* mat_size> 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<mat_size, MOD>; 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; }