1 矩阵
矩阵是一个二维数组, 行数通常用
r
o
w
row
row或
r
r
r表示, 列数用
c
o
l
u
m
n
column
column或
c
c
c表示, 矩阵由中括号或小括号括起来, 就像这样
(
1
2
3
4
5
6
7
8
9
)
\left( \begin{matrix} 1 & 2 & 3\\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{matrix} \right)
147258369
[
1
2
3
4
5
6
7
8
9
]
\left[\begin{matrix}1 & 2 & 3 \\4 & 5 & 6 \\7 & 8 & 9\end{matrix}\right]
147258369
称左上到右下的一条对角线为主对角线
1.1 简单矩阵运算
矩阵加减: 两个行列数相等的矩阵进行运算, 对应位置的数值相加减
矩阵数乘: 一个矩阵与一个数字相乘, 矩阵中每个位置上的数都乘这个数字
1.2 矩阵乘法
一个长
a
a
a宽
b
b
b的矩阵
X
X
X乘一个长
b
b
b宽
c
c
c的矩阵
Y
Y
Y, 得到长
a
a
a宽
c
c
c的矩阵
Z
Z
Z
Z
i
j
=
X
{Z_i}_j = X
Zij=X第
i
i
i行的数与
Y
Y
Y第
j
j
j行的数依次相乘, 也就是
Z
i
j
=
∑
k
=
1
b
X
i
k
+
Y
k
j
{Z_i}_j = \displaystyle \sum_{k=1}^b{{X_i}_k + {Y_k}_j}
Zij=k=1∑bXik+Ykj
矩阵乘法不满足交换律
A
×
B
≠
B
×
A
A \times B \ne B \times A
A×B=B×A, 满足结合律
(
A
×
B
)
×
C
=
A
×
(
B
×
C
)
(A \times B) \times C = A \times (B \times C)
(A×B)×C=A×(B×C)
2 单位元
在一个运算系统中m 如果某个元素
x
x
x和一个元素
y
y
y做运算, 结果为
y
y
y, 称
x
x
x为这个运算系统的单位元
x
x
x运算
y
=
y
y = y
y=y时称
x
x
x为左单位元,
y
y
y运算
x
=
y
x = y
x=y时称
x
x
x为右单位元
特殊地, 当满足交换律时:
x
x
x运算
y
=
y
y = y
y=y运算
x
=
y
x = y
x=y, 称
x
x
x为双边单位元
3 矩阵快速幂
先看一个普通快速幂代码
int qpow(int x, int y){
int res = 1;
while(y){
if(y & 1) res = res * x;
y >>= 1;
x = x * x;
}
return res;
}
在这个代码中
r
e
s
res
res赋的初值
1
1
1, 就是乘法运算中的单位元
那我们就不难想象所有运算中的快速幂都可以用这个代码, 只需要把
r
e
s
res
res的初值赋为该运算系统的单位元
3.1 单位元矩阵
设四个数 a , b , c , d a, b, c, d a,b,c,d
[ 1 2 3 4 ] × [ a b c d ] = [ 1 2 3 4 ] \left[\begin{matrix}1 & 2 \\ 3 & 4\end{matrix}\right] \times \left[\begin{matrix}a & b \\ c & d\end{matrix}\right] \,= \left[\begin{matrix}1 & 2 \\ 3 & 4\end{matrix}\right] [1324]×[acbd]=[1324]
得到
{
a
+
2
c
=
1
b
+
2
d
=
2
3
a
+
4
c
=
3
3
b
+
4
d
=
4
\begin{cases} a+2c = 1 \\ b+2d = 2 \\ 3a+4c = 3 \\ 3b + 4d = 4 \end{cases}
⎩
⎨
⎧a+2c=1b+2d=23a+4c=33b+4d=4
解得
{
a
=
1
b
=
0
c
=
0
d
=
1
[
1
0
0
1
]
\begin{cases} a = 1 \\ b = 0 \\ c = 0 \\ d = 1 \end{cases} \qquad\left[ \begin{matrix} 1 & 0 \\ 0 & 1 \\ \end{matrix} \right]
⎩
⎨
⎧a=1b=0c=0d=1[1001]
三维矩阵解得
[
1
0
0
0
1
0
0
0
1
]
\left[ \begin{matrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{matrix} \right]
100010001
发现单位元矩阵主对角线的数字为 1 1 1, 其他位置为 0 0 0, 我们一般称 单位元矩阵 为单位矩阵
3.2 例题
求斐波那契数列的第
n
n
n项
(
1
≤
n
≤
2
63
−
1
)
(1 \le n \le 2^{63}-1)
(1≤n≤263−1), 可以构造一个矩阵
A
A
A, 使矩阵
[
a
n
−
1
a
n
−
2
0
0
]
×
A
=
[
a
n
a
n
−
1
0
0
]
\left[\begin{matrix}a_{n-1} & a_{n-2} \\0 & 0\end{matrix}\right] \times A = \left[\begin{matrix}a_n & a_{n-1} \\0 & 0\end{matrix}\right]
[an−10an−20]×A=[an0an−10]
这样通过
[
a
2
a
1
0
0
]
×
A
n
−
2
\left[\begin{matrix}a_2 & a_1 \\0 & 0\end{matrix}\right] \times A^{n-2}
[a20a10]×An−2得到
[
a
n
a
n
−
1
0
0
]
\left[\begin{matrix}a_n & a_{n-1} \\0 & 0\end{matrix}\right]
[an0an−10]
计算得到
A
=
[
1
1
1
0
]
A = \left[\begin{matrix}1 & 1 \\1 & 0\end{matrix}\right]
A=[1110]
4 矩阵模板
struct Matrix{
int a[N][N];
int r, c;
// 构造函数 函数名与结构体名相同 无返回值
Matrix(int _r = 0, int _c = 0){
r = _r, c = _c;
memset(a, 0, sizeof(a));
if(c == 0)
c = r; // 如果只传递r的值, 矩阵变成方阵
}
// 单位矩阵
void unit(){
memset(a, 0, sizeof(a));
for(int i = 1;i <= r;i++)
a[i][i] = 1;
}
Matrix operator+(const Matrix &t) const{
Matrix ans(r, c);
for(int i = 1;i <= r;i++)
for(int j = 1;j <= c;j++)
ans.a[i][j] = a[i][j] + t.a[i][j];
return ans;
}
Matrix operator-(const Matrix &t) const{
Matrix ans = *this; //*this表示直接复制当前结构内容
for(int i = 1;i <= r;i++)
for(int j = 1;j <= c;j++)
ans.a[i][j] -= t.a[i][j];
return ans;
}
Matrix operator*(const int &t) const{
Matrix ans = *this;
for(int i = 1;i <= r;i++)
for(int j = 1;j <= c;j++)
ans.a[i][j] *= t;
return ans;
}
Matrix operator*(const Matrix &t) const{
Matrix ans(r, t.c); //r行c列乘以t.r行t.c列
int n = r, m = t.c;
for(int i = 1;i <= n;i++)
for(int j = 1;j <= m;j++)
for(int k = 1;k <= c;k++)
ans.a[i][j] += a[i][k] * t.a[k][j];
return ans;
}
Matrix operator%(const int t) const{
Matrix ans = *this;
for(int i = 1;i <= r;i++)
for(int j = 1;j <= c;j++)
ans.a[i][j] %= t;
return ans;
}
void print(){
for(int i = 1;i <= r;i++){
for(int j = 1;j <= c;j++)
printf("%d ", a[i][j]);
printf("\n");
}
}
Matrix pow(ll b){
// 计算b次方
Matrix ans(r, c), a = *this;
ans.unit();
while(b){
if(b & 1) ans = ans * a;
a = a *a;
b >>= 1;
}
return ans;
}
Matrix pow(ll b, ll p){
//计算b次方模p
Matrix ans(r, c), a = *this;
ans.unit();
while(b){
if(b & 1) ans = ans * a % p;
a = a * a % p;
b >>= 1;
}
return ans;
}
};