斐波那契数列相关算法及例题

本文探讨了如何使用矩阵快速幂算法在O(logn)时间内解决斐波那契数列问题,同时提供了避免溢出的解决方案,并介绍了利用公式在O(1)复杂度下求解斐波那契数列的方法。

1..循环    时间复杂度O(n)

int f(int a)
{
	int f0=0,f1=1,f2=1;
	if(a)
	{
		for(int i=1;i<a;i++)
	{
		f2=f0+f1;
		f0=f1;
		f1=f2;
	}
	return f2;
	}
	else return 0;
}
2. 矩阵求解    时间复杂度O(logn)

    斐波那契的递推公式可以表示成如下矩阵形式,所以其


      

所以根据矩阵的分治算法,可以在O(logn)时间内算出结果。

笔试问题:

对于斐波拉契经典问题,我们都非常熟悉,通过递推公式F(n) = F(n - 1) + F(n - 2),我们可以在线性时间内求出第nF(n),现在考虑斐波拉契的加强版,我们要求的项数n的范围为int范围内的非负整数,请设计一个高效算法,计算第nF(n)。第一个斐波拉契数为F(0) = 1

给定一个非负整数,请返回斐波拉契数列的第n项,为了防止溢出,请将结果Mod 1000000007


2.矩阵求解    时间复杂度O(logn)     重要

    斐波那契的递推公式可以表示成如下矩阵形式,所以其


      

所以根据矩阵的分治算法,可以在O(logn)时间内算出结果。

笔试问题:

对于斐波拉契经典问题,我们都非常熟悉,通过递推公式F(n) = F(n - 1) + F(n - 2),我们可以在线性时间内求出第nF(n),现在考虑斐波拉契的加强版,我们要求的项数n的范围为int范围内的非负整数,请设计一个高效算法,计算第nF(n)。第一个斐波拉契数为F(0) = 1

给定一个非负整数,请返回斐波拉契数列的第n项,为了防止溢出,请将结果Mod 1000000007

  1. long[][] f = new long[][]{{0,1},{1,1}};  
  2. public int getNthNumber1(int n) {  
  3.     if(n == 0)  
  4.         return 1;  
  5.     if(n == 1)  
  6.         return 1;  
  7.     f = pow(n,f);  
  8.       
  9. turn (int) f[1][1];  
  10. }  
  11.   
  12. private long[][] pow(int n,long[][] f){  
  13.     if(n == 1)  
  14.         return f;  
  15.           
  16.     if(n == 2){  
  17.         return fun(f,f);  
  18.     }  
  19.   
  20.     if( n % 2 == 0){//偶数  
  21.         f = pow(n/2,f);  
  22.         return fun(f, f);  
  23.     }else{  
  24.         return fun(pow(n/2,f),pow(n/2 + 1,f));  
  25.     }  
  26. }  
  27.   
  28. private long[][] fun(long[][] f,long[][] m){  
  29.     long[][] temp = new long[2][2];  
  30.     temp[0][0] = (f[0][0]*m[0][0] + f[0][1]*m[1][0])%1000000007;  
  31.     temp[0][1] = (f[0][0]*m[0][1] + f[0][1]*m[1][1])%1000000007;  
  32.     temp[1][0] = (f[1][0]*m[0][0] + f[1][1]*m[1][0])%1000000007;  
  33.     temp[1][1] = (f[1][0]*m[0][1] + f[1][1]*m[1][1])%1000000007;  
  34.     return temp;  
  35. }  

3.公式求解  时间复杂度O(1)

利用到数列的公式:an=(1/√5) * [((1+√5)/2)^n-((1-√5)/2)^n](n=1,2,3.....)


取完对数

例题如下:


这是一种模板式的方法,对于一个数a,取t=log10(a),b为log10(a)的小数部分,取10^b得到一个大于1小于10的浮点数,此数就是将原数/10直到只剩个位的数





代码1.:

#include<iostream>
#include<cmath>
using namespace std;
int f(int a)
{
	int f0=0,f1=1,f2=1;
	if(a)
	{
		for(int i=1;i<a;i++)
	{
		f2=f0+f1;
		f0=f1;
		f1=f2;
	}
	return f2;
	}
	else return 0;
}
int main()
{
	int n;double a;
	while(cin>>n)
	{
		if(n<=20)cout<<f(n)<<endl;
		else
		{
			a=-0.5*log10(5.0)+n*log10((1.0+sqrt(5.0))/2.0);
			a-=(int)a;
			a=pow(10,a);
			a*=1000;
			cout<<(int)a<<endl;
		}
	}
	return 0;

升级例题2.

点击打开链接     (涉及到矩阵求解)(极其重要)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值