斐波那契数列的多种解法(含矩阵快速幂)

斐波那契数列的多种解法

斐波那契函数的定义:斐波那契数列,又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*)
解法一
利用递归的方法做
首先要确定递归的终止条件:F(0)=1,F(1)=1。只后再利用公式F(n)=F(n-1)+F(n-2)(n≥2,n∈N*)即可

#include<stdio.h> 
int f(int n)
{
	//递归终止条件 
	if(n==0) return 0;
	if(n==1) return 1;
	//递归函数 
	return (f(n-1)+f(n-2));
}

int main()
{
	int n;
	scanf("%d",&n);
	printf("%d\n",f(n));
	return 0;
}

但是经过仔细的思考发现,该递过在运行过程中会出现许多重复计算的现象,利于计算F(4)时就要算边F(2).那么有什么办法可以改善一下吗。下面我们通过添加一个数组来解决这个问题。

#include<stdio.h> 
int a[100]={0}; 
int f(int n)
{
	//递归终止条件 
	if(n==0) return 0;
	//如果已经计算过就不用再次计算了 
	if(a[n]!=0) return a[n];
	//记录下斐波那契数列的值避免重复的计算 
	a[n]=f(n-1)+f(n-2);
	return a[n];
}

int main()
{
	a[1]=1;
	int n;
	scanf("%d",&n);
	printf("%d\n",f(n));
	return 0;
}

解法二
利用循环实现

#include<stdio.h> 
int a[100]={0}; 
int f(int n)
{
	int first=0,second=1,third;
	if(n==0) return 0;
	if(n==1) return 1;
	while(n!=1){
		third=first+second;
		first=second;
		second=third;
		n--;
	} 
	return third;
}

int main()
{
	a[1]=1;
	int n;
	scanf("%d",&n);
	printf("%d\n",f(n));
	return 0;
} 

解法三
利用矩阵快速幂实现
在写代码之前我们先来了解什么是矩阵快速幂
先来看看这样一个问题如果让你求解x6的话你会怎么算呢是不是直接写成xxxxx*x呢?显然这样的话要做五次关于x的乘法。有没有一种方法可以减少运算的次数呢。
首先我们把6写成二进制的形式110则x6=x4*x2.而x4=x2*x2。我们这样我们仅仅只需要做3次乘法就可以计算出x6的值。进一步我们将之代码化如下

#include<stdio.h>
int f(int x,int e)
{
	int result=1;
	while(e!=0)
	{
		if(e&1){
			result*=x;
		}
		x*=x;
		e>>=1;
	}
	return result;
}
int main()
{
	int x,e;
	printf("请输入底数和指数:");
	scanf("%d %d",&x,&e);
	printf("%d",f(x,e));
}

那么同样的假设A为一个矩阵那么An是否可是用同样的方法来计算呢,大家可以在私下里试一试。只需要在添加一个用于计算矩阵相乘的函数就可以了。
那么该如何利用这个方法来计算斐波那契数列呢,请看下面的公式。
f[i] = 1f[i-1]+1f[i-2] f[i-1] = 1f[i-1] + 0f[i-2];

在这里插入图片描述
那么可以得到
在这里插入图片描述
就这两幅图完美诠释了斐波那契数列如何用矩阵来实现。
那么下面看下代码的实现

#include<stdio.h>
typedef struct 
{
	long long b[2][2];
}X;

X mul(X a,X b,int an,int bn,int abk)
{
	X tem; 
	int i,j,k;
	for(i=0;i<an;i++){
		for(j=0;j<bn;j++){
			tem.b[i][j]=0;
		}
	}
	for(i=0;i<an;i++){
		for(j=0;j<bn;j++){
			for(k=0;k<abk;k++){
				tem.b[i][j]=(a.b[i][k]*b.b[k][j]+tem.b[i][j]);
			}
		}
	}
	return tem;
}

long long fibornacci(long long n)
{
	if(n==1) return 1; 
	//初始化矩阵
	X res;
	res.b[0][0]=1;
	res.b[0][1]=1;
	res.b[1][0]=1;
	res.b[1][1]=0;
	//用于存放答案的矩阵
	X ans;
	ans.b[0][0]=1;
	ans.b[0][1]=1;
	ans.b[1][0]=1;
	ans.b[1][1]=1;
	n=n-2;
	while(n){
		if(n&1){
			ans=mul(ans,res,2,2,2);
		}
		res=mul(res,res,2,2,2);
		n>>=1;
	}
	X y;
	y.b[0][0]=1;
	y.b[1][0]=0;
	ans=mul(ans,y,2,1,2);
	return ans.b[0][0];
}
int main()
{
	long long n;
	scanf("%lld",&n);
	printf("%lld\n",fibornacci(n));
	return 0;
} 

好了以上便是关于斐波那契函数的几种解法,看都看都这里了确定不点一个赞,加一个关注吗。QAQ

  • 12
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值