ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

矩阵及其快速幂

2022-09-05 23:33:00  阅读:223  来源: 互联网

标签: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,快速
来源: https://www.cnblogs.com/Cattle-Horse/p/16660038.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有