【矩阵乘法入门】给数学不好的人的矩阵乘法模板教程

来源:互联网 发布:tensorflow for java 编辑:程序博客网 时间:2024/05/02 00:58

今天稍微学习了一下矩阵乘法和应用,我线代也不是很好。。。

矩阵的定义和求解方法在线性代数中已经有所定义,我们在这里采用不太严谨的定义,矩阵就是一个有行有列的数表,体现在计算机中就是二维数组。

class Mat{public:    int mat[15][15];};

这个数表和那个数表可以相加,可以相乘,数表自身也可以求幂。

单位阵定义:主对角线为1,其余都是0的特殊矩阵,线代中用E表示。

void initE(){for(int i=0;i<15;i++)E.mat[i][i]=1;}

1、加法:很简单,这个矩阵的对应行列加那个矩阵的对应行列。

Mat operator+(Mat a,Mat b){    Mat c;    int i,j;    for (i=0;i<n;i++)    {        for (j=0;j<n;j++)            c.mat[i][j] = a.mat[i][j]+b.mat[i][j];    }    return c;}
2、乘法:也不难,第一个矩阵的行乘以第二个矩阵的列对应的值,然后求和作为新的矩阵的总值(只有矩阵A的行等于矩阵B的列时,才能相乘,否则无法相乘,这也是为什么相乘没有交换律的原因,交换了行不一定等于列了)。

举个例子,一看就明白是怎么个行乘列相加了。。

重要性质:矩阵乘法没有交换律,但是有结合律。



在计算机中求解主要是采用朴素的O(n^3)方法,因为再怎么优化最好的目前算法只能到O(n^2.3)。。。就不费这个劲了。

Mat operator*(Mat a,Mat b){    int i,j,k;    Mat c;    for (i=0;i<n;i++)    {        for (j=0;j<n;j++)        {       c.mat[i][j] = 0;       for (k=0;k<n;k++)       {                c.mat[i][j]+=(a.mat[i][k]*b.mat[k][j]);       }       //c.mat[i][j]%=MOD;        }    }    return c;}

3、求幂:这个要好好讲讲。

定义的话很简单,A的平方就相当于矩阵乘法中的A*A,立方就是A*A*A。。如果直接用定义在计算机中求解的话,效率为O((n^3)*k),实在太慢,那应该怎么办呢。

可以根据结合律进行二分加速。比如求A^6=A*A*A*A*A*A,需要5次。

也可以 => (A*A)*(A*A)*(A*A)
这样变的好处是,你只需要计算一次A*A,然后将结果(A*A)连乘自己两次就能得到A^6,即(A*A)^3=A^6。算一下发现这次一共乘了3次,少于原来的5次,效率变成(lgk*N^3)。

奇数的话手动乘一次之后变成偶数了再二分。有些代码采用了位运算,优化少许时间而已(x&1就是x%2==1,x>>=1,就是x/=2)。在这里给出正常点的代码。

Mat operator^(Mat a,int x)  {       Mat p = E,q = a;       while (x>=1)       {           if(x%2==1)               p = p*q;           x/=2;           q = q*q;       }       return p;  }

4、有些情况下让你求A^1+A^2+...+A^k,依然可以二分加速,二次二分效率更省。

Mat solve(Mat a,int p)  {       if(p==1)           return a;     else if(p&1)           return (a^p)+solve(a,p-1);       else           return ((a^(p>>1))+E)*solve(a,p>>1);  }  
计算log(n)个A^k即可。