library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub gyouzasushi/library

:heavy_check_mark: test/library-checker/pow_of_matrix.test.cpp

Depends on

Code

#define PROBLEM "https://judge.yosupo.jp/problem/pow_of_matrix"
#include <atcoder/modint>
#include <iostream>

#include "math/matrix.hpp"

using mint = atcoder::modint998244353;
int main() {
    int n;
    long long k;
    std::cin >> n >> k;
    matrix<mint> a(n, n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            int x;
            std::cin >> x;
            a[i][j] = mint::raw(x);
        }
    }
    matrix b = a.pow(k);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            std::cout << b[i][j].val() << " \n"[j == n - 1];
        }
    }
}
#line 1 "test/library-checker/pow_of_matrix.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/pow_of_matrix"
#include <atcoder/modint>
#include <iostream>

#line 2 "math/matrix.hpp"
#include <cassert>
#include <optional>
#include <utility>
#include <vector>

#line 2 "algebra/concept.hpp"
#include <concepts>
template <class M>
concept semigroup = requires(typename M::S a, typename M::S b) {
    { M::op(a, b) } -> std::same_as<typename M::S>;
};
template <class M>
concept monoid = semigroup<M> && requires {
    { M::e() } -> std::same_as<typename M::S>;
};
template <class G>
concept group = monoid<G> && requires(typename G::S a) {
    { G::inv(a) } -> std::same_as<typename G::S>;
};
template <class A>
concept action = requires(typename A::F f, typename A::F g) {
    { A::composition(f, g) } -> std::same_as<typename A::F>;
    { A::id() } -> std::same_as<typename A::F>;
    { A::composition_commutative } -> std::convertible_to<bool>;
};
template <class A>
concept acted_monoid = monoid<A> && action<A> && requires(typename A::S x, typename A::F f) {
    { A::mapping(f, x) } -> std::same_as<typename A::S>;
};
template <class R>
concept semiring = requires(typename R::S a, typename R::S b) {
    { R::add(a, b) } -> std::same_as<typename R::S>;
    { R::zero() } -> std::same_as<typename R::S>;
    { R::mul(a, b) } -> std::same_as<typename R::S>;
    { R::one() } -> std::same_as<typename R::S>;
};
template <class A>
concept beats_acted_monoid = acted_monoid<A> && requires(typename A::S x) {
    { x.fail } -> std::convertible_to<bool>;
};
#line 2 "algebra/semiring_plus_times.hpp"
template <class T>
struct semiring_plus_times {
    using S = T;
    static S add(S a, S b) {
        return a + b;
    }
    static S zero() {
        return T(0);
    }
    static S mul(S a, S b) {
        return a * b;
    }
    static S one() {
        return T(1);
    }
};
#line 9 "math/matrix.hpp"
template <semiring R>
struct semiring_matrix {
    using S = typename R::S;
    semiring_matrix() : semiring_matrix(0, 0) {}
    semiring_matrix(int h, int w) : h(h), w(w), a(h, std::vector<S>(w, R::zero())) {}
    explicit semiring_matrix(std::vector<std::vector<S>> v) : h(int(v.size())), w(h ? int(v[0].size()) : 0), a(std::move(v)) {
        for (int i = 0; i < h; i++) assert(int(a[i].size()) == w);
    }
    static semiring_matrix e(int n) {
        semiring_matrix ret(n, n);
        for (int i = 0; i < n; i++) ret[i][i] = R::one();
        return ret;
    }
    int height() const {
        return h;
    }
    int width() const {
        return w;
    }
    const std::vector<S>& operator[](int i) const {
        return a[i];
    }
    std::vector<S>& operator[](int i) {
        return a[i];
    }
    friend semiring_matrix operator+(const semiring_matrix& lhs, const semiring_matrix& rhs) {
        assert(lhs.h == rhs.h && lhs.w == rhs.w);
        semiring_matrix ret(lhs.h, lhs.w);
        for (int i = 0; i < lhs.h; i++) {
            for (int j = 0; j < lhs.w; j++) ret[i][j] = R::add(lhs[i][j], rhs[i][j]);
        }
        return ret;
    }
    friend semiring_matrix operator*(const semiring_matrix& lhs, const semiring_matrix& rhs) {
        assert(lhs.w == rhs.h);
        semiring_matrix ret(lhs.h, rhs.w);
        for (int i = 0; i < lhs.h; i++) {
            for (int k = 0; k < lhs.w; k++) {
                for (int j = 0; j < rhs.w; j++) ret[i][j] = R::add(ret[i][j], R::mul(lhs[i][k], rhs[k][j]));
            }
        }
        return ret;
    }
    semiring_matrix& operator+=(const semiring_matrix& rhs) {
        return *this = *this + rhs;
    }
    semiring_matrix& operator*=(const semiring_matrix& rhs) {
        return *this = *this * rhs;
    }
    semiring_matrix pow(long long k) const {
        assert(h == w && k >= 0);
        semiring_matrix x = *this, ret = e(h);
        while (k) {
            if (k & 1) ret *= x;
            x *= x;
            k >>= 1;
        }
        return ret;
    }
    friend bool operator==(const semiring_matrix& lhs, const semiring_matrix& rhs) {
        return lhs.a == rhs.a;
    }

private:
    int h, w;
    std::vector<std::vector<S>> a;
};
template <class T>
using matrix = semiring_matrix<semiring_plus_times<T>>;
template <class T> T determinant(matrix<T> a) {
    int n = a.height();
    assert(n == a.width());
    T det = 1;
    for (int c = 0; c < n; c++) {
        int p = c;
        while (p < n && a[p][c] == T(0)) p++;
        if (p == n) return 0;
        if (p != c) {
            std::swap(a[p], a[c]);
            det = -det;
        }
        det *= a[c][c];
        T inv = T(1) / a[c][c];
        for (int i = c + 1; i < n; i++) {
            if (a[i][c] == T(0)) continue;
            T f = a[i][c] * inv;
            for (int j = c; j < n; j++) a[i][j] -= f * a[c][j];
        }
    }
    return det;
}
template <class T> std::optional<matrix<T>> inverse(matrix<T> a) {
    int n = a.height();
    assert(n == a.width());
    matrix<T> b = matrix<T>::e(n);
    for (int c = 0; c < n; c++) {
        int p = c;
        while (p < n && a[p][c] == T(0)) p++;
        if (p == n) return std::nullopt;
        std::swap(a[p], a[c]);
        std::swap(b[p], b[c]);
        T inv = T(1) / a[c][c];
        for (int j = 0; j < n; j++) {
            a[c][j] *= inv;
            b[c][j] *= inv;
        }
        for (int i = 0; i < n; i++) {
            if (i == c || a[i][c] == T(0)) continue;
            T f = a[i][c];
            for (int j = 0; j < n; j++) {
                a[i][j] -= f * a[c][j];
                b[i][j] -= f * b[c][j];
            }
        }
    }
    return b;
}
template <class T> int matrix_rank(matrix<T> a) {
    int h = a.height(), w = a.width(), r = 0;
    for (int c = 0; c < w && r < h; c++) {
        int p = r;
        while (p < h && a[p][c] == T(0)) p++;
        if (p == h) continue;
        std::swap(a[p], a[r]);
        T inv = T(1) / a[r][c];
        for (int i = r + 1; i < h; i++) {
            if (a[i][c] == T(0)) continue;
            T f = a[i][c] * inv;
            for (int j = c; j < w; j++) a[i][j] -= f * a[r][j];
        }
        r++;
    }
    return r;
}
template <class T> struct linear_system_solution {
    std::vector<T> x;
    std::vector<std::vector<T>> kernel;
};
template <class T> std::optional<linear_system_solution<T>> solve_linear_system(matrix<T> a, std::vector<T> b) {
    int h = a.height(), w = a.width();
    assert(int(b.size()) == h);
    std::vector<int> pivot;
    int r = 0;
    for (int c = 0; c < w && r < h; c++) {
        int p = r;
        while (p < h && a[p][c] == T(0)) p++;
        if (p == h) continue;
        std::swap(a[p], a[r]);
        std::swap(b[p], b[r]);
        T inv = T(1) / a[r][c];
        for (int j = c; j < w; j++) a[r][j] *= inv;
        b[r] *= inv;
        for (int i = 0; i < h; i++) {
            if (i == r || a[i][c] == T(0)) continue;
            T f = a[i][c];
            for (int j = c; j < w; j++) a[i][j] -= f * a[r][j];
            b[i] -= f * b[r];
        }
        pivot.push_back(c);
        r++;
    }
    for (int i = r; i < h; i++) {
        if (b[i] != T(0)) return std::nullopt;
    }
    linear_system_solution<T> ret;
    ret.x.assign(w, T(0));
    for (int i = 0; i < r; i++) ret.x[pivot[i]] = b[i];
    std::vector<bool> is_pivot(w, false);
    for (int c : pivot) is_pivot[c] = true;
    for (int f = 0; f < w; f++) {
        if (is_pivot[f]) continue;
        std::vector<T> v(w, T(0));
        v[f] = T(1);
        for (int i = 0; i < r; i++) v[pivot[i]] = -a[i][f];
        ret.kernel.push_back(std::move(v));
    }
    return ret;
}
#line 6 "test/library-checker/pow_of_matrix.test.cpp"

using mint = atcoder::modint998244353;
int main() {
    int n;
    long long k;
    std::cin >> n >> k;
    matrix<mint> a(n, n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            int x;
            std::cin >> x;
            a[i][j] = mint::raw(x);
        }
    }
    matrix b = a.pow(k);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            std::cout << b[i][j].val() << " \n"[j == n - 1];
        }
    }
}
Back to top page