fabonacci数列递推式:f[i]=f[i-1]+f[i-2]
对于给定的n,当n很大时,从第一项开始递推时间复杂度很大。考虑用矩阵做。
我们的目标是构造一个矩阵A满足下面式子:
注意一般将递推式右边写在左边,用来递推求出右边的Fn
可推出A为2*2的矩阵:
所以:
令 ,则Fn=F0*A[0][0]+F1*A[1][0]=A[1][0]
斐波那契数列卷积
theme:给定n,求an,其中an递推式为:
solution:首先推出an递推式:
推出矩阵A:
下面编码采用An-1、fn等顺序不一样,可自行推导:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
#define far(i,t,n) for(int i=t;i<n;++i)
#define pk(a) push_back(a)
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int inf=0x3f3f3f3f;
int mod=998244353;
struct mat
{
ll var[10][10];
mat()
{
far(i,0,10)
far(j,0,10)
var[i][j]=0;
}
void init()
{
var[0][0]=var[0][1]=var[0][2]=1;
var[1][0]=1;
var[2][2]=var[2][3]=1;
var[3][2]=1;
}
mat operator*(mat b)const
{
mat ans;
far(i,0,4)
far(j,0,4)
{
ll sum=0;
far(k,0,4)
sum=(sum+var[i][k]*b.var[k][j]%mod)%mod;
ans.var[i][j]=sum;
}
return ans;
}
};
mat quickMatPow(mat a,ll b)
{
mat ans;
far(i,0,4)
ans.var[i][i]=1;
while(b)
{
if(b%2)
ans=ans*a;
a=a*a;
b/=2;
}
return ans;
}
int main()
{
ll n;
while(scanf("%lld",&n)!=EOF)
{
mat a;
a.init();
a=quickMatPow(a,n-1);
printf("%lld\n",a.var[0][2]);
}
}
求斐波那契数后n位数
就是用矩阵快速幂求,后n个数即求模,如后4位就是矩阵乘的时候将mod改为10000即可
求斐波那契数前n位数
斐波那契数列通式:
两边取10的对数:
log10(fi)=-0.5*log10(5.0)+i*1.0*log10((1+sqrt(5.0))/2.0);
通过log10(fi)可求出fi的长度,如n=12345,则log10(n)=4.09149,则n的长度为4+1=5,(即n比10^4大一点),即n=10^4.09149=10^4*10^0.09149,所以通过10^0.09149就可以得到n科学计数法的系数1.2345,这时求前4位数*1000即可
所以求fibonacci数前4位代码为:
注意不足4位的要特判一下
double ans=-0.5*log10(5.0)+n*1.0*log10((1+sqrt(5.0))/2.0);
ans=ans-(int)ans;
ans=pow(10.0,ans);
ans=ans*1000;
int pre=(int)ans;
hdu:3117Fibonacci Numbers
theme:给定n,求Fibonacci[i]的前4位和后4位数。0<=n<=1e8
theme:给定n,求Fibonacci[i]的前4位和后4位数。0<=n<=1e8
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
#define far(i,t,n) for(int i=t;i<n;++i)
#define pk(a) push_back(a)
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int inf=0x3f3f3f3f;
int mod=10000;
int f[50];
struct mat
{
int var[10][10];
mat()
{
far(i,0,10)
far(j,0,10)
var[i][j]=0;
}
void init()
{
var[0][0]=var[0][1]=var[1][0]=1;
}
mat operator*(mat b)const
{
mat ans;
far(i,0,2)
far(j,0,2)
{
int sum=0;
far(k,0,2)
sum=(sum+var[i][k]*b.var[k][j]%mod)%mod;
ans.var[i][j]=sum;
}
return ans;
}
};
mat quickMatPow(mat a,int b)
{
mat ans;
far(i,0,2)
ans.var[i][i]=1;
while(b)
{
if(b%2)
ans=ans*a;
a=a*a;
b/=2;
}
return ans;
}
int main()
{
f[0]=0,f[1]=1;
for(int i=2;i<=39;++i)
f[i]=f[i-1]+f[i-2];
int n;
while(scanf("%d",&n)!=EOF)
{
if(n<40)
{
printf("%d\n",f[n]);
continue;
}
mat a;
a.init();
a=quickMatPow(a,n);
int last=a.var[0][1];
double ans=-0.5*log10(5.0)+n*1.0*log10((1+sqrt(5.0))/2.0);
ans=ans-(int)ans;
ans=pow(10.0,ans);
ans=ans*1000;
int pre=(int)ans;
printf("%d...%04d\n",pre,last);
}
}