二:矩阵快速幂

改编自:地址

第一篇介绍了如何快速求幂,这一篇介绍如何用数字快速求幂的思想,来快速求矩阵之幂

这是求矩阵A、B乘积的代码:

const int N=100;
int c[N][N];
void multi(int a[][N],int b[][N],int n)
{
    memset(c,0,sizeof c);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        for(int k=1;k<=n;k++)
        c[i][j]+=a[i][k]*b[k][j];
}

这里我直接写的是n*n的矩阵(即方阵),显然两个相乘是要一行和一列对应乘,那么矩阵乘法是需要A的行数与B的列数相等的(这是A*B的前提条件,可见矩阵的乘法是不满足交换律的)。然而这些一般都是没什么用的,矩阵快速幂只会用到方阵(除非题目是裸的矩阵乘法)。矩阵快速幂都是方阵也就避免的相乘的前提条件,可以放心用。

 

OK,现在可以求两个矩阵之积,那么矩阵的“平方”和“幂”也就可以求,下面就是矩阵如何快速求幂,和第一篇的思想相同

需要用到一个小知识就是:单位矩阵与矩阵A相乘,结果仍是矩阵A

 

const int N=10;
int tmp[N][N];
void multi(int a[][N],int b[][N],int n)
{
    memset(tmp,0,sizeof tmp);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        for(int k=1;k<=n;k++)
        tmp[i][j]+=a[i][k]*b[k][j];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        a[i][j]=tmp[i][j];
}
int res[N][N];
void Pow(int a[][N],int n)
{
    memset(res,0,sizeof res);
    for(int i=1;i<=n;i++) res[i][i]=1;
    while(n)
    {
        if(n&1)
            multi(res,a,n);//res=res*a;复制直接在multi里面实现了;
        multi(a,a,n);//a=a*a
        n>>=1;
    }
}

 

如上,在最后结果存在res里,如果觉得不爽也可以在pow函数的最后加一个复制,把res复制给a

 将n次矩阵相乘减少到logn次,这就是矩阵快速幂的核心妙处

通过将其他问题转化为“求矩阵之幂”,进而运用快速幂的思想求出结果

那么,你会问,怎么会有求“矩阵之幂“这种无聊的问题呀?嘿,还真有

前两篇是基础,第三篇开始实例

据知后事如何,请看下回分解

posted @ 2018-03-25 18:47  柳暗花明_liu  阅读(167)  评论(0编辑  收藏  举报