矩阵快速幂

处理何种问题:用于优化加速一些线性关系式,可将一些时间复杂度降至O(logn)。

(如果题目上出现 1e18 之类的数据范围,就可以往矩阵快速幂上想了)

 

性能:具体的时间复杂度为O(edge * edge * log n),edge为矩阵的阶数。

 

原理:矩阵乘法性质、快速幂。

 

实现步骤:以斐波那契数列为例

公式为: F[i] = F[i-1] + F[i-2],根据公式将此转化为矩阵公式

 

 

备注:需要进行 *、= 符号的重载,套用快速幂模板,但取模在 * 重载函数中。

 

输入样例解释

99999999999999  //f(n)

 

输出样例解释

626  //结果

--------------------------------------------------------------------

代码

///此代码为求斐波那契数列矩阵快速幂,若要求其他矩阵快速幂注意更改标记   <--- 的行。
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;

const long long mod=10000;/// <---
const int edge=2;/// <---

struct Matrix ///定义矩阵,重载*,=;
{
    long long a[edge][edge];
    Matrix()
    {
        memset(a,0,sizeof(a));///构造函数,初始化矩阵
    }
    Matrix operator *(const Matrix b) ///自定义矩阵乘法
    {
        Matrix temp;
        for(int i=0; i<edge; ++i)
            for(int j=0; j<edge; ++j)
                for(int k=0; k<edge; ++k)
                {
                    temp.a[i][j]+=a[i][k]*b.a[k][j];
                    temp.a[i][j]%=mod;///在此取模
                }
        return temp;
    }
};

Matrix m_fpow(Matrix a,long long n)
{
    Matrix Ans;

    Ans.a[0][0]=Ans.a[1][1]=1;///初始化为单位矩阵    // <---

    while(n!=0)///套用快速幂
    {
        if(n&1)
            Ans=Ans*a;
        n=n>>1;
        a=a*a;
    }
    return Ans;
}

int main()
{
    Matrix Ans,a,b;
    long long n;

    scanf("%lld",&n);
    if(n==0)
        printf("0
");
    else if(n==1)
        printf("1
");
    else
    {
        a.a[0][0]=a.a[0][1]=a.a[1][0]=1;///初始化,不同的dp关系对应不同的矩阵    // <---
        b.a[0][0]=b.a[1][0]=1;                                                    /// <---
        Ans=m_fpow(a,n-2)*b;
        printf("%lld
",Ans.a[0][0]);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/l1l1/p/8719294.html