This documentation is automatically generated by online-judge-tools/verification-helper
#pragma once
#include <array>
#include <cassert>
#include <initializer_list>
#include <vector>
#include "../utility/int_alias.cpp"
#include "../utility/rep.cpp"
template <class S> class SemiRingMatrix {
using T = typename S::Type;
using A = typename S::Sum;
using M = typename S::Product;
using Self = SemiRingMatrix;
std::vector<std::vector<T>> data;
public:
SemiRingMatrix() = default;
explicit SemiRingMatrix(const int h, const int w, const T& val = A::zero()) : data(h, std::vector<T>(w, val)) {}
SemiRingMatrix(const std::vector<std::vector<T>>& vec) : data(vec) {
for (const auto& v : data) assert(v.size() == width());
}
SemiRingMatrix(const std::initializer_list<std::initializer_list<T>>& list) {
data.reserve(list.size());
for (const auto& v : list) data.emplace_back(v.begin(), v.end());
for (const auto& v : data) assert(v.size() == width());
}
int height() const { return data.size(); }
int width() const { return data.empty() ? 0 : data[0].size(); }
T& operator()(const int i, const int j) {
assert(0 <= i and i < height());
assert(0 <= j and j < width());
return data[i][j];
}
const T& operator()(const int i, const int j) const {
assert(0 <= i and i < height());
assert(0 <= j and j < width());
return data[i][j];
}
Self operator+(const Self& other) const { return Self(*this) += other; }
Self& operator+=(const Self& other) {
assert(height() == other.height());
assert(width() == other.width());
for (const int i : rep(height()))
for (const int j : rep(width())) data[i][j] = A::operation(data[i][j], other.data[i][j]);
return *this;
}
Self operator*(const Self& other) const {
assert(width() == other.height());
Self ret(height(), other.width(), A::identity());
for (const int i : rep(height()))
for (const int k : rep(width()))
for (const int j : rep(other.width()))
ret.data[i][j] = A::operation(ret.data[i][j], M::operation(data[i][k], other.data[k][j]));
return ret;
}
Self operator*(const T& other) const { return Self(*this) *= other; }
Self& operator*=(const T& other) {
for (const int i : rep(height()))
for (const int j : rep(width())) data[i][j] = M::operation(data[i][j], other);
}
Self pow(u64 exp) const {
assert(height() == width());
Self ret(height(), width(), A::identity()), mult(*this);
for (const int i : rep(height())) ret.data[i][i] = M::identity();
for (; exp > 0; exp >>= 1) {
if (exp & 1) ret = ret * mult;
mult = mult * mult;
}
return ret;
}
};
#line 2 "math/semiring_matrix.cpp"
#include <array>
#include <cassert>
#include <initializer_list>
#include <vector>
#line 2 "utility/int_alias.cpp"
#include <cstdint>
using i32 = std::int32_t;
using u32 = std::uint32_t;
using i64 = std::int64_t;
using u64 = std::uint64_t;
using i128 = __int128_t;
using u128 = __uint128_t;
#line 2 "utility/rep.cpp"
#include <algorithm>
class Range {
struct Iter {
int itr;
constexpr Iter(const int pos) noexcept : itr(pos) {}
constexpr void operator++() noexcept { ++itr; }
constexpr bool operator!=(const Iter& other) const noexcept { return itr != other.itr; }
constexpr int operator*() const noexcept { return itr; }
};
const Iter first, last;
public:
explicit constexpr Range(const int first, const int last) noexcept : first(first), last(std::max(first, last)) {}
constexpr Iter begin() const noexcept { return first; }
constexpr Iter end() const noexcept { return last; }
};
constexpr Range rep(const int l, const int r) noexcept { return Range(l, r); }
constexpr Range rep(const int n) noexcept { return Range(0, n); }
#line 8 "math/semiring_matrix.cpp"
template <class S> class SemiRingMatrix {
using T = typename S::Type;
using A = typename S::Sum;
using M = typename S::Product;
using Self = SemiRingMatrix;
std::vector<std::vector<T>> data;
public:
SemiRingMatrix() = default;
explicit SemiRingMatrix(const int h, const int w, const T& val = A::zero()) : data(h, std::vector<T>(w, val)) {}
SemiRingMatrix(const std::vector<std::vector<T>>& vec) : data(vec) {
for (const auto& v : data) assert(v.size() == width());
}
SemiRingMatrix(const std::initializer_list<std::initializer_list<T>>& list) {
data.reserve(list.size());
for (const auto& v : list) data.emplace_back(v.begin(), v.end());
for (const auto& v : data) assert(v.size() == width());
}
int height() const { return data.size(); }
int width() const { return data.empty() ? 0 : data[0].size(); }
T& operator()(const int i, const int j) {
assert(0 <= i and i < height());
assert(0 <= j and j < width());
return data[i][j];
}
const T& operator()(const int i, const int j) const {
assert(0 <= i and i < height());
assert(0 <= j and j < width());
return data[i][j];
}
Self operator+(const Self& other) const { return Self(*this) += other; }
Self& operator+=(const Self& other) {
assert(height() == other.height());
assert(width() == other.width());
for (const int i : rep(height()))
for (const int j : rep(width())) data[i][j] = A::operation(data[i][j], other.data[i][j]);
return *this;
}
Self operator*(const Self& other) const {
assert(width() == other.height());
Self ret(height(), other.width(), A::identity());
for (const int i : rep(height()))
for (const int k : rep(width()))
for (const int j : rep(other.width()))
ret.data[i][j] = A::operation(ret.data[i][j], M::operation(data[i][k], other.data[k][j]));
return ret;
}
Self operator*(const T& other) const { return Self(*this) *= other; }
Self& operator*=(const T& other) {
for (const int i : rep(height()))
for (const int j : rep(width())) data[i][j] = M::operation(data[i][j], other);
}
Self pow(u64 exp) const {
assert(height() == width());
Self ret(height(), width(), A::identity()), mult(*this);
for (const int i : rep(height())) ret.data[i][i] = M::identity();
for (; exp > 0; exp >>= 1) {
if (exp & 1) ret = ret * mult;
mult = mult * mult;
}
return ret;
}
};