矩阵及其快速幂
模板
Code
template <typename T>
concept is_mat = requires(T a) { a.row; };
template <typename T>
concept not_mat = !is_mat<T>;
template <typename T>
concept can_do = requires(T a) { a + 1, a * 1; };
template <typename T>
concept not_and_can = not_mat<T> && can_do<T>;
template <not_mat T>
struct mat : public vector<vector<T>> {
int row, col;
template <not_mat U>
void isotype(const mat<U>& o) { assert(row == o.row and col == o.col); }
template <not_mat U>
void can_mul(const mat<U>& o) const { assert(col == o.row); }
mat(const int& n = 1, const int& m = 1, const T& v = 0) : row(n), col(m), vector<vector<T>>(n, vector<T>(m, v)) { assert(n > 0 and m > 0); }
template <not_mat U>
mat(const vector<vector<U>>& o) : row(o.size()), col(o.front().size()), vector<vector<T>>(o) { assert(!o.empty() and !o.front().empty()); }
template <not_mat U>
mat(const mat<U>& o) : row(o.row), col(o, col), vector<vector<T>>(o) {}
template <not_and_can U>
mat<T>& operator+=(const U& o) {
for (auto& x : *this)
for (auto& y : x) y += o;
return *this;
}
template <is_mat U>
mat<T>& operator+=(const U& o) {
isotype(o);
for (int i = 0; i < row; ++i)
for (int j = 0; j < col; ++j)
(*this)[i][j] += o[i][j];
return *this;
}
template <not_and_can U>
mat<T>& operator*=(const U& o) {
for (auto& x : *this)
for (auto& y : x) y *= o;
return *this;
}
template <is_mat U>
friend mat<T> operator*(const mat<T>& a, const U& o) {
a.can_mul(o);
mat<T> ret(a.row, a.col, 0);
for (int i = 0; i < a.row; ++i)
for (int k = 0; k < a.col; ++k)
for (int j = 0; j < o.col; ++j)
ret[i][j] += a[i][k] * o[k][j];
return ret;
}
template <typename U>
friend mat<T> operator+(const mat<T>& a, const U& b) { return mat(a) += b; }
template <not_and_can U>
friend mat<T> operator*(const mat<T>& a, const U& b) { return mat(a) *= b; }
template <is_mat U>
mat<T>& operator*=(const U& o) { return *this = *this * o; }
};
template <not_mat T>
istream& operator>>(istream& i, mat<T>& v) {
for (auto& x : v)
for (auto& y : x) i >> y;
return i;
}
template <not_mat T>
ostream& operator<<(ostream& o, const mat<T>& v) {
cout << v[0][0];
for (int i = 1; i < v.row; ++i) cout << ' ' << v[0][i];
for (int i = 1; i < v.row; ++i) {
cout << '\n'
<< v[i][0];
for (int j = 1; j < v.col; ++j) cout << ' ' << v[i][j];
}
return o;
}
template <not_and_can T>
mat<T> get_diagonal_matrix(const int& n, const T& v = 0) {
mat<T> ret(n, n, 0);
for (int i = 0; i < n; ++i) ret[i][i] = v;
return ret;
}
template <not_mat T>
struct phalanx : public mat<T> {
phalanx(const int& n = 1, const T& v = 0) : mat<T>(n, n, v) {}
template <not_mat U>
phalanx(const vector<vector<U>>& o) : mat<T>(o) { assert(o.size() == o.front().size()); }
template <not_mat U>
phalanx(const phalanx<U>& o) : mat<T>(o) {}
template <Can_bit U>
friend phalanx<T> qpow(const phalanx<T>& A, const U& B) {
phalanx<T> ans(get_diagonal_matrix(A.row, static_cast<T>(1))), a(A);
for (U b = B; b; b >>= 1, a *= a)
if (b & static_cast<U>(1)) ans *= a;
return ans;
}
};
Code
#include <bits/stdc++.h>
using namespace std;
template <typename T>
concept Can_bit = requires(T x) { x >>= 1; };
template <int MOD>
struct modint {
int val;
static int norm(const int& x) { return x < 0 ? x + MOD : x; }
static constexpr int get_mod() { return MOD; }
modint inv() const {
assert(val);
int a = val, b = MOD, u = 1, v = 0, t;
while (b > 0) t = a / b, swap(a -= t * b, b), swap(u -= t * v, v);
assert(b == 1);
return modint(u);
}
modint() : val(0) {}
modint(const int& m) : val(norm(m)) {}
modint(const long long& m) : val(norm(m % MOD)) {}
modint operator-() const { return modint(norm(-val)); }
bool operator==(const modint& o) { return val == o.val; }
bool operator<(const modint& o) { return val < o.val; }
modint& operator+=(const modint& o) { return val = (1ll * val + o.val) % MOD, *this; }
modint& operator-=(const modint& o) { return val = norm(1ll * val - o.val), *this; }
modint& operator*=(const modint& o) { return val = static_cast<int>(1ll * val * o.val % MOD), *this; }
modint& operator/=(const modint& o) { return *this *= o.inv(); }
modint& operator^=(const modint& o) { return val ^= o.val, *this; }
modint& operator>>=(const modint& o) { return val >>= o.val, *this; }
modint& operator<<=(const modint& o) { return val <<= o.val, *this; }
modint operator-(const modint& o) const { return modint(*this) -= o; }
modint operator+(const modint& o) const { return modint(*this) += o; }
modint operator*(const modint& o) const { return modint(*this) *= o; }
modint operator/(const modint& o) const { return modint(*this) /= o; }
modint operator^(const modint& o) const { return modint(*this) ^= o; }
modint operator>>(const modint& o) const { return modint(*this) >>= o; }
modint operator<<(const modint& o) const { return modint(*this) <<= o; }
friend std::istream& operator>>(std::istream& is, modint& a) {
long long v;
return is >> v, a.val = norm(v % MOD), is;
}
friend std::ostream& operator<<(std::ostream& os, const modint& a) { return os << a.val; }
friend std::string tostring(const modint& a) { return std::to_string(a.val); }
template <Can_bit T>
friend modint qpow(const modint& a, const T& b) {
assert(b >= 0);
modint x = a, res = 1;
for (T p = b; p; x *= x, p >>= 1)
if (p & 1) res *= x;
return res;
}
};
using M107 = modint<1000000007>;
using M998 = modint<998244353>;
using Mint = M107;
// constexpr mod = ...;
// using Mint = modint<mod>;
struct Fact {
std::vector<Mint> fact, factinv;
const int n;
Fact(const int& _n) : n(_n), fact(_n + 1, Mint(1)), factinv(_n + 1) {
for (int i = 1; i <= n; ++i) fact[i] = fact[i - 1] * i;
factinv[n] = fact[n].inv();
for (int i = n; i; --i) factinv[i - 1] = factinv[i] * i;
}
Mint C(const int& n, const int& k) {
if (n < 0 || k < 0 || n < k) return 0;
return fact[n] * factinv[k] * factinv[n - k];
}
Mint A(const int& n, const int& k) {
if (n < 0 || k < 0 || n < k) return 0;
return fact[n] * factinv[n - k];
}
};
template <typename T>
concept is_mat = requires(T a) { a.row; };
template <typename T>
concept not_mat = !is_mat<T>;
template <typename T>
concept can_do = requires(T a) { a + 1, a * 1; };
template <typename T>
concept not_and_can = not_mat<T> && can_do<T>;
template <not_mat T>
struct mat : public vector<vector<T>> {
int row, col;
template <not_mat U>
void isotype(const mat<U>& o) { assert(row == o.row and col == o.col); }
template <not_mat U>
void can_mul(const mat<U>& o) const { assert(col == o.row); }
mat(const int& n = 1, const int& m = 1, const T& v = 0) : row(n), col(m), vector<vector<T>>(n, vector<T>(m, v)) { assert(n > 0 and m > 0); }
template <not_mat U>
mat(const vector<vector<U>>& o) : row(o.size()), col(o.front().size()), vector<vector<T>>(o) { assert(!o.empty() and !o.front().empty()); }
template <not_mat U>
mat(const mat<U>& o) : row(o.row), col(o, col), vector<vector<T>>(o) {}
template <not_and_can U>
mat<T>& operator+=(const U& o) {
for (auto& x : *this)
for (auto& y : x) y += o;
return *this;
}
template <is_mat U>
mat<T>& operator+=(const U& o) {
isotype(o);
for (int i = 0; i < row; ++i)
for (int j = 0; j < col; ++j)
(*this)[i][j] += o[i][j];
return *this;
}
template <not_and_can U>
mat<T>& operator*=(const U& o) {
for (auto& x : *this)
for (auto& y : x) y *= o;
return *this;
}
template <is_mat U>
friend mat<T> operator*(const mat<T>& a, const U& o) {
a.can_mul(o);
mat<T> ret(a.row, a.col, 0);
for (int i = 0; i < a.row; ++i)
for (int k = 0; k < a.col; ++k)
for (int j = 0; j < o.col; ++j)
ret[i][j] += a[i][k] * o[k][j];
return ret;
}
template <typename U>
friend mat<T> operator+(const mat<T>& a, const U& b) { return mat(a) += b; }
template <not_and_can U>
friend mat<T> operator*(const mat<T>& a, const U& b) { return mat(a) *= b; }
template <is_mat U>
mat<T>& operator*=(const U& o) { return *this = *this * o; }
};
template <not_mat T>
istream& operator>>(istream& i, mat<T>& v) {
for (auto& x : v)
for (auto& y : x) i >> y;
return i;
}
template <not_mat T>
ostream& operator<<(ostream& o, const mat<T>& v) {
cout << v[0][0];
for (int i = 1; i < v.row; ++i) cout << ' ' << v[0][i];
for (int i = 1; i < v.row; ++i) {
cout << '\n'
<< v[i][0];
for (int j = 1; j < v.col; ++j) cout << ' ' << v[i][j];
}
return o;
}
template <not_and_can T>
mat<T> get_diagonal_matrix(const int& n, const T& v = 0) {
mat<T> ret(n, n, 0);
for (int i = 0; i < n; ++i) ret[i][i] = v;
return ret;
}
template <not_mat T>
struct phalanx : public mat<T> {
phalanx(const int& n = 1, const T& v = 0) : mat<T>(n, n, v) {}
template <not_mat U>
phalanx(const vector<vector<U>>& o) : mat<T>(o) { assert(o.size() == o.front().size()); }
template <not_mat U>
phalanx(const phalanx<U>& o) : mat<T>(o) {}
template <Can_bit U>
friend phalanx<T> qpow(const phalanx<T>& A, const U& B) {
phalanx<T> ans(get_diagonal_matrix(A.row, static_cast<T>(1))), a(A);
for (U b = B; b; b >>= 1, a *= a)
if (b & static_cast<U>(1)) ans *= a;
return ans;
}
};
int main() {
std::ios_base::sync_with_stdio(false), std::cin.tie(nullptr), std::cout.tie(nullptr);
int n;
long long k;
cin >> n >> k;
phalanx<Mint> a(n);
cin >> a;
cout << qpow(a, k);
}