矩阵 | 数论工具1
今天来聊聊矩阵
A
=
(
x
11
x
12
…
x
1
n
x
21
x
22
…
x
2
n
⋮
⋮
⋱
⋮
x
n
1
x
n
2
…
x
n
n
)
\mathbf{A} = \left( \begin{array}{} x_{11} & x_{12} & \ldots & x_{1n}\\ x_{21} & x_{22} & \ldots & x_{2n}\\ \vdots & \vdots & \ddots & \vdots\\ x_{n1} & x_{n2} & \ldots & x_{nn}\\ \end{array} \right)
A=
x11x21⋮xn1x12x22⋮xn2……⋱…x1nx2n⋮xnn
其中,我们把
X
i
j
X_{ij}
Xij 称作矩阵
A
A
A 的第
i
i
i 行,第
j
j
j 列的元素‘
在C++中,我们可以把矩阵理解成2维数组,通常使用struct和operator进行定义和维护。
先来看看看基本矩阵
0矩阵
0
=
(
0
0
…
0
0
0
…
0
⋮
⋮
⋱
⋮
0
0
…
0
)
\mathbf{0} = \left( \begin{array}{} 0 & 0 & \ldots & 0\\ 0 & 0 & \ldots & 0\\ \vdots & \vdots & \ddots & \vdots\\ 0 & 0 & \ldots & 0\\ \end{array} \right)
0=
00⋮000⋮0……⋱…00⋮0
即所有元素均为0的元素
通常用于初始化。
单位矩阵( I I I)
0
=
(
1
0
…
0
0
1
…
0
⋮
⋮
⋱
⋮
0
0
…
1
)
\mathbf{0} = \left( \begin{array}{} 1 & 0 & \ldots & 0\\ 0 & 1 & \ldots & 0\\ \vdots & \vdots & \ddots & \vdots\\ 0 & 0 & \ldots &1\\ \end{array} \right)
0=
10⋮001⋮0……⋱…00⋮1
单位矩阵简称
I
I
I ,特性:
I
×
A
=
A
(
∀
A
都成立)
I \times A =A(\forall A都成立)
I×A=A(∀A都成立)
可以把
I
I
I 理解为单位
1
\mathbf1
1
接下来谈谈别的
提前定义(一定要看)
为了方便我们举例子
定义如下:
U
=
(
1
0
1
1
0
0
0
1
0
)
\mathbf{U} = \left( \begin{array}{} 1 & 0 & 1\\ 1 & 0 & 0\\ 0 & 1 & 0\\ \end{array} \right)
U=
110001100
V
=
(
1
1
1
1
0
1
1
0
0
)
\mathbf{V} = \left( \begin{array}{} 1 & 1 & 1\\ 1 & 0 & 1\\ 1 & 0 & 0\\ \end{array} \right)
V=
111100110
W
\mathbf{W}
W 为运算结果
矩阵加法(减法类似)
定义 U + V = W ( ∀ i , j ; W i j = U i j + V i j ) \mathbf{U}+\mathbf{V} = \mathbf{W} ( \forall i,j;\mathbf{W}_{ij}=\mathbf{U}_{ij}+\mathbf{V}_{ij}) U+V=W(∀i,j;Wij=Uij+Vij)
即
W
=
(
2
1
2
2
0
1
1
1
0
)
\mathbf{W} = \left( \begin{array}{} 2 & 1 & 2\\ 2 & 0 & 1\\ 1 & 1 & 0\\ \end{array} \right)
W=
221101210
没问题吧?就是把各个对应元素相加。
这个比较好理解
要求: U , V 行数列数均一致 \mathbf{U},\mathbf{V}行数列数均一致 U,V行数列数均一致
矩阵的数量积(数量商也一样)
这个学过向量的人应该很清楚
定义 U × k = W ( ∀ i , j ; W i j = U i j × k ) \mathbf{U} \times k=\mathbf{W}(\forall i,j;\mathbf{W}_{ij}=\mathbf{U}_{ij} \times k) U×k=W(∀i,j;Wij=Uij×k)
即当
k
=
2
k=2
k=2 时
W
=
(
2
0
2
2
0
0
0
2
0
)
\mathbf{W} = \left( \begin{array}{} 2 & 0 & 2\\ 2 & 0 & 0\\ 0 & 2 & 0\\ \end{array} \right)
W=
220002200
也就是矩阵内每个元素扩大
k
k
k
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
-----------------------------
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
特性:具有双乘性(本人认为)
(数论)双乘性:
m
×
n
=
m
n
,
m
n
=
m
×
n
m \times n=mn,mn=m \times n
m×n=mn,mn=m×n
例子:二次互反律
J
a
c
o
b
i
雅可比符号
Jacobi雅可比符号
Jacobi雅可比符号 有兴趣的可以了解一下数论
要求:没有
矩阵乘法
注意,要求
U
的行数
=
V
的列数
\mathbf{U}的行数=\mathbf{V}的列数
U的行数=V的列数
终于到了重要部分,设
U
的行数
=
V
的列数
\mathbf{U}的行数=\mathbf{V}的列数
U的行数=V的列数 为
r
r
r
定义 U × V = W ( ∀ i , j ; W i j = ∑ k ∈ [ 1 , r ] U i k × V k j ) \mathbf{U} \times \mathbf{V}=\mathbf{W}(\forall i,j;\mathbf{W}_{ij}=\sum_{k \in [1,r]}\mathbf{U}_{ik} \times \mathbf{V}_{kj}) U×V=W(∀i,j;Wij=∑k∈[1,r]Uik×Vkj)
举个例子:
U
×
V
=
(
2
1
1
1
1
1
1
0
1
)
\mathbf{U} \times \mathbf{V} =\left( \begin{array}{} 2 & 1 & 1\\ 1 & 1 & 1\\ 1 & 0 & 1\\ \end{array} \right)
U×V=
211110111
可以掏出笔来算一下,
或者找个程序跑一下。
例题:P3390 【模板】矩阵快速幂
AC代码:
#include<bits/stdc++.h>
#define int long long
#define mod 1000000007
using namespace std;
int n,k;
struct jz{
int a[105][105];
jz operator * (jz x){//重载运算符*,看不懂可以写函数jz chonghao(jz a,jz b)
jz ans;
memset(ans.a,0,sizeof ans.a);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int c=1;c<=n;c++){
ans.a[i][j]+=(a[i][c]*x.a[c][j]);
ans.a[i][j]%=mod;
}
}
}
return ans;
}
}f;
jz ksm(jz x,int k){//快速幂模板
jz ans;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
ans.a[i][j]=0;
if(i==j) ans.a[i][j]=1;
}
}
while(k) {
if(k&1) ans=(ans*x);
x=x*x;//注意不能简写为x*=x,因为没有重载*=运算符
k=k>>1;
}
return ans;
}
void print(jz x){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<x.a[i][j]<<" ";
}
cout<<endl;
}
}
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>f.a[i][j];
}
}
print(ksm(f,k));
return 0;
}
如有疑问,欢迎评论区
点个赞再走吧,看在我送洛谷代码的份上