模板

线性递推公式找递推矩阵的方法:

https://blog.csdn.net/synapse7/article/details/18790165

构造方法:规定由递推矩阵A,左乘由项构成的矩阵F,其中矩阵A的第一列为对应系数,左下角为单位矩阵,右下角为零矩阵。

对于递推式的常数C,在矩阵F中增加最后一行C,在A的最右列增加两个1(通常选右上角和左下角)。

对于递推式的C的n次方,在矩阵F中增加最后一行C的n次方,在A的最右列增加两个C(通常选右上角和左下角)。

以斐波那契数列为例,这里使用了快速乘进一步防止溢出。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAXN 2

ll mod=1000000007;

//快速乘 a*b%p 防止乘法溢出ll
ll qmut(ll a,ll b){
    ll res=0;
    while(b){
        if(b&1) res=(res+a)%mod;
        a=(a+a)%mod;
        b>>=1;
    }
    return res;
}

class Matrix {
  public:
    ll m[MAXN][MAXN];
    //二维数组存放矩阵
    Matrix() {
        memset(m,0,sizeof(m));
    }
    //对数组的初始化
    void init(ll num[MAXN][MAXN]) {
        for(int i = 0 ; i < MAXN ; i++) {
            for(int j = 0 ; j < MAXN ; j++) {
                m[i][j] = num[i][j];
            }
        }
    }

    Matrix operator*(Matrix &m1) {
        int i, j, k;
        Matrix t;
        for(i = 0; i < MAXN; i++) {
            for(j = 0; j < MAXN; j++) {
                t.m[i][j] = 0;
                for(k = 0 ; k < MAXN ; k++)
                    t.m[i][j] = (t.m[i][j] + qmut(m[i][k],m1.m[k][j]))%mod;
            }
        }
        return t;
    }

    Matrix qpow(ll n) {
        Matrix t;
        for(int i = 0 ; i < MAXN ; i++)
            for(int j = 0 ; j < MAXN ; j++)
                t.m[i][j] = (i == j);

        Matrix M=*this;
        while(n) {
            if(n & 1)
                t = t * M;
            n = n >> 1;
            M = M * M;
        }
        return t;
    }

    void show() {
        for(int i=0; i<MAXN; i++) {
            for(int j=0; j<MAXN; j++) {
                cout<<m[i][j]<<" ";
            }
            cout<<endl;
        }
        cout<<endl;
    }
};

int main() {
    ll n;
    cin>>n;

    if(n<=2){
        cout<<1<<endl;
        return 0;
    }

    ll num[MAXN][MAXN];

    Matrix A;
    memset(num,0,sizeof(num));
    num[0][1]=num[1][0]=num[1][1]=1;
    A.init(num);//初始化A矩阵
    //A.show();

    Matrix ini;
    memset(num,0,sizeof(num));
    num[0][0]=1;
    num[1][0]=1;

    ini.init(num);
    //ini.show();

    Matrix An=A.qpow(n-2); //求出矩阵的快速幂
    //An.show();

    Matrix res=An*ini;
    //res.show();

    cout<<res.m[1][0]<<endl;
}

https://www.luogu.org/problemnew/show/P1939

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAXN 4

ll mod=1000000007;

//快速乘 a*b%p 防止乘法溢出ll
ll qmut(ll a,ll b){
    ll res=0;
    while(b){
        if(b&1) res=(res+a)%mod;
        a=(a+a)%mod;
        b>>=1;
    }
    return res;
}

class Matrix {
  public:
    ll m[MAXN][MAXN];
    //二维数组存放矩阵
    Matrix() {
        memset(m,0,sizeof(m));
    }
    //对数组的初始化
    void init(ll num[MAXN][MAXN]) {
        for(int i = 0 ; i < MAXN ; i++) {
            for(int j = 0 ; j < MAXN ; j++) {
                m[i][j] = num[i][j];
            }
        }
    }

    Matrix operator*(Matrix &m1) {
        int i, j, k;
        Matrix t;
        for(i = 0; i < MAXN; i++) {
            for(j = 0; j < MAXN; j++) {
                t.m[i][j] = 0;
                for(k = 0 ; k < MAXN ; k++)
                    t.m[i][j] = (t.m[i][j] + qmut(m[i][k],m1.m[k][j]))%mod;
            }
        }
        return t;
    }

