题目描述 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;
题解:
一个比较裸的矩阵乘
构造如下矩阵
⎡⎣⎢110001100⎤⎦⎥ ×⎡⎣⎢x[n−1]x[n−2]x[n−3]⎤⎦⎥=⎡⎣⎢x[n]x[n−1]x[n−2]⎤⎦⎥
然后计算第一个矩阵的n-3次方再乘上
⎡⎣⎢x[3]x[2]x[1]⎤⎦⎥即可
代码:
#include<iostream>
#include<cstdio>
#define m 1000000007
using namespace std;
long long ans[10][10],n,aa[10][10],sum,t;
bool f;
inline long long cheng(long long a,long long b)
{
long long ans(0);
a=a%m;
while (b>0)
{
if (b%2==1)
ans=(ans+a)%m;
b/=2;
a=(a*2)%m;
}
return ans;
}
inline void power(long long x)
{
long long k[5][5];
while (x>0)
{
if (x%2==1)
{
if (f==false)
{
for (int i=1;i<=3;i++)
for (int j=1;j<=3;j++)
ans[i][j]=aa[i][j];
f=true;
}
else
{
for (int i=1;i<=3;i++)
for (int j=1;j<=3;j++)
{
k[i][j]=0;
for (int p=1;p<=3;p++)
k[i][j]=(k[i][j]+cheng(ans[i][p],aa[p][j]))%m;
}
for (int i=1;i<=3;i++)
for (int j=1;j<=3;j++)
ans[i][j]=k[i][j];
}
}
x/=2;
for (int i=1;i<=3;i++)
for (int j=1;j<=3;j++)
{
k[i][j]=0;
for (int p=1;p<=3;p++)
k[i][j]=(k[i][j]+cheng(aa[i][p],aa[p][j]))%m;
}
for (int i=1;i<=3;i++)
for (int j=1;j<=3;j++)
aa[i][j]=k[i][j];
}
}
int main()
{
cin>>t;
while (t--)
{
cin>>n;
if (n==1||n==2||n==3)
cout<<1<<endl;
else
{
f=false;
aa[1][1]=1;aa[1][2]=0;aa[1][3]=1;
aa[2][1]=1;aa[2][2]=0;aa[2][3]=0;
aa[3][1]=0;aa[3][2]=1;aa[3][3]=0;
power(n-3);
sum=(cheng(ans[1][1],1)+cheng(ans[1][2],1)+cheng(ans[1][3],1))%m;
printf("%lld\n",sum);
}
}
}