矩阵乘法写法研究
矩阵乘法写法研究
固定大小,array 的别名
template <size_t N, size_t M>
using matrix = array<array<int, M>, N>;
int main() {
matrix<2, 3> a = {{ {1, 2, 3}, {4, 5, 6} }};
matrix<2, 3> c = {-1, -2, -3, -4, -5, -6};
return 0;
}
- 所有
size_t都是必要的,不能改成int。对应的重载运算符等也都要写为size_t。 - 不要把有关这个别名的函数封到命名空间里。因为那是别名,不是新类型,ADL 不会查找命名空间里的函数。
- 构造矩阵的时候,要么在外层额外加一层花括号(
a),要么只加一层花括号(c)。 - 构造矩阵的时候,可以只写某一行的前几项,剩下的都会是零,但这样就要用
a那种写法。特别地,= {}就是全零矩阵。
不要继承 array,不然会无法使用聚合初始化,还不如这样写。
固定大小,原生数组
template <int N, int M>
struct matrix {
int arr[N][M];
auto& operator[](int i) { return arr[i]; }
auto& operator[](int i) const { return arr[i]; }
};
int main() {
matrix<2, 3> a = {{ {1, 2, 3}, {4, 5, 6} }};
matrix<2, 3> c = {-1, -2, -3, -4, -5, -6};
return 0;
}
和上一个的区别是,这样写就可以不用写一堆 size_t 而可以全写 int 了。另外矩阵的构造方式还是不变的。
不定大小,继承 vector
struct matrix : vector<vector<mint>> {
matrix(size_t n, size_t m) : vector(n, vector<mint>(m)) {}
matrix(initializer_list<vector<int>> init) : vector(init) {}
};
int main() {
matrix a = {{1, 2, 3}, {4, 5, 6}};
matrix b(2, 3);
return 0;
}
这应该是相对人类的一种写法了,用正统的 initializer_list 写,不过要注意 initializer_list 里面的类型是要写 vector<int>,不要搞错了。
完整代码
固定大小 array 别名:
#include <bits/stdc++.h>
using namespace std;
template <size_t N, size_t M>
using matrix = array<array<int, M>, N>;
template <size_t N, size_t M, size_t R>
matrix<N, R> operator*(const matrix<N, M>& lhs, const matrix<M, R>& rhs) {
matrix<N, R> res = {};
for (size_t i = 0; i < N; i++) {
for (size_t k = 0; k < R; k++) {
for (size_t j = 0; j < M; j++) {
res[i][k] += lhs[i][j] * rhs[j][k];
}
}
}
return res;
}
template <size_t N, class T>
matrix<N, N> qpow(matrix<N, N> a, T b) {
matrix<N, N> res = {};
for (size_t i = 0; i < N; i++) res[i][i] = 1;
while (b) {
if (b & 1) res = res * a;
if (b >>= 1) a = a * a;
}
return res;
}
int main() {
matrix<3, 3> a = {{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
}};
matrix<3, 3> c = {
-1, -2, -3,
-4, -5, -6,
-7, -8, -9
};
auto b = qpow(a, 5) * c;
return 0;
}
固定大小原生数组:
#include <bits/stdc++.h>
using namespace std;
template <int N, int M>
struct matrix {
int arr[N][M];
auto& operator[](int i) { return arr[i]; }
auto& operator[](int i) const { return arr[i]; }
};
template <int N, int M, int R>
matrix<N, R> operator*(const matrix<N, M>& lhs, const matrix<M, R>& rhs) {
matrix<N, R> res = {};
for (int i = 0; i < N; i++) {
for (int k = 0; k < R; k++) {
for (int j = 0; j < M; j++) {
res[i][k] += lhs[i][j] * rhs[j][k];
}
}
}
return res;
}
template <int N, class T>
matrix<N, N> qpow(matrix<N, N> a, T b) {
matrix<N, N> res = {};
for (int i = 0; i < N; i++) res[i][i] = 1;
while (b) {
if (b & 1) res = res * a;
if (b >>= 1) a = a * a;
}
return res;
}
int main() {
matrix<3, 3> a = {{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
}};
matrix<3, 3> c = {
-1, -2, -3,
-4, -5, -6,
-7, -8, -9
};
auto b = qpow(a, 5) * c;
return 0;
}
不定大小,继承 vector
struct matrix : vector<vector<mint>> {
matrix(size_t n, size_t m) : vector(n, vector<mint>(m)) {}
matrix(initializer_list<vector<int>> init) : vector(init) {}
};
matrix operator*(const matrix& lhs, const matrix& rhs) {
matrix res(lhs.size(), rhs[0].size());
for (int i = 0; i < (int)lhs.size(); i++) {
for (int j = 0; j < (int)rhs.size(); j++) {
for (int k = 0; k < (int)rhs[0].size(); k++) {
res[i][k] += lhs[i][j] * rhs[j][k];
}
}
}
return res;
}
matrix qpow(matrix a, LL b) {
int n = (int)a.size();
matrix r(n, n);
for (int i = 0; i < n; i++) r[i][i] = 1;
while (b) {
if (b & 1) r = r * a;
if (b >>= 1) a = a * a;
}
return r;
}
本文来自博客园,作者:caijianhong,转载请注明原文链接:https://www.cnblogs.com/caijianhong/p/19143751
浙公网安备 33010602011771号