浅谈矩阵快速幂

一.简介

首先,矩阵快速幂是从快速幂里延伸出的算法,需要快速幂以及线性代数的知识。快速幂是利用二进制的有关性质快速计算出xn,矩阵快速幂则是通过将递推式化成一个矩阵,求解某个递推结果的过程变成求解一个矩阵的n次幂的过程,从而能用快速幂加快递推式的求解。

举个例子,我们来用斐波那契数列来解释一下矩阵快速幂的具体流程。大家都知道递推式为F(n) = F(n-1)+F(n-2)。这个式子十分浅显易懂,但是用来及求解较大的项时就会变得非常慢,因此我们可以考虑用矩阵快速幂来优化一下计算过程。在一般情况下,我们要通过递推式获得一个矩阵之间的递推关系,形如T*A(n-1) = A(n)(其中TA(n-1)A(n)均为矩阵)

对于F(n),我们可以得到一个矩阵之间的递推关系就是

其中,要注意的是,为了方便运算,我们构造的矩阵都是方阵,在这里An其实也是一个2*2的方阵,但我们只关心An的左边,所以就没有写出An的右边。很明显,上面给出的等式是成立的,接下来,如果我们要求F(n),就可以先求出A(n) = Tn-2*A(1),

A(1)是左边为两个1的2*2矩阵,此时F(n)就是A(n)左上角的值。这样,我们就把一个递推式的计算过程优化,然后运用矩阵快速幂进行极快的求解。

矩阵快速幂的难点就在于矩阵的构造。

下面给一些简单的递推式
1.f(n)=a*f(n-1)+b*f(n-2)+c;(a,b,c是常数)

 

2.f(n)=c^n-f(n-1) ;(c是常数)

二.代码实现

const int N = 2;
const int mod = 10000;
struct Matrix
{
    int mat[N][N];
    Matrix(){};
    Matrix operator*(Matrix const &b) const
    {
        Matrix res;
        memset(res.mat,0,sizeof(res.mat));
        for(int i = 0;i<N;++i)
        {
            for(int j = 0;j<N;++j)
            {
                for(int k = 0;k<N;++k)
                {
                    printf("%d %d %d\n",i,j,k);
                    res.mat[i][j] = (res.mat[i][j]+this->mat[i][k]*b.mat[k][j])%mod;
                }
            }
        }
        return res;
    }
    void Print()
    {
        for(int i =0;i<N;++i)
        {
            for(int j = 0;j<N;++j)
                printf("%d ",mat[i][j]);
            printf("\n");
        }
        return ;
    }
};
Matrix pow_mod(Matrix base,int n)
{
    Matrix res;
    memset(res.mat,0,sizeof(res.mat));
    for(int i = 0;i<N;++i)
        res.mat[i][i] = 1;
    while(n>0)
    {
        if(n&1)
        {
            res.Print();
            res= res*base;
        }
        base = base*base;
        n>>=1;
        res.Print();
    }
    return res;

}

三.相关习题

posted @ 2020-01-28 23:25  浅花迷人  阅读(...)  评论(...编辑  收藏