求斐波那契数列的方法

求斐波那契数列的方法,递推循环和矩阵快速幂

前言:

我们都知道斐波那契数列指的是第三项开始,前两项之和等于第三项的值.这里罗列了两种方法来实现.

一.递推

由前言我们可以知道,斐波那契数列的递推式为:

  a [ i ] = a [ i - 1 ] + a [ i - 2 ]

所以在求斐波那契额数列第几项的值时我们可以运用数列储存每一项结果,再利用循环每一项求解,下面是代码

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	int a[1000];
	a[1] = 1;
	a[2] = 1;
	for(int i = 3; i < 1000; i ++)
	{
		a[i] = a[ i - 1 ] + a[ i - 2 ];
	}

	return 0;
}

虽然能求出结果,但是在项数高的时候结果非常大,一般会使用long long,以及对一个比较大的数取模.

二.矩阵快速幂

第一种方法虽然简单,但是在项数特别大的时候就没有办法很快的得出结果,这时我们可以使用矩阵快速幂,这个方法可以解决这种递推的问题.

我们知道斐波那契额数列每一项结果只和前两项有关.所以我们可以根据递推式写出他的转移矩阵.开始时我们的式子可以表达成如下式子

\begin{vmatrix} a[2]\\a[1] \end{vmatrix} = \begin{bmatrix} 1\\1 \end{bmatrix}

当我们乘上他的转移矩阵k

\begin{bmatrix} 1 &1 \\ 1 & 0 \end{bmatrix}

会得到

                                                               \begin{bmatrix} 2\\1 \end{bmatrix} = \begin{bmatrix} a[3]\\a[2] \end{bmatrix}

而我们要得到第四项字需要在乘一次转移矩阵.要得到第n项只需要乘上n - 2 次转移矩阵k,相当于乘上k ^ (n - 2).这时们就可以用快速幂的思想去快速求得结果,在乘以首项,就可以得到第n项的结果.

相比于正常快速幂我们只是多了一部分重载乘号.

下面结合代码

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
const long long MOD=1e9+7;// 一个比较大的质数
struct ma//定义矩阵的结构体
{
	long long a[11][11];//定义矩阵大小
	ma (){memset(a,0,sizeof(a));}//初始化矩阵所有值为0
	void set()//定义一个函数让横纵坐标相等的位置得一,
     //这种矩阵的特点是无论什么矩阵乘他都等于本身
	{
		for(int i=0;i<=11;i++)
		a[i][i]=1;
	}
	
};
ma operator*(const ma &a1,const ma &a2)//重载乘法
{
	ma res;
	for(int i=1;i<=10;i++)
	{
		for(int j=1;j<=10;j++)
		{
			for(int k=1;k<=10;k++)
			{
				res.a[i][j]+=a1.a[i][k]*a2.a[k][j]%MOD;
			}
		}
	}//矩阵乘法的规则
	return res;
}
ma qpow(ma a1,long long n)
{//和普通快速幂一样
	ma res;
	res.set();
	while(n)
	{
		if(n&1)
		{
			res=res*a1;
			
		}
		n=n>>1;
		a1=a1*a1;
	}
	return res;
}
void solve()
{
	ma trans,f;
	trans.a[1][1]=trans.a[1][2]=trans.a[2][1]=1;// 初始化转移矩阵
	f.a[1][1]=f.a[2][1]=1;//初始化首项矩阵
	long long n;
	cin >> n;
	trans=qpow(trans,n-2);
	trans=trans*f;//注意:矩阵乘法时顺序不能串
	printf("%lld\n",trans.a[1][1]%MOD);
}
int main()
{
	int t;
	cin >> t;
	while(t--)
	{
		solve();
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值