洛谷 P1939 【模板】矩阵加速(数列)

题目描述

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

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

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

输入输出格式

输入格式:

第一行一个整数T,表示询问个数。

以下T行,每行一个正整数n。

输出格式:

每行输出一个非负整数表示答案。

输入输出样例

输入样例#1:  

3
6
8
10

输出样例#1:  

4
9
19

说明

对于30%的数据 n<=100;

对于60%的数据 n<=2*10^7;

对于100%的数据 T<=100,n<=2*10^9;

题解:

其实这篇本来想写日记的,但是老师突然来到了我的身边,我就迅速把这道刚做完的题粘到了这里。

有始有终,就写吧。

谁可以告诉我,为什么我的暴力没有分!

众人OS:你错了呗。

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

typedef long long LL;
const int mod=1e9+7;
int T, n;
LL tmp[3][3]={{0,0,1},{1,0,0},{0,1,1}};

struct Matrix33{
    LL mat[3][3];
    Matrix33 operator *(Matrix33 b){
        Matrix33 m;
        for (int i=0; i<3; ++i) for (int j=0; j<3; ++j){
            m.mat[i][j]=0;
            for (int k=0; k<3; ++k)
                m.mat[i][j]=(m.mat[i][j]+(mat[i][k]*b.mat[k][j]%mod))%mod;
        }
        return m;
    }
}beg, unit, plus;

Matrix33 get_mat(int n){
    memcpy(plus.mat, tmp, sizeof(tmp));
    Matrix33 ans=unit;
    while (n){
        if (n&1) ans=ans*plus;
        plus=plus*plus;
        n>>=1;
    }
    return ans;
}

int main(){
    unit.mat[0][0]=unit.mat[1][1]=unit.mat[2][2]=1;
    beg.mat[0][0]=beg.mat[0][1]=beg.mat[0][2]=1;
    scanf("%d", &T);
    for (int tt=0; tt<T; ++tt){
        scanf("%d", &n);
        if (n<4) printf("1\n");
        else printf("%lld\n", (beg*get_mat(n-3)).mat[0][2]);
    }
    return 0;
}
AC

一世安宁

posted @ 2018-08-08 10:37  GTBA  阅读(205)  评论(0编辑  收藏  举报