矩阵快速幂

  之前只做了快速幂取模,这次是矩阵。

  就因为线代没怎么学,今天还花了一些时间去想为什么矩阵A^k+A^l=A^(k+l),是因为A^n=A^(n-1)*A=A^(n-2)*A*A=.....由于矩阵相乘满足结合律(可以以三个为例证明一下),所以可以任意取位置先后结合,所以有A^k+A^l=A^(k+l)。

  两个矩阵相乘,复杂度是O(N^3),再乘M次,所以一个矩阵的M次方时间复杂度是O(N^3*M),如果用快速幂的思想,时间复杂度就可以变成O(N^3*logM).

//矩阵为N*N
struct Mat{                             //定义矩阵
    long long mat[N][N];
    Mat(){
        memset(mat,0,sizeof(mat));
    }
};
Mat operator * (Mat a,Mat b){           //一次矩阵乘法
    int i,j,k;
    Mat ret;
    for(k=0;k<N;k++){
        for(i=0;i<N;i++){
            if(a.mat[i][k]==0) continue;//剪枝,很重要
            for(j=0;j<N;j++){
                if(b.mat[k][j]==0) continue;
                ret.mat[i][j]+=a.mat[i][k]*b.mat[k][j];//结果要取余时mod M
            }
        }
    }
    return ret;
}
Mat operator ^ (Mat a,int n){       //实现矩阵快速幂
    Mat ret,t=a;
    int i,j;
    for(i=0;i<N;i++)
        for(j=0;j<N;j++) ret.mat[i][j]=(i==j);
    while(n){
        if(n&1) ret=ret*t;
        t=t*t;
        n>>=1;
    }
    return ret;
}

实现矩阵快速幂的部分和快速幂很像,快速幂中ret初始化为1,t初始化为a^(2^0) mod M,这里ret初始化为单位矩阵(单位矩阵E乘A还为A),t就为要算N次幂的矩阵。

这个算法有一个用O(logn * 2^3)的复杂度算斐波那契数列,比普通的O(n)要快

  f[0]=1

  f[1]=1

  f[2]=2

  f[3]=3...

  f[n]=f[n-1]+f[n-2]

  网上找了个图

矩阵快速幂_第1张图片


于是我们可以把a矩阵初始化,a.mat[0][0]=a.mat[0][1]=a.mat[1][0]=1,a.mat[1][1]=0,这样求出a^N,a.mat[0][0]的值就是f[N]。

你可能感兴趣的:(矩阵快速幂)