题目描述
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×107;
对于100%的数据 T<=100,n<=2×109;
#include<cstdio>
#include<iostream>
#include<cstring>
#define ll long long
#define mod 1000000007
using namespace std;
#define N 102
class Matrix{
public:
ll a[N][N],n;
Matrix(ll _n){
n=_n;
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++) a[i][i]=1%mod;
}
ll get(int x,int y){
return a[x][y];
}
void set(int x,int y,int val){
a[x][y]=val%mod;
}
void mul(Matrix &b){
ll c[N][N]={0};
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
c[i][j]+=a[i][k]*b.a[k][j]%mod;
c[i][j]%=mod;
}
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) a[i][j]=c[i][j];
}
void pow(ll k){
Matrix ret(n);
while(k){
if(k&1){
ret.mul(*this);
}k>>=1;
this->mul(*this);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) a[i][j]=ret.a[i][j]%mod;
}
void display(){
for(int i=1;i<=n;i++){
printf("%lld",a[i][1]);
for(int j=2;j<=n;j++){
printf(" %lld",a[i][j]);
}
printf("\n");
}
}
};
int main(){
int T=0;scanf("%d",&T);
while(T--){
Matrix f(3);
long long n;scanf("%lld",&n);
if(n<=3){
printf("1\n");
continue;
}
f.set(1,1,1);f.set(1,2,0);f.set(1,3,1);
f.set(2,1,1);f.set(2,2,0);f.set(2,3,0);
f.set(3,1,0);f.set(3,2,1);f.set(3,3,0);
f.pow(n-3);
long long ret=f.get(1,1)%mod+f.get(1,2)%mod+f.get(1,3)%mod;
printf("%lld\n",ret%mod);
}
return 0;
}