矩阵快速幂

来源:互联网 发布:分布式数据库系统 编辑:程序博客网 时间:2024/06/05 09:31

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

  就因为线代没怎么学,今天还花了一些时间去想为什么矩阵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*Nstruct 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]

  网上找了个图


于是我们可以把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]。

0 0