1 <= n <= 100000000000000
题解:矩阵加速线性递推
关键在于构造矩阵,初始矩阵中存储的是数列的第0项和第1项
s={0
1}
然后是加速矩阵
e={0 1
1 1}
然后先进行矩阵快速幂,再将快速幂后的矩阵乘初始矩阵即为答案
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
long long x,i,j;
int n;
const int inf= 1000000007;
struct data
{
long long m[5][5];
};data e,s;
void init(data &a,data b)
{
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
a.m[i][j]=b.m[i][j];
}
data mul(data a,data b)
{
data c;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
c.m[i][j]=0;
for (int k=1;k<=n;k++)
c.m[i][j]=(long long)(c.m[i][j]%inf+(a.m[i][k]%inf*b.m[k][j]%inf)%inf)%inf;
}
return c;
}
data quickpow(long long x)
{
data ans;
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
ans.m[i][j]=0;
for (int i=1;i<=2;i++)
ans.m[i][i]=1;
data a;
init(a,e);
while (x>0)
{
if (x&1)
ans=mul(ans,a);
x=x>>1;
a=mul(a,a);
}
return ans;
}
int main()
{
s.m[1][1]=0;
s.m[2][1]=1;
e.m[1][1]=0; e.m[1][2]=1; e.m[2][1]=1; e.m[2][2]=1;
n=2;
while (scanf("%lld",&x)!=EOF)
{
data k=quickpow(x-1);
/*for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
cout<<k.m[i][j]<<" ";
cout<<endl;
}*/
data l=mul(k,s);
printf("%d\n",l.m[2][1]);
}
}