基础算法题——斐波那契
做题心得
这道算法题花了我几乎一天的时间才弄懂,不得不说我还是太菜了…
该算法题主要考查了对斐波那契数列的理解、矩阵与斐波那契结合、快速求幂。在看了数篇博客后我才慢慢对矩阵、快速求幂有所了解,由于是初步接触这类题型,如果有不正确的地方,欢迎大家来交流讨论。
斐波那契题目
题目分析
题目很短,乍一看很简单,不就是将每一个斐波那契数列算出来然后再把每一项的平方和累加起来,如果遇到了过大的数就求余,然后将答案再求余防止过大,这不就是简简单单的一道送分题嘛。但是我们仔细观察就会发现n的取值范围居然是1<=n<=1e18,这也太大了。如果n=1e18,按我们算法复杂度O(n),这我们就要让程序将1~1e18项的斐波那契数列全部相加,很显然肯定会超时!!那我们还能用那种普通思维去对待这道看似简单的题目吗?不行,我们需要学习新的东西,才能够解决这道题给我们留的坑。
斐波那契数列
斐波那契数列又称黄金分割数列、兔子数列。
指的是这样一个数列:1、1、2、3、5、8、13、21…在数学上,斐波那契数列以如下被递推的方法定义:F(1)=1,F(2)=1,F(n)=F(n-1)+F(n-2)其中的n>=3。
为了能够更简便地将前n项平方和计算出结果,我们将引入一种全新的计算方式(当然这种全新是对我来说)。
题目中我们要求1~n项斐波那契数列的平方和sum。
sum=a12+a22 + …+an2=an*an+1
具体证明请参照大佬讲解:斐波那契数列平方和计算公式
快速求幂
什么是快速求幂?
21000000对1e9+7取余,我们会如何计算呢?用一个循环将答案算出?这种方案效率太低,这时我们可以用快速求幂的方法将结果算出。
如果对该算法不理解的同学,我力荐他点击下面那篇博客,博客中对快速求幂算法将得清晰无比!把昨天在泥潭中的我拉上了岸,在此感谢博主的精彩解析!博客中我认为最为精华的一句话:最后求出的幂结果实际上就是在变化过程中所有当指数为奇数时底数的乘积。
快速幂算法
//若看完上面的博客,对快速求幂有了一定的理解
//你可以尝试下能否看懂这篇代码
//如果可以说明你已经基本理解了何为快速求幂
#include<stdio.h>
long long quick(long long base, long long power);
const int MOD=1e9+7;
int main()
{
long long base, power;
printf("求x为底数,y为指数的值对1e9+7取余:\nx y:");
scanf("%lld%lld", &base, &power);
printf("%lld", quick(base, power));
return 0;
}
long long quick(long long base, long long power)
{
long long result=1;
while(power)
{
if(power&1)//只有奇数才乘以底数
result=result*base%MOD;
base=base*base%MOD;
power=power>>1;
}
if(base==0){
result=0;
}
return result%MOD;
}
若看不懂上面的代码,说明对快速求幂理解不够,需要再点击上方“快速求幂算法”链接加深理解。
矩阵与斐波那契数列结合
矩阵怎么就和斐波那契数列扯上了关系?这个问题昨天一直在我脑海里“挥之不去”,终于我又遇到了一篇微信上的文章,它讲解了矩阵与斐波那契数列的关系。
简简单单一张图,将矩阵与斐波那契数列完美地结合在了一起!
能够了解到这种联系,说实在的,心里莫名激动!
矩阵与斐波那契数列结合
代码讲解
如果你已经理解了上面的全部知识点,也许你也不一定能将其中联系起来完成这道算法题。(我就是这样,也许是我太菜了吧…)
于是我又看了好多其他人的代码,发现他们喜欢用结构、映射和一些我不常用甚至不理解的表达方式(所以说看别人写的代码真的很难受)。最后我就在矩阵求斐波那契数列的代码上进行修改加入了快速求