牛客 2018年湘潭大学程序设计竞赛 G 又见斐波那契(矩阵构造)
链接:https://www.nowcoder.com/acm/contest/105/G
来源:牛客网
题目描述
这是一个加强版的斐波那契数列。
给定递推式
求F(n)的值,由于这个值可能太大,请对109+7取模。
输入描述:
第一行是一个整数T(1 ≤ T ≤ 1000),表示样例的个数。
以后每个样例一行,是一个整数n(1 ≤ n ≤ 1018)。
输出描述:
每个样例输出一行,一个整数,表示F(n) mod 1000000007。
示例1
输入
4
1
2
3
100
输出
1
16
57
558616258
解析
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
#define mod 1000000007
#define rep(i,a,b) for(int i=a;i<b;i++)
#define rep1(i,b,a) for(int i=b;i>=a;i--)
using namespace std;
const int N=1e5+100;
/*
关键在于矩阵的构造
其实很好推(i+1)^3=i^3+3*i^2+3*i+1
同理推出其他的项(共六项)
构造出arr数组(即一个矩阵)
初始矩阵为(1,0,8,4,2,1)
然后按照矩阵快速幂模板来做即可
*/
ll arr[6][6]={
1,1,0,0,0,0,
1,0,0,0,0,0,
1,0,1,0,0,0,
1,0,3,1,0,0,
1,0,3,2,1,0,
1,0,1,1,1,1};
struct node
{
ll m,l;//m为矩阵的行数,l为矩阵的列数
ll v[7][7];
};
node get_mul(node a,node b)
{
node c;
c.m=a.m,c.l=b.l;
for(int i=0;i<c.m;i++)
{
for(int j=0;j<c.l;j++)
{
c.v[i][j]=0;
for(int k=0;k<a.l;k++)
{
c.v[i][j]=(c.v[i][j]+a.v[i][k]*b.v[k][j])%mod;
}
}
}
return c;
}
int getresult(ll n)
{
node a,b;
a.l=6,a.m=1;
a.v[0][0]=1,a.v[0][1]=0,a.v[0][2]=8;
a.v[0][3]=4,a.v[0][4]=2,a.v[0][5]=1,
b.l=6,b.m=6;
rep(i,0,6)
rep(j,0,6)
b.v[i][j]=arr[i][j];
while(n)
{
if(n&1)
a=get_mul(a,b);
b=get_mul(b,b);
n>>=1;
}
return a.v[0][0];
}
int main()
{
ios::sync_with_stdio(false);
ll n,t;
cin>>t;
while(t--)
{
cin>>n;
cout<<getresult(n-1)<<endl;
}
return 0;
}