本站首文,主要是斐波那契数列的讨论。
斐波那契数列,也就是兔子数列,上故事(谢谢bing):
一般而言,兔子在出生两个月后,就有繁殖能力,一对兔子每个月能生出一对小兔子来。如果所有兔子都不死:
我们不妨拿新出生的一对小兔子分析一下:
第一个月小兔子没有繁殖能力,所以还是一对
两个月后,生下一对小兔对数共有两对
三个月以后,老兔子又生下一对,因为小兔子还没有繁殖能力,所以一共是三对
我们接着往下算,就会得到形如1,1,2,3,5,8……(或0,1,1,2……)的一个数列,,也就是说,每一项都是由前两项的和得来的,得出数学上的求通项公式也是很容易的,也就是an=1/√5[(1+√5)n/2-(1-√5)n/2]这个简单的式子(推了一个晚自习),但是毕竟是一道OJ上的题目,所以我们就要用编程的角度去实现,毕竟gg说过:我们是负责想的,电脑是负责算的。
数组思想
我们不妨从最开始定义一个数组叫做fb[10000],然后人为的初始化fb[1]和fb[2],然后用一个for循环依次带入到fb[n]就可以了,但是有一个无法解决的缺点就是——数组是有大小的,相比较而言,会容易爆,上代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[30],n;
scanf("%d",&n);
a[1] = a[0] = 1;
for(int i = 2;i <= n; i++)
{
a[i] = a[i - 2] + a[i - 1];
}
printf("%d",a[n - 1]);
return 0;
}
循环思想
其实,循环的思想和数组或者接下来的递归递推思想是很像的,他在这里起到一个承上启下的作用,这就是我为什么要在这里写出他的原因.其实循环也并不难,首先函数肯定是离不开的,所以我们定义一个叫做fb的函数(注意,一定是int型的,因为要返回值),然后对于边界n=1,n=2的限定,然后从3开始循环,定义一个last1,last2和sum,使sum=last1+last2,然后使三者分别赋值就可以,在main函数里fb(n)就行了,好,上代码:
#include<bits/stdc++.h>
using namespace std;
int fb(int n)
{
if (n == 1)
{
return 1;
}
if (n == 2)
{
return 1;
}
int last1 = 1;
int last2 = 1;
int sum = 0;
for (int i = 3; i <= n; i++){
sum = last1 + last2;
last2 = last1;
last1 = sum;
}
return sum;
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d\n", fb(n));
return 0;
}
递归思想
递归的本质是自己调用自己,所以只要定义边界fb(1),fb(2),就可以了,然后return fb(n)=fb(n-1)+fb(n-2);上代码:
#include<bits/stdc++.h>
using namespace std;
int fb(int n)
{
if(n == 1)//1边界
return 1;
if(n == 2)//2边界
return 1;
else
return fb(n - 1) + fb(n - 2);//递归式
}
int main()
{
int k;
scanf("%d",&k);
fb(k);
printf("%d\n",fb(k));
return 0;
}
递推思想
关于递推和递归,其实就本问题而言,表达式是一样的,直接看代码吧:
#include<bits/stdc++.h>
using namespace std;
int fb(int n)
{
int f0 = 0,f1 = 1,f;
if(n == 0 || n == 1)
{
return n;
}
for(int i = 2;i <= n; i++)
{
f = f0 + f1;
f0 = f1;
f1 = f;
}
return f;
}
int main()
{
int n;
scanf("%d",&n);
printf("%d\n",fb(n));
return 0;
}
递归的优化(Half an Hour)
不难看出,上面的时间复杂度还是太高,所以我又对递归进行了优化,降低到了线性级别,是属于灵感迸发,上代码:
#include<bits/stdc++.h>
const int MAX=101;//上网搜的,否则爆
using namespace std;
int a[MAX];
int fb(int n)
{
if(a[n] != -1)
return a[n];
else
{
a[n] = fb(n - 1) + fb(n - 2);
return a[n];
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i = 0;i <= MAX - 1; i++)
{
a[i] =- 1;
}
a[0] = 0;
a[1] = 1;
cout << fb(n);
return 0;
}
高精度算法
感谢老版一本通吧,上代码,这个真的不是自己做的:
#include<bits/stdc++.h>
using namespace std;
char sum[1200];
int s = 0,m = 0,n;
int main()
{
scanf("%d",&n);
string s1,s2;
int a[1200],b[1200];
int he,i;
s1 = "0";
s2 = "1";
for(m = 2;m < n+1; m++)
{
memset(a,0,sizeof a);
memset(b,0,sizeof b);
a[0] = s1.length();
for(i = 1;i <= a[0]; i++)
{
a[i] = s1[a[0] - i] - '0';
}
b[0] = s2.length();
for(i = 1;i <= b[0]; i++)
{
b[i] = s2[b[0] - i] - '0';
}
he = (a[0] > b[0] ? a[0] : b[0]);
for(i = 1;i <= he; i++)
{
a[i] += b[i];
a[i+1] += a[i]/10;
a[i] %= 10;
}
he++;
while((a[he] == 0) && (he > 1))
he--;
for(i = he,s = 0;i >= 1; i--,s++)
{
sum[s] = a[i] + '0';
}
s1 = s2;
s2 = sum;
}
cout << s2;
return 0;
}
总结
斐波那契数列作为函数的入门题型,虽说好想,但是优化起来还是很难的,而且他的变式也是很多,所以说掌握还是很重要的!
公元2023年11月27日
宇宙-拉尼亚凯亚超星系团-室女座星系团-本星系群-银河系-猎户臂-古尔德带-本地泡-本星际云-奥尔特云-太阳系第三行星-地球-中华人民共和国-辽宁省-大连市-中山区——著
本文介绍了斐波那契数列的理论背景,以及如何通过数组、循环、递归、递推等编程方法计算数列,重点讲解了递归优化以提高效率,同时提及了高精度算法的应用。
736

被折叠的 条评论
为什么被折叠?



