#ifndef JIKKA_MODULO_MATRIX_HPP #define JIKKA_MODULO_MATRIX_HPP /** * @file jikka/modulo_matrix.hpp * @author Kimiyuki Onaka * @copyright Apache License 2.0 */ #include "jikka/divmod.hpp" #include "jikka/matrix.hpp" #include namespace jikka { namespace modmat { using jikka::floormod; template std::array floormod(std::array x, int64_t MOD) { for (size_t i = 0; i < N; ++i) { x[i] = floormod(x[i], MOD); } return x; } template matrix floormod(matrix a, int64_t MOD) { for (size_t y = 0; y < H; ++y) { for (size_t x = 0; x < W; ++x) { a[y][x] = floormod(a[y][x], MOD); } } return a; } template std::array ap(const matrix &a, const std::array &b, int64_t MOD) { std::array c = {}; for (size_t y = 0; y < H; ++y) { for (size_t x = 0; x < W; ++x) { c[y] += a[y][x] * b[x] % MOD; } c[y] = floormod(c[y], MOD); } return c; } template matrix add(const matrix &a, const matrix &b, int64_t MOD) { matrix c; for (size_t y = 0; y < H; ++y) { for (size_t x = 0; x < W; ++x) { c[y][x] = floormod(a[y][x] + b[y][x], MOD); } } return c; } template matrix mul(const matrix &a, const matrix &b, int64_t MOD) { matrix c = {}; for (size_t y = 0; y < H; ++y) { for (size_t z = 0; z < N; ++z) { for (size_t x = 0; x < W; ++x) { c[y][x] += a[y][z] * b[z][x] % MOD; } } } for (size_t y = 0; y < H; ++y) { for (size_t x = 0; x < W; ++x) { c[y][x] = floormod(c[y][x], MOD); } } return c; } template matrix pow(matrix x, int64_t k, int64_t MOD) { matrix y = mat::one(); for (; k; k >>= 1) { if (k & 1) { y = mul(y, x, MOD); } x = mul(x, x, MOD); } return y; } } // namespace modmat } // namespace jikka #endif // JIKKA_MODULO_MATRIX_HPP