    Matrix qpow(ll n) {
        Matrix t;
        for(int i = 0 ; i < MAXN ; i++)
            for(int j = 0 ; j < MAXN ; j++)
                t.m[i][j] = (i == j);

        Matrix M=*this;
        while(n) {
            if(n & 1)
                t = t * M;
            n = n >> 1;
            M = M * M;
        }
        return t;
    }

    void show() {
        for(int i=0; i<MAXN; i++) {
            for(int j=0; j<MAXN; j++) {
                cout<<m[i][j]<<" ";
            }
            cout<<endl;
        }
        cout<<endl;
    }
};

int main() {
    int T;
    while(~scanf("%d",&T)){
        while(T--){
            int n;
            scanf("%d",&n);

            if(n<=3){
                printf("%d
",1);
                continue;
            }

            ll num[MAXN][MAXN];

            Matrix A;
            memset(num,0,sizeof(num));
            num[0][1]=num[1][2]=num[2][3]=num[3][1]=num[3][3]=1;
            A.init(num);//初始化A矩阵
            //A.show();

            Matrix ini;
            memset(num,0,sizeof(num));
            num[0][0]=1;
            num[1][0]=1;
            num[2][0]=1;
            num[3][0]=2;

            ini.init(num);
            //ini.show();

            Matrix An=A.qpow(n-4); //求出矩阵的快速幂
            //An.show();

            Matrix res=An*ini;
            //res.show();

            printf("%d
",res.m[3][0]);
        }
    }
}

带n的次方的矩阵快速幂,找出相邻两项的关系就可以,用杨辉三角就可以了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAXN 8

ll mod=2147493647;

class Matrix {
  public:
    ll m[MAXN][MAXN];
    //二维数组存放矩阵
    Matrix() {
        memset(m,0,sizeof(m));
    }
    //对数组的初始化
    void init(ll num[MAXN][MAXN]) {
        for(int i = 0 ; i < MAXN ; i++) {
            for(int j = 0 ; j < MAXN ; j++) {
                m[i][j] = num[i][j];
            }
        }
    }

    Matrix operator*(Matrix &m1) {
        int i, j, k;
        Matrix t;
        for(i = 0; i < MAXN; i++) {
            for(j = 0; j < MAXN; j++) {
                t.m[i][j] = 0;
                for(k = 0 ; k < MAXN ; k++)
                    t.m[i][j] = (t.m[i][j] + m[i][k]*m1.m[k][j]%mod)%mod;
            }
        }
        return t;
    }

    Matrix qpow(ll n) {
        Matrix t;
        for(int i = 0 ; i < MAXN ; i++)
            for(int j = 0 ; j < MAXN ; j++)
                t.m[i][j] = (i == j);

        Matrix M=*this;
        while(n) {
            if(n & 1)
                t = t * M;
            n = n >> 1;
            M = M * M;
        }
        return t;
    }

    void show() {
        for(int i=0; i<MAXN; i++) {
            for(int j=0; j<MAXN; j++) {
                cout<<m[i][j]<<" ";
            }
            cout<<endl;
        }
        cout<<endl;
    }
};

int main() {
    int T;
    while(~scanf("%d",&T)) {
        while(T--) {
            ll n,a,b;
            scanf("%lld%lld%lld",&n,&a,&b);
            if(n==1) {
                printf("%lld
",a);
            } else if(n==2) {
                printf("%lld
",b);
            } else {
                ll num[MAXN][MAXN];

                Matrix A;
                memset(num,0,sizeof(num));
                num[0][0]=1;
                num[1][0]=1;
                num[1][1]=1;
                for(int i=2;i<=5;i++){
                    num[i][0]=1;
                    for(int j=1;j<=i;j++){
                        num[i][j]=num[i-1][j-1]+num[i-1][j];
                    }
                }
                num[6][7]=1;
                num[7][5]=3;
                num[7][6]=3;
                num[7][7]=2;
                A.init(num);//初始化A矩阵
                //A.show();

                Matrix ini;
                memset(num,0,sizeof(num));
                num[0][0]=1;
                num[1][0]=3;
                num[2][0]=9;
                num[3][0]=27;
                num[4][0]=81;
                num[5][0]=243;
                num[6][0]=a;
                num[7][0]=b;

                ini.init(num);
                //ini.show();

                Matrix An=A.qpow(n-2); //求出矩阵的快速幂
                //An.show();

                Matrix res=An*ini;
                //res.show();
                printf("%lld
",res.m[7][0]);
            }
        }
    }
}
原文地址:https://www.cnblogs.com/Yinku/p/10398954.html