jun 碰到了挺多数列的题,线性递推,值又很大,直接推会超时,所以去网上找题解的时候,找到了矩阵快速幂以及杜教板子,杜教板子还没看懂,就以后再发

首先,快速幂,之前也学了整数的快速幂,复杂度是O(log^2n)这里就把模版贴一下

int poww(int a,int b){
    int ans=1,base=a;
    while(b!=0){
        if(b&1!=0)
          ans*=base;
        base*=base;
        b>>=1;
  }
    return ans;
}

然后对于矩阵快速幂,只需要在快速幂中将两个整数a ,b改成矩阵形式就行了,然后相乘需要改成矩阵相乘

const int maxn=3;
const int mod=1000000007;
struct matrix{
    long long a[maxn][maxn];
    void init(){
        memset(a,0,sizeof(a));
        for(int i=0;i<maxn;i++) a[i][i]=1;
    }
};
matrix mul(matrix a,matrix b){
    matrix ans;
    for(int i=0;i<maxn;++i){
        for(int j=0;j<maxn;++j){
            ans.a[i][j] = 0;
            for(int k=0;k<maxn;++k){
                ans.a[i][j]=(ans.a[i][j]+a.a[i][k]*b.a[k][j]+mod)%mod;
            }
        }
    }
    return ans;
}
matrix qpow(matrix a, int n){
    matrix ans;
    ans.init();
    while(n){
        if(n&1) ans = mul(ans, a);
        a=mul(a,a);
        n/=2;
    }
    return ans;
}

然后对于矩阵快速幂的运用来说,一般上用于线性递推的数列求第n项和

比如巨大的斐波拉契数列,如果直接用f(n)=f(n-1)+f(n-2)的话会超时,而如果用矩阵快速幂的形式去算的的话复杂度会降很多

即矩阵形式就是

然后只需要对前面的那个矩阵求(n-1)次方就行了

还有的题目是需要自己去推的矩阵形式

列出最近写的两个题

一道是hdu的6185http://acm.hdu.edu.cn/showproblem.php?pid=6185

一道是牛客网小白赛6的洋灰三角https://www.nowcoder.com/acm/contest/136/J

第二题是需要求前n项和的但是解法还是相似的,递推式就是sum(n)=sum(n-1)+f(n)

就把第二题的代码附一下吧

#include <cstdio>
#include <iostream>
#include <string>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <stack>
#define INF 1e9
using namespace std;
const int maxn=3;
const int mod=1000000007;
struct matrix{
    long long a[maxn][maxn];
    void init(){
        memset(a,0,sizeof(a));
        for(int i=0;i<maxn;i++) a[i][i]=1;
    }
};
matrix mul(matrix a,matrix b){
    matrix ans;
    for(int i=0;i<maxn;++i){
        for(int j=0;j<maxn;++j){
            ans.a[i][j] = 0;
            for(int k=0;k<maxn;++k){
                ans.a[i][j]=(ans.a[i][j]+a.a[i][k]*b.a[k][j]+mod)%mod;
            }
        }
    }
    return ans;
}
matrix qpow(matrix a, int n){
    matrix ans;
    ans.init();
    while(n){
        if(n&1) ans = mul(ans, a);
        a=mul(a,a);
        n/=2;
    }
    return ans;
}
int main()
{
    matrix ans,res;
    int n,k,q;
    memset(ans.a,0,sizeof(ans.a));
    memset(res.a,0,sizeof(res.a));
    cin>>n>>k>>q;
    if(n==1){
        cout<<1<<endl;
        return 0;
    }
    ans.a[0][0]=1;ans.a[0][1]=1;ans.a[1][1]=k;
    ans.a[1][2]=1;ans.a[2][2]=1;
    res=qpow(ans,n);
    long long s=res.a[0][0]*1l%mod+res.a[0][1]*1l%mod+res.a[0][2]*q%mod;
    cout<<s%mod-1<<endl;
}