数列
TimeLimit:1000MS MemoryLimit:64MB
64-bit integer IO format:
%lld
已解决 |
点击收藏
Problem Description
已知一个数列的通向公式:F[n] = 2F[n - 1] + 4F[n - 2] + 2F[n - 3],F[1]、F[2]、F[3]均为1。输入n(1 <= n <= 10^18),求F[n]的值。因为数太大,输出对1000000007取模的值。
Input
第一行输入T,表示T组数据,接下来T行,每行一个n,1 <= n <= 10^18。
Output
输出T行,每行输出F[n] % 1000000007的值。
SampleInput
3 3 6 100
SampleOutput
1 78 360461226
这题是福建农林大学的校赛,当时并没有做出来,因为那是只学了快速幂,不会构造矩阵TT。
这题n的范围有10^18直接暴力O(n)稳稳超时
先构造矩阵,再用快速幂就可以将时间复杂度降为log2(n)
那么如何构造矩阵呢?
f(n) = a(1)*f(n-1) + a(2)*f(n-2) +...+a(d)*f(n-d)
0 1 0 0 . . . 0
0 0 1 0 . . . 0
0 0 0 1 . . . 0
. . . . . . . 0
. . . . . . . 1
a(d) a(d-1) a(d-2) .... a[1]
构造好矩阵后就可以使用快速幂
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 1000000007
using namespace std;
const int maxn = 3;
struct matrix ///开一个结构体存矩阵
{
long long M[maxn][maxn];
};
matrix mul(matrix a,matrix b) ///矩阵相乘
{
matrix c;
for(int i=0; i<maxn; i++)
for(int j=0; j<maxn; j++)
{
c.M[i][j] = 0;
for(int k=0; k<maxn; k++)
c.M[i][j] =(c.M[i][j]+ a.M[i][k]*b.M[k][j]%mod)%mod;
}
return c;
}
long long Matrix_fast_power(matrix a,matrix b,long long m) ///快速幂
{
if(m <= 3) return 1;
m -= 3;
while(m)
{
if(m&1)
a=mul(a,b);
m>>=1;
b=mul(b,b);
}
return (a.M[2][0] + a.M[2][1] + a.M[2][2]) % mod;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
long long n;
scanf("%lld",&n);
matrix a,b;
memset(a.M,0,sizeof(a.M));
memset(b.M,0,sizeof(b.M));
a.M[0][0]=a.M[1][1]=a.M[2][2]=1; ///单位矩阵
b.M[0][1] = 1,b.M[1][2] = 1,b.M[2][0] = 2,b.M[2][1] = 4,b.M[2][2] = 2;
///构造的矩阵
printf("%lld\n",Matrix_fast_power(a,b,n));
}
return 0;
}