时间复杂度为\(O(\frac{n}{k}+k),\)当k=\(\sqrt n\)时取最小,得出结果\(O(\sqrt n).\)
代码:
#include<cstdio>
#include<cmath>
# define ll long long
void make(ll n,ll &x,ll &y,ll m)////x:Fib[n] ; y:Fib[n+1] ; m:Mod
{
ll a,b,to[3]={0,1,1};
////特判
if(n<2)
{
x=to[n];
y=to[n+1];
return;
}
if(n==2)
{
x=1;
y=2;
return;
}
////求k,并递归求解Fib[k]及F[k+1]
ll k=sqrt(n);
make(k,a,b,m);
////从Fib[k]到Fib[k*k]的变化
for(ll i=1;i<=k;++i)
{
to[2]=(to[1]*a+to[2]*b)%m;
to[1]=(to[0]*a+to[1]*b)%m;
to[0]=(to[2]-to[1])%m;
}
k*=k;
////如果已经得到解(n为完全平方数),退出
if(k==n)
{
x=(to[0]%m+m)%m;
y=(to[1]%m+m)%m;
return;
}
////如果没有,则从k*k迭代到n
for(ll i=k+1;i<=n;++i)
{
to[2]=to[1];
to[1]=(to[0]+to[1])%m;
to[0]=to[2];
}
x=(to[0]%m+m)%m;
y=(to[1]%m+m)%m;
}
int main()
{
ll n,x,y;
scanf("%lld",&n);
make(n,x,y,1000000007);
printf("%lld",x);
return 0;
}
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
# define Type template<typename T>
Type inline T read1()
{
T t=0;
char k=getchar();
bool flag=0;
while('0'>k||k>'9')
{
if(k=='-')flag=1;
k=getchar();
}
while('0'<=k&&k<='9')t=(t<<3)+(t<<1)+(k^48),k=getchar();
return flag?-t:t;
}
# define ll long long
class Mat
{
# define Vec vector<ll>
# define Arr vector<Vec>
Arr a;
public:
Mat(){}
Mat(Arr k):a(k){}
Mat(ll x,ll y){a.resize(x);for(ll i=0;i<x;++i)a[i].resize(y);}
Vec& operator [](const ll k){return a[k];}
ll wide(){return a.size();}
ll len(){return a.empty()?0:a[0].size();}
Mat operator *(Mat k)
{
Arr tem;
tem.resize(wide());
for(ll i=0;i<wide();++i)
{
tem[i].resize(k.len());
for(ll j=0;j<len();++j)
for(ll l=0;l<k.len();++l)
tem[i][l]+=a[i][j]*k[j][l];
}
return Mat(tem);
}
Mat operator +(Mat k)
{
ll o=max(wide(),k.wide()),p=max(len(),k.len());
Mat tem(o,p);
for(ll i=0;i<o;++i)
for(ll j=0;j<p;++j)
{
if(i<wide()&&j<len())tem[i][j]=a[i][j];
if(i<k.wide()&&j<k.len())tem[i][j]+=k[i][j];
}
return tem;
}
Mat operator %(ll k)
{
Mat tem(wide(),len());
for(ll i=0;i<wide();++i)
for(ll j=0;j<len();++j)
tem[i][j]=a[i][j]%k;
return tem;
}
Mat& operator %=(ll k){return *this=*this%k;}
Mat& operator *=(Mat k){return *this=*this*k;}
Mat& operator +=(Mat k){return *this=*this+k;}
bool scan(ll x,ll y,const ll value)
{
if(x>=wide()||y>=len()||x<0||y<0)return 0;
a[x][y]=value;
return 1;
}
# undef Vec
# undef Arr
};
Type T quickpow(T k,const ll n,ll Mod)
{
if(n==1)return k;
T tem=quickpow(k,n>>1,Mod);
if(Mod!=0)
{
tem=(tem*tem)%Mod;
if(n&1)tem=(tem*k)%Mod;
}
else
{
tem*=tem;
if(n&1)tem*=k;
}
return tem;
}
# define read read1<ll>()
int main()
{
ll n=read,l=read;
if(n==1)return !putchar('1');
Mat k(2,2);
k[0][0]=k[0][1]=k[1][0]=1;
k=quickpow(k,n-1,l);
printf("%lld",k[0][0]);
return 0;
}
原文:https://www.cnblogs.com/SYDevil/p/11900291.html