3332 数列
时间限制: 1 s
空间限制: 256000 KB
题目等级 : 大师 Master
题目描述 Description
a[1]=a[2]=a[3]=1
a[x]=a[x-3]+a[x-1] (x>3)
求a数列的第n项对1000000007(10^9+7)取余的值。
输入描述 Input Description
第一行一个整数T,表示询问个数。
以下T行,每行一个正整数n。
输出描述 Output Description
每行输出一个非负整数表示答案
样例输入 Sample Input
3
6
8
10
样例输出 Sample Output
4
9
19
数据范围及提示 Data Size & Hint
对于30%的数据 n<=100;
对于60%的数据 n<=2*10^7;
对于100%的数据 T<=100,n<=2*10^9;
分类标签 Tags
快速幂 矩阵乘法 数论
/*
矩阵乘法快速幂.
关键在于推矩阵.
这个题矩阵还是比较好推的.
然后很快就A了......
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define mod 1000000007
#define MAXN 4
#define LL long long
using namespace std;
LL b[MAXN][MAXN],a[MAXN][MAXN],ans[MAXN][MAXN],c[MAXN][MAXN];
void mi(int n)
{
while(n)
{
if(n&1)
{
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
for(int k=1;k<=3;k++)
c[i][j]=(c[i][j]+ans[i][k]*b[k][j]%mod)%mod;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
ans[i][j]=c[i][j],c[i][j]=0;
}
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
for(int k=1;k<=3;k++)
c[i][j]=(c[i][j]+b[i][k]*b[k][j]%mod)%mod;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
b[i][j]=c[i][j],c[i][j]=0;
n>>=1;
}
}
void slove(int n)
{
memset(ans,0,sizeof ans);memset(b,0,sizeof b);
b[1][1]=ans[1][1]=1,b[1][2]=ans[1][2]=1,
b[2][3]=ans[2][3]=1,b[3][1]=ans[3][1]=1;
a[1][1]=a[1][2]=a[1][3]=1;
mi(n);
printf("%lld\n",ans[3][1]%mod);
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);n--;
slove(n);
}
return 0;
}