矩阵快速幂
\(emmm\),考试上面见到的,以前听颜神讲过一遍但是没有听懂,现在看一下还是比较妙妙的
矩阵乘法
矩阵乘法是什么?
简而言之就是
\[c_{ij} = \quad\sum_{k=1}^na_{ik} *b_{kj}
\]
举个简单的例子
\[\left\{
\begin{matrix}
14 \\
32 \\
50
\end{matrix}
\right\} =
\left\{
\begin{matrix}
1 & 2 & 3\\
4 & 5 & 6\\
7 & 8 & 9
\end{matrix}
\right\} * \left\{
\begin{matrix}
1\\
2 \\
3
\end{matrix}
\right\}
\]
真简单哇!(光速溜
\(emmm\),这就是矩阵乘法的定义
下面给出详细代码
int n;//矩阵大小 void Up(int &x, int y) { x = (x + y) % mod; }//简单定义 += struct Matrix { int a[n][n];//矩阵 friend Matrix operator *(const Matrix x, const Matrix y)//定义矩阵类型的乘法 { Matrix c;//定义新的矩阵用来存储结果 memset(c.a, 0, sizeof(c.a));//初始化 for(int i = 0; i < n;i ++)//进行枚举 for(int j = 0; j < n;j ++) for(int k = 0; k < n;k ++) Up(c.a[i][j], x.a[i][k] * y.a[k][j] % mod);//相乘 return c;//返回答案矩阵 } };
快速幂
快速幂还算比较简单了的吧
反正我一开始只是知道快速幂而已
简单来说,通过二进制位来实现
\(2^0= 2^0\)
\(2^1 = 2^1\)
\(2^2=2^2\)
\(2^3 = 2^2*2\)
\(2^4 =2^4\)
\(2^5 = 2^4*2\)
\(2^6 = 2 ^ 4 * 2 ^ 2\)
\(2^7 = 2^4*2^2*2\)
所以我们可以看出来的是
二进制位上我们现在只有当某一位是1的时候才乘
举个例子
\[2^{15} =2^{1111} = 2^{1000}*2^{100}*2^{10}*2^{1}=2^8*2^4*2^2*2^1
\]
所以相对来说比较好理解
原来\(O(b)\)复杂度一下降低到了\(O(logb)\)
所以快速幂是一种优化的手段
下面贴上代码
inline int pow(int a,int b) { int r=1,base=a; while(b) { if(b&1) r*=base;//如果当前位是1,那么直接相乘 base*=base;//不管是什么数字下一位都需要再乘一次(2的倍数) b>>=1;//移到下一位 } return r;//返回结果 }
矩阵乘法快速幂
void Up(int &x, int y) { x = (x + y) % mod; }//简单定义+= struct Matrix { int a[n][n]; friend Matrix operator *(const Matrix x, const Matrix y)//定义矩阵乘法 { Matrix c; memset(c.a, 0, sizeof(c.a)); for(int i = 0; i < n; i ++) for(int j = 0; j < n; j ++) for(int k = 0; k < n; k ++) Up(c.a[i][j], x.a[i][k] * y.a[k][j] % mod); return c; } }; Matrix Qpow(Matrix x, int timer)//矩阵快速幂 { Matrix base;//定义结果矩阵 for(int i = 0; i < n; i ++) for(int j = 0; j < n; j ++) base.a[i][j] = 0; for(int i = 0; i < n; i ++) base.a[i][i] = 1; for(; timer; timer >>= 1, x = x * x) if(timer & 1) base = base * x; return base; }
\(mod\)是一个简单的模数,考试的时候一般要求取模运算
\(emmm\)可以说是矩阵快速幂的基础练习题
来源:https://www.cnblogs.com/eqvpkbz/p/9512534.html