快速幂+矩阵乘法log(n)时间解决【斐波那契前项和】问题

看这篇文章一定要有矩阵乘法和快速幂的基础!

首先我们先确认一下斐波那契的推理公式:

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

首先,如果我们想要快速幂,那么我们一定得对每个东西就行n次方的处理,这个东西就是矩阵,为什么是矩阵呢??

我们可以将上面这个推到公式用矩阵来代替:

\begin{bmatrix} f[n] & f[n-1] & \\ 0& 0& \end{bmatrix} =\begin{bmatrix} f[n-1] &f[n-2] \\ 0&0 \end{bmatrix} \begin{bmatrix} 1 & 1\\ 1& 0 \end{bmatrix}

所以有:

\begin{bmatrix} f[n] &f[n-1] \\ 0&0 \end{bmatrix} =\begin{bmatrix} f[2] &f[1] \\ 0&0 \end{bmatrix} \begin{bmatrix} 1 &1 \\ 1& 0 \end{bmatrix}\frac{n-1}{1}

所以我们就可以对常数矩阵就行快速幂,然后将初始矩阵乘上快速幂后的矩阵;

那么我们先来看一道例题:

快速幂+矩阵乘法log(n)时间解决【斐波那契前项和】问题_第1张图片

 显然,用暴力的话会超时:

然后我们就可以构造一个矩阵:

记F[n]为前n项和,f[n]为第n项,无数字部分默认为0

\begin{bmatrix} F[n] &f[n] &f[n-1] \\ & & \\ & & \end{bmatrix}= \begin{bmatrix} F[n-1] & f[n-1] &f[n-2] \\ & & \\ & & \end{bmatrix} \begin{bmatrix} 1 & & \\ 1& 1&1 \\ 1& 1 & \end{bmatrix}

所以我们可以对上面这个公式就行快速幂,最终在logn的时间复杂度下跑出结果

代码如下:

#include
#include
#include
#define ll long long
using namespace std;

const int N=10;

ll bakp[N][N];
ll A[N][N],ans[N][N];
ll n,m;

void mul(ll a[][N],ll b[][N],ll c[][N]){//这个函数的作用是a=b*c,其中abc是矩阵
    
    ll tmp[N][N]; memset(tmp,0,sizeof tmp);
    
    for(int i=1;i<=3;i++){
        for(int j=1;j<=3;j++){
            for(int k=1;k<=3;k++){
                
                tmp[i][j]+=(b[i][k]*c[k][j])%m;
                tmp[i][j]%=m;
            }   
        }
    }
    
    memcpy(a,tmp,sizeof tmp);
}

int main(){
    //对矩阵进行初始化
    ans[1][1]=2,ans[1][2]=ans[1][3]=1;
    A[1][1]=A[2][2]=A[2][1]=A[3][2]=A[2][3]=A[3][1]=1;
    cin>>n>>m; n-=2;
    
    for(int i=1;i<=3;i++) bakp[i][i]=1;//将bakp设置为单位矩阵

    for(int i=n;i;i>>=1){//对矩阵进行快速幂
        
        if(i&1) mul(bakp,bakp,A);

        mul(A,A,A);
        
    }
    
    mul(ans,ans,bakp);
    
    cout<

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