线性代数
矩阵的定义
一般用圆括号或方括号表示矩阵,矩阵拥有行与列,一般这么表示:\(\begin{bmatrix}a & b &c\\d & e & f\\\end{bmatrix}\),其行数为 \(2\),列数为 \(3\) 。
方阵
行列相等的矩阵。
同型矩阵
两个矩阵行列对应相等。
单位矩阵
所有第 \(i\) 行 \(i\) 列的元素为 \(1\)(即主对角线) ,其他均为 \(0\) ,如:
\(\begin{bmatrix}1 & 0 & 0\\0 & 1 & 0\\\end{bmatrix}\) \(\begin{bmatrix}1 & 0 \\0 & 1 \\\end{bmatrix}\) \(\begin{bmatrix}1 & 0 \\0 & 1 \\0&0\end{bmatrix}\)
即:
for(int i=1;i<=min(n,m);i++)a[i][i]=1;
矩阵的运算
矩阵的加减法
如果两个同型矩阵相加,对应位置相加(减)即可,非同型矩阵不得相加(减)。例如:
\(\begin{bmatrix}1 & 1 & 4\\5 & 1 & 4\\\end{bmatrix}+\begin{bmatrix}1 & 9 & 1\\9 & 8 & 10\\\end{bmatrix}=\begin{bmatrix}2 & 10 & 5\\14 & 9 & 14\\\end{bmatrix}\)
矩阵的乘法
一个矩阵 \(A\) 乘 \(k\),将 \(A\) 上所有元素乘 \(k\),记作 \(kA\) 。
当 \(A\) 矩阵的列等于 \(B\) 矩阵的行,那么才能进行相乘。
若 \(A\) 是一个 \(n\cdot k\) 的矩阵, \(B\) 是一个 \(k\cdot m\) 的矩阵,他们的结果将是一个 \(n\cdot m\) 的矩阵 \(C\) , \(C_{i,j}=\sum_{l=1}^kA_{i,l} \cdot B_{l,j}\) 。
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int l=1;l<=k;l++)
c[i][j]+=a[i][l]*b[l][j];
运算律
加法满足交换律与结合律,即:\(C=A+B=B+A , D=A+B+C=A+(B+C)\) 。
乘法只满足结合律,不满足交换律,即:\(D=A\cdot B \cdot C=A\cdot(B\cdot C),C=A\cdot B\neq B\cdot A\) 因为乘法分先后,考虑前后行列数。
矩阵快速幂
跟普通快速幂一样,只不过将类型改为矩阵类型,将初始化的1改为单位矩阵,将乘法换成函数(或重载运算符),注意,能开幂的矩阵一定是一个方阵(即行列相等)。
struct jz{
int a[N][N];
};
jz mul(jz a,jz b){
jz c;
memset(c.a,0,sizeof(c.a));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int l=1;l<=n;l++)
c.a[i][j]+=a.a[i][l]*b.a[l][j];//都是方阵,所以都开n
return c;
}
jz jzpow(jz a,int b){
jz c;
for(int i=1;i<=n;i++)c.a[i][i]=1;//初始化单位矩阵
while(b){
if(b&1)c=mul(c,a);
a=mul(a,a);
b>>=1;
}
return c;
}
矩阵快速幂加速递推
自编题
如题,当 \(n>5\) 时,有一个递推式,按他递推会TLE,我们可以将其转化成一个矩阵。
我们设矩阵 \(A=\begin{bmatrix}f_i&f_{i-1}&f_{i-2}&f_{i-3}&f_{i-4}\\\end{bmatrix}\) , \(B=\begin{bmatrix}f_{i-1}&f_{i-2}&f_{i-3}&f_{i-4}&f_{i-5}\\\end{bmatrix}\) ,我们设 \(A\) 是由 \(B\) 乘上另一个矩阵得到的,我们就可以尝试推出这个矩阵,经过一顿推敲,我们得到这样一个矩阵:
那么有 \(A=B\cdot C\),将 \(A\) 初始化为 \(A=\begin{bmatrix}f_5&f_4&f_3&f_2&f_1\\\end{bmatrix}\) , 将其乘上 \(B\) ,得到 \(\begin{bmatrix}f_6&f_5&f_4&f_3&f_2\\\end{bmatrix}\) , 那么将其乘上\((n-5)\) ,得到 \(\begin{bmatrix}f_n&f_{n-1}&f_{n-2}&f_{n-3}&f_{n-4}\\\end{bmatrix}\) 。
示例程序:
为方便,将初始化变为\(\begin{bmatrix}
1&1&1&1&1\\
0&0&0&0&0\\
0&0&0&0&0\\
0&0&0&0&0\\
0&0&0&0&0\\
\end{bmatrix}
\),不影响结果。
#include <bits/stdc++.h>
using namespace std;
const long long N = 105, mod = 1e9 + 7;
struct jz {
long long m[N][N];
};
int len = 5;
jz mul(jz a, jz b) {
jz c;
memset(c.m, 0, sizeof(c.m));
for (int i = 0; i < len; i++)
for (int j = 0; j < len; j++) {
for (int k = 0; k < len; k++) {
c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j]) % mod;
}
}
return c;
}
jz jpow(jz a, long long n) {
jz ans;
memset(ans.m, 0, sizeof(ans.m));
for (int i = 0; i < len; i++)
ans.m[i][i] = 1;
while (n) {
if (n & 1) {
ans = mul(ans, a);
}
a = mul(a, a);
n /= 2;
}
return ans;
}
int main() {
long long n;
cin >> n;
if (n <= 5) {
cout << 1;
return 0;
}
jz F, A;
for (int i = 0; i < len; i++)
F.m[0][i] = 1;
memset(A.m, 0, sizeof(A.m));
A.m[0][0] = A.m[0][1] = A.m[1][2] = A.m[2][0] = A.m[2][3] = A.m[3][4] = A.m[4][0] = 1;
F = mul(F, jpow(A, n - 5));
cout << F.m[0][0];
return 0;
}

浙公网安备 33010602011771号