首页 > 其他分享 >矩阵及其快速幂

矩阵及其快速幂

时间:2022-09-05 23:22:06浏览次数:94  
标签:const mat int 及其 矩阵 template operator return 快速

矩阵及其快速幂

模板

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;
}

标签:const,mat,int,及其,矩阵,template,operator,return,快速
From: https://www.cnblogs.com/Cattle-Horse/p/16660038.html

相关文章