[Luogu] P1939 【模板】矩阵加速(数列)

题目描述

a[1]=a[2]=a[3]=1

a[x]=a[x-3]+a[x-1] (x>3)

求a数列的第n项对1000000007(10^9+7)取余的值。

题目解析

顺序:x.x,y.y,x.y

Code

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int MOD = 1000000007;

struct Matrix {
    long long m[10][10];
    int sx,sy;
} str,pro;

long long n;

void init() {
    str.m[1][1] = str.m[1][2] = str.m[1][3] = 1;
    str.sx = 1;
    str.sy = 3;
    pro.m[1][1] = pro.m[1][2] = pro.m[2][2] = pro.m[2][3] = pro.m[3][1] = 0;
    pro.m[1][3] = pro.m[2][1] = pro.m[3][2] = pro.m[3][3] = 1;
    pro.sx = pro.sy = 3;
    return;
}

inline Matrix mul(Matrix a,Matrix b) {
    Matrix res;
    memset(res.m,0,sizeof(res.m));
    for(int i = 1;i <= a.sx;i++) {
        for(int j = 1;j <= b.sy;j++) {
            for(int k = 1;k <= b.sx;k++) {
                res.m[i][j] += a.m[i][k] * b.m[k][j] % MOD;
                res.m[i][j] %= MOD;
            }
        }
    }
    res.sx = a.sx, res.sy = b.sy;
    return res;
}

inline Matrix quick_pow(Matrix x,long long y) {
    Matrix res;
    res.sx = str.sx;
    res.sy = str.sy;
    for(int i = 1;i <= 5;i++) {
        for(int j = 1;j <= 5;j++) {
            res.m[i][j] = (i==j);
        }
    }
    while(y) {
        if(y & 1) res = mul(res,x);
        x = mul(x,x);
        y >>= 1;
    }
    return res;
}

int main() {
    int T;
    scanf("%d",&T);
    while(T--) {
        scanf("%lld",&n);
        init();
        if(n <= 3) {
            puts("1");
            continue;
        }
        Matrix ans = mul(str,quick_pow(pro,n));
        printf("%lld
",ans.m[1][3]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/floatiy/p/9772496.html