矩阵快速幂

  矩阵快速幂的用途主要是用来递推公式。主要过程是构造一个系数矩阵A和一个值的矩阵B,令(A^k)×B的值与第k项正好相等或是相关。

模板的话差不多都是一样的,只不过是把对数的快速幂拓展到了对矩阵的快速幂。这个模板里面用的是静态的矩阵,速度稍微会 快一点。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <math.h>
#define pi acos(-1.0 )
#define fastio ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;       // 不能加负号!!!
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;//4e18 ~= 2^62
const int maxn =100000 + 10;
const LL mod = 2147493647;

vector<LL> V;

typedef struct MATRIX
{
    LL mat[10][10];
}MATRIX;

MATRIX A, B;

inline MATRIX mul(MATRIX a,MATRIX b,int n)
{
    MATRIX c;
    memset(c.mat,0,sizeof(c.mat));
    for(int k=0;k<n;k++)
        for(int i=0;i<n;i++)
            if(a.mat[i][k])
                for(int j=0;j<n;j++)
                    if(b.mat[k][j])
                    {
                        c.mat[i][j]+=a.mat[i][k]*b.mat[k][j]%mod;
                        c.mat[i][j]%=mod;
                    }
    return c;
}
inline MATRIX pow(MATRIX a,int N,int n)
{
    MATRIX E;
    memset(E.mat,0,sizeof(E.mat));
    for(int i=0;i<n;i++) E.mat[i][i]=1;
    while(N>0)
    {
        if(N & 1)
            E=mul(E,a,n);
        N>>=1;
        a=mul(a,a,n);
    }
    return E;
}

void inn(int index , string s)
{
    for(int i=0;i<s.length();i++){
        A.mat[index][i] = s[i]-'0';
    }
}

int main()
{
    int T; scanf("%d", &T);
    while(T--){
        memset(A.mat, 0, sizeof(A.mat));
        memset(B.mat, 0, sizeof(B.mat));
        LL n, a, b;
        scanf("%lld%lld%lld", &n, &a, &b);
        string s;
        inn(0,"1210000");
        inn(1,"1000000");
        inn(2,"0014641");
        inn(3,"0001331");
        inn(4,"0000121");
        inn(5,"0000011");
        inn(6,"0000001");

        B.mat[0][0] = b;
        B.mat[1][0] = a;
        B.mat[2][0] = 81;
        B.mat[3][0] = 27;
        B.mat[4][0] = 9 ;
        B.mat[5][0] = 3 ;
        B.mat[6][0] = 1 ;

        if(n<=2){
            if(n==1) printf("%lld\n",a);
            else printf("%lld\n", b);
        }
        else {
            A = pow(A, n-2, 7);
            B = mul(A, B, 7);
            printf("%lld\n", B.mat[0][0]);
        }
    }
}
View Code

题目的链接:Recursive sequence

主要的用法和技巧:

 

posted @ 2018-10-04 19:36  会打架的程序员不是好客服  阅读(171)  评论(0编辑  收藏  举报