【洛谷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;

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
inline ll read(){
    ll x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct mat
{
    ll m[6][6];
    int x,y;
}a,b;
inline mat matmul(mat x,mat y){
    mat t; t.x=x.y; t.y=y.y;
    for(int i=1;i<=x.x;++i)
    for(int j=1;j<=y.y;++j){
        t.m[i][j]=0;
        for(int k=1;k<=x.y;++k)
        t.m[i][j]=(t.m[i][j]+x.m[i][k]*y.m[k][j])%mod;
    }
    return t;
}
inline mat matpow(mat x,int p){
    mat res; res.x=res.y=3;
    for(int i=1;i<=3;++i)
    for(int j=1;j<=3;++j)
        res.m[i][j]=x.m[i][j];
    while(p){
        if(p&1) res=matmul(res,x);
        x=matmul(x,x);
        p=p>>1;
    }
    return res;
}
int main()
{
    int T=read(),n;
    a.m[1][1]=a.m[1][3]=a.m[2][1]=a.m[3][2]=1;
    b.m[1][1]=b.m[2][1]=b.m[3][1]=1;
    a.x=a.y=3; b.x=3; b.y=1;
    while(T--){
        n=read();
        if(n<=3) {printf("%d\n",1); continue;}
        mat tmp=matpow(a,n-3-1);
        tmp=matmul(tmp,b);
        printf("%lld\n",tmp.m[1][1]);
    }
    return 0;
}

 

posted @ 2017-10-17 22:14  沐灵_hh  阅读(186)  评论(0编辑  收藏  举报