矩阵及其快速幂
模板
Code
template <typename T>
concept arithmetic = is_arithmetic_v<T>;
template <typename T>
struct mat : public vector<vector<T>> {
int row, col;
template <typename U>
void isotype(const mat<U>& o) { assert(row == o.row and col == o.col); }
template <typename 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 <typename U>
mat(const vector<vector<U>>& o) : row(o.size()), col(o.front().size()), vector<vector<U>>(o) { assert(!o.empty() and !o.front().empty()); }
template <typename U>
mat(const mat<U>& o) : row(o.row), col(o, col), vector<vector<T>>(o) {}
template <arithmetic U>
mat<T>& operator+=(const U& o) {
for (auto& x : *this)
for (T& y : x) y += o;
return *this;
}
template <typename U>
mat<T>& operator+=(const mat<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 <arithmetic U>
mat<T>& operator*=(const U& o) {
for (auto& x : *this)
for (auto& y : x) y *= o;
return *this;
}
template <typename U>
friend mat<T> operator*(const mat<T>& a, const mat<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 <arithmetic U>
friend mat<T> operator+(const mat<T>& a, const U& b) { return mat(a) += b; }
template <typename U>
friend mat<T> operator+(const mat<T>& a, const mat<U>& b) { return mat(a) += b; }
template <arithmetic U>
friend mat<T> operator*(const mat<T>& a, const U& b) { return mat(a) *= b; }
template <typename U>
mat<T>& operator*=(const mat<U>& o) { return *this = *this * o; }
};
template <typename T>
istream& operator>>(istream& i, mat<T>& v) {
for (auto& x : v)
for (auto& y : x)
i >> y;
return i;
}
template <typename 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 <typename 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 <typename T>
struct phalanx : public mat<T> {
phalanx(const int& n = 1, const T& v = 0) : mat<T>(n, n, v) {}
template <typename U>
phalanx(const vector<vector<U>>& o) : mat<T>(o) { assert(o.size() == o.front().size()); }
template <typename U>
phalanx(const phalanx<U>& o) : mat<T>(o) {}
template <integral 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 & 1) ans *= a;
return ans;
}
};
洛谷P3390
Code
#include <bits/stdc++.h>
using namespace std;
template <typename T>
T inv(const T& x, const T& y) {
assert(x != 0);
T u = 0, v = 1, a = x, m = y, t;
while (a != 0) {
t = m / a;
std::swap(a, m -= t * a);
std::swap(u -= t * v, v);
}
assert(m == 1);
return u;
}
constexpr int mod = 1e9 + 7;
struct Mint {
int val;
template <typename T>
static int norm(const T& x) {
int t = static_cast<int>(mod <= x and x < mod ? x : x % mod);
return t < 0 ? t + mod : t;
}
Mint() : val(0) {}
Mint(const int& m) : val(norm(m)) {}
Mint(const long long& m) : val(norm(m % mod)) {}
Mint operator-() const { return Mint(norm(-val)); }
bool operator==(const Mint& o) { return val == o.val; }
bool operator<(const Mint& o) { return val < o.val; }
Mint& operator+=(const Mint& o) { return val = norm(val + o.val), *this; }
Mint& operator-=(const Mint& o) { return val = norm(val - o.val), *this; }
Mint& operator*=(const Mint& o) { return val = static_cast<int>(1ll * val * o.val % mod), *this; }
Mint& operator/=(const Mint& o) { return *this *= Mint(inv(o.val, mod)); }
Mint& operator^=(const Mint& o) { return val ^= o.val, *this; }
Mint& operator>>=(const Mint& o) { return val >>= o.val, *this; }
Mint& operator<<=(const Mint& o) { return val <<= o.val, *this; }
Mint operator-(const Mint& o) const { return Mint(*this) -= o; }
Mint operator+(const Mint& o) const { return Mint(*this) += o; }
Mint operator*(const Mint& o) const { return Mint(*this) *= o; }
Mint operator/(const Mint& o) const { return Mint(*this) /= o; }
Mint operator^(const Mint& o) const { return Mint(*this) ^= o; }
Mint operator>>(const Mint& o) const { return Mint(*this) >>= o; }
Mint operator<<(const Mint& o) const { return Mint(*this) <<= o; }
friend std::istream& operator>>(std::istream& is, Mint& a) {
long long v;
is >> v;
a.val = norm(v);
return is;
}
friend std::ostream& operator<<(std::ostream& os, const Mint& a) { return os << a.val; }
};
std::string tostring(const Mint& a) { return tostring(a.val); }
template <typename T>
Mint qpow(const Mint& a, const T& b) {
assert(b >= 0);
Mint x = a, res = 1;
for (T p = b; p; x *= x, p >>= 1)
if (p & 1) res *= x;
return res;
}
template <typename T>
concept arithmetic = is_arithmetic_v<T>;
template <typename T>
struct mat : public vector<vector<T>> {
int row, col;
template <typename U>
void isotype(const mat<U>& o) { assert(row == o.row and col == o.col); }
template <typename 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 <typename U>
mat(const vector<vector<U>>& o) : row(o.size()), col(o.front().size()), vector<vector<U>>(o) { assert(!o.empty() and !o.front().empty()); }
template <typename U>
mat(const mat<U>& o) : row(o.row), col(o, col), vector<vector<T>>(o) {}
template <arithmetic U>
mat<T>& operator+=(const U& o) {
for (auto& x : *this)
for (T& y : x) y += o;
return *this;
}
template <typename U>
mat<T>& operator+=(const mat<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 <arithmetic U>
mat<T>& operator*=(const U& o) {
for (auto& x : *this)
for (auto& y : x) y *= o;
return *this;
}
template <typename U>
friend mat<T> operator*(const mat<T>& a, const mat<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 <arithmetic U>
friend mat<T> operator+(const mat<T>& a, const U& b) { return mat(a) += b; }
template <typename U>
friend mat<T> operator+(const mat<T>& a, const mat<U>& b) { return mat(a) += b; }
template <arithmetic U>
friend mat<T> operator*(const mat<T>& a, const U& b) { return mat(a) *= b; }
template <typename U>
mat<T>& operator*=(const mat<U>& o) { return *this = *this * o; }
};
template <typename T>
istream& operator>>(istream& i, mat<T>& v) {
for (auto& x : v)
for (auto& y : x)
i >> y;
return i;
}
template <typename 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 <typename 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 <typename T>
struct phalanx : public mat<T> {
phalanx(const int& n = 1, const T& v = 0) : mat<T>(n, n, v) {}
template <typename U>
phalanx(const vector<vector<U>>& o) : mat<T>(o) { assert(o.size() == o.front().size()); }
template <typename U>
phalanx(const phalanx<U>& o) : mat<T>(o) {}
template <integral U>
friend phalanx<T> qpow(const phalanx<T>& A, const U& B) {
phalanx<T> ans(get_diagonal_matrix(A.row, static_cast<Mint>(1))), a(A);
for (U b = B; b; b >>= 1, a *= a)
if (b & 1) ans *= a;
return ans;
}
};
signed main() {
int n;
long long k;
cin >> n >> k;
phalanx<Mint> a(n);
cin >> a;
cout << qpow(a, k);
return 0;
}