矩阵快速幂

在遇到一些递推式时,如果我们直接按公式一步步进行运算,效率较低。构造矩阵进行快速运算,可以高效地解决这个问题。

以int型方阵为例:

矩阵结构:

struct Mat{
    int mat[n][n];
};

矩阵乘法:

Mat mul(Mat A,Mat B)
{
    Mat ret;
    memset(ret.mat,0,sizeof(ret));
    for(int i = 0; i<n; ++i)
        for(int j = 0; j<n; ++j)
            for(int k = 0; k<n; ++k)
                ret.mat[i][j] += A.mat[i][k]*B.mat[k][j];
    return ret;
}

快速计算方阵a的k次幂:

Mat matquickpow(Mat A,int k)
{
    Mat ret;
    for(int i = 0; i<n; ++i)
        for(int j = 0; j<n; ++j)
            ret.mat[i][j] = (i == j);   //初始化为单位矩阵
    while(k){
        if(k&1)
            ret = mul(ret,A);
        A = mul(A,A);
        k >>= 1;
    }
    return ret;
}

快速计算方阵a的k次幂对mod取模的一步运算:

Mat mulmod(Mat A,Mat B,int mod)
{
    Mat ret;
    memset(ret.mat,0,sizeof(ret));
    for(int i = 0; i<n; ++i)
        for(int j = 0; j<n; ++j)
            for(int k = 0; k<n; ++k)
                ret.mat[i][j] = (ret.mat[i][j]+A.mat[i][k]*B.mat[k][j])%mod;
                //对于某些题目,当结果为负数不合题意时,可以对最终结果进行处理
                //或者将此处改为ret.mat[i][j] = ((ret.mat[i][j]+a[i][k]*b[k][j])%mod+mod)%mod;
    return ret;
}

快速计算方阵a的k次幂对mod取模:

Mat matquickpowmod(Mat A,int k,int m)
{
    Mat ret;
    for(int i = 0; i<n; ++i)
        for(int j = 0; j<n; ++j)
            ret.mat[i][j] = (i == j);   //初始化为单位矩阵
    while(k){
        if(k&1)
            ret = mulmod(ret,A);
        A = mulmod(A,A);
        k >>= 1;
    }
    return ret;
}

例如,对于斐波那契数列的递推部分,我们可以运用矩阵快速幂进行计算:

将Fn+2 = Fn+Fn+1转换为

就可以运用矩阵快速幂进行计算了。

原文地址:https://www.cnblogs.com/inmoonlight/p/5259912.html