矩阵乘法

矩阵乘法

矩阵大小相同才可进行运算法则

矩阵 \(A(n\times m)\)\(B(m \times k)\) 相乘,要求第一个矩阵的列数必须要等于第二个矩阵的行数,得到矩阵\(C(n\times k)\)

法则

  1. 具备结合律 即 \((A\times B)\times C= A\times(B\times C)\)
  2. 不具备交换律 即 \(A\times B \ != B \times A\)(因为横和高不同,形成的矩阵也就不同)
  3. 左分配律 即 \(A\times(B+C)=A\times B+A\times C\)
  4. 右分配律 即 \((A+B) \times C=A\times C + B\times C\)

矩阵的零次幂

任何矩阵的 \(0\) 次幂又称单位矩阵 \(E\), 其定义是他的左上角到右下角的对角线(又称主对角线)为 \(1\), 其余全部为零 \(0\)

法则是:任何矩阵和单位矩阵 \(E\) 相乘都得本身,如图所示

\[\begin{bmatrix}1&\cdots&0\\\vdots&1&\vdots\\0&\cdots&1\end{bmatrix} \]

模拟过程

\[\begin{bmatrix}1&2\\3&4\end{bmatrix}\times\begin{bmatrix}1&2&3\\4&5&6\end{bmatrix}\ \]

若得到矩阵中\((2,3)\) 的数字则:

\[H\ ofA\ 2_{nd}\ --3,4\\ \times,\times\\ L\ ofB\ 3_{rd}\ --3,3\\ 9+12=21 \]

\((2,3)\) 数字为 \(21\)

斐波那契额矩阵快速幂

首先斐波那契数列的通式是:

\[f[i] = f[i-1]+f[i-2] \]

我们要求出 \(f[n]\) 就需要枚举,时间复杂度为 \(O(n)\)

若用矩阵乘法和快速幂,就可达到 \(O(logn)\)

原理:\(f[i]\) 受到前两项的影响,那么可以设置一个 \(1\times2\) 的矩阵,原因是若所求受到的影响为 \(n\) 个变量,则可以设置一个 \(1\times n\)的矩阵转移,即:

\[\begin{vmatrix}f[i]&f[i-1]\end{vmatrix} \]

其次,利用矩阵乘法就要保证 \(f[i]\) 运算后是往后移一位的,与之相乘的一定是一个\(2\times 2\) 的矩阵,怎么找呢?

我们不妨这么设

\[\begin{vmatrix}a&b\\c&d\end{vmatrix} \]

因为两者相乘后我们得到的答案为

\[\begin{vmatrix}f[i+1]&f[i]\end{vmatrix} \]

所以可以列出方程式

\[\begin{cases}af[i]+cf[i-1]=f[i+1]\\bf[i]+df[i-1]=f[i]\end{cases} \]

我们可以有合并同类项可得二式的解为 \(b=1,d=0\)

而一式可以将右侧的 \(f[i+1]\) 拆分成 \(f[i]+f[i-1]\) 再进行合并同类项

得:\(a=1,c=1\)

综上所述,我们的相乘矩阵为:

\[\begin{vmatrix}1&1\\1&0\end{vmatrix} \]

那么式子就可以推导为

\[\begin{vmatrix}f[i]&f[i-1]\end{vmatrix}\times \begin{matrix}\underbrace{\begin{vmatrix}1&1\\1&0\end{vmatrix}\times\begin{vmatrix}1&1\\1&0\end{vmatrix}.....\times\begin{vmatrix}1&1\\1&0\end{vmatrix}}\\n\end{matrix}=\begin{vmatrix}f[n+1]&f[n]\end{vmatrix} \]

化简得

\[\begin{vmatrix}f[i]&f[i-1]\end{vmatrix}\times \begin{vmatrix}1&1\\1&0\end{vmatrix}^{n}=\begin{vmatrix}f[n+1]&f[n]\end{vmatrix} \]

因此我们可以用矩阵快速幂,在 \(O(logn)\) 级别求出

太妙了~

struct matrix
{
	int n,m;
	int z[10][10];
	matrix(){
		n=m=0;
		memset(z,0,sizeof(z));
	}
};
matrix operator*(const matrix &m1, const matrix &m2)
{
	matrix m3;
	m3.n = m1.n;
	m3.m = m2.m;//矩阵原理
	for (int i=1;i<=m3.n;i++)
		//乘法分配律,乘法交换律,思考?????????????????????????
			for (int k=1;k<=m1.m;k++)
                	for (int j=1;j<=m3.m;j++)
				m3.z[i][j] += m1.z[i][k] * m2.z[k][j];
	return m3;//矩阵乘法
}
matrix ksm(matrix m, int n)
{
	if (n==0){//当n==0时存在一个特殊的矩阵上述会给出
		matrix z;
		z.n=z.m=m.n;
		for (int i=1;i<=z.n;i++)
			z.z[i][i]=1;//特殊的快速幂即只有对角线为1,其余全是0
		return z;
	}
	matrix z=ksm(m,n/2);
	z=z*z;
	if (n%2==1) z=z*m;//利用承载运算符,所以乘的时候直接就是矩阵乘法
	return z;
}


int main()
{
	scanf("%d",&n);
	matrix m1;
	m1.n =1;m1.m=2;
	m1.z[1][1]=1;m1.z[1][2]=0;
	
	matrix m2;
	m2.n=m2.m=2;
	m2.z[1][1]=1; m2.z[1][2]=1;
	m2.z[2][1]=1; m2.z[2][2]=0;
	m1 = m1 * ksm(m2, n);
	printf("%d\n"m1.z[1][2]);
}
posted @ 2021-02-16 19:41  zxsoul  阅读(442)  评论(1编辑  收藏  举报