第十二周项目3-用递归方法求解(二)
编制递归函数fib(int n)返回第n个Fibnacci数,以此输出Fibnacci序列的第20个数
关于Fibnacci:
Fibnacci数列又称斐波那契数列和黄金分割数列,指的是这样一个数列:1、1、2、3、5、8、13、21、……在数学上,斐波纳契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=F(n-1)+F(n-2)(n>=2,n∈N*)在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从1963起出版了以《斐波纳契数列季刊》为名的一份数学杂志,用于专门刊载这方面的研究成果。
递推公式
斐波那契数列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...[1]
如果设F(n)为该数列的第n项(n∈N*),那么这句话可以写成如下形式:[1]
显然这是一个线性递推数列。[1]
通项公式
(如上,又称为“比内公式”,是用无理数表示有理数的一个范例。)
注:此时a1=1,a2=1,an=a(n-1)+a(n-2)(n>=3,n∈N*)
通项公式推导
方法一:利用特征方程(线性代数解法)
线性递推数列的特征方程为:
X^2=X+1
解得
X1=(1+√5)/2, X2=(1-√5)/2.
则F(n)=C1*X1^n + C2*X2^n
∵F(1)=F(2)=1
∴C1*X1 + C2*X2=C1*X1^2 + C2*X2^2=1
解得C1=1/√5,C2=-1/√5
∴F(n)=(1/√5)*{[(1+√5)/2]^n - [(1-√5)/2]^n}【√5表示根号5】
方法二:待定系数法构造等比数列1(初等代数解法)
设常数r,s。
使得F(n)-r*F(n-1)=s*[F(n-1)-r*F(n-2)]。
则r+s=1, -rs=1。
n≥3时,有。
F(n)-r*F(n-1)=s*[F(n-1)-r*F(n-2)]。
F(n-1)-r*F(n-2)=s*[F(n-2)-r*F(n-3)]。
F(n-2)-r*F(n-3)=s*[F(n-3)-r*F(n-4)]。
……
F⑶-r*F⑵=s*[F⑵-r*F⑴]。
联立以上n-2个式子,得:
F(n)-r*F(n-1)=[s^(n-2)]*[F⑵-r*F⑴]。
∵s=1-r,F⑴=F⑵=1。
上式可化简得:
F(n)=s^(n-1)+r*F(n-1)。
那么:
F(n)=s^(n-1)+r*F(n-1)。
= s^(n-1) + r*s^(n-2) + r^2*F(n-2)。
= s^(n-1) + r*s^(n-2) + r^2*s^(n-3) + r^3*F(n-3)。
……
= s^(n-1) + r*s^(n-2) + r^2*s^(n-3) +……+ r^(n-2)*s + r^(n-1)*F⑴。
= s^(n-1) + r*s^(n-2) + r^2*s^(n-3) +……+ r^(n-2)*s + r^(n-1)。
(这是一个以s^(n-1)为首项、以r^(n-1)为末项、r/s为公比的等比数列的各项的和)。
=[s^(n-1)-r^(n-1)*r/s]/(1-r/s)。
=(s^n - r^n)/(s-r)。
r+s=1, -rs=1的一解为 s=(1+√5)/2,r=(1-√5)/2。
则F(n)=(√5/5)*{[(1+√5)/2]^n - [(1-√5)/2]^n}。
方法三:待定系数法构造等比数列2(初等代数解法)
已知a1=1,a2=1,an=a(n-1)+a(n-2)(n>=3),求数列{an}的通项公式。
解 :设an-αa(n-1)=β(a(n-1)-αa(n-2))。
得α+β=1。
αβ=-1。
构造方程x^2-x-1=0,解得α=(1-√5)/2,β=(1+√5)/2或α=(1+√5)/2,β=(1-√5)/2。
所以。
an-(1-√5)/2*a(n-1)=(1+√5)/2*(a(n-1)-(1-√5)/2*a(n-2))=[(1+√5)/2]^(n-2)*(a2-(1-√5)/2*a1)`````````1。
an-(1+√5)/2*a(n-1)=(1-√5)/2*(a(n-1)-(1+√5)/2*a(n-2))=[(1-√5)/2]^(n-2)*(a2-(1+√5)/2*a1)`````````2。
由式1,式2,可得。
an=[(1+√5)/2]^(n-2)*(a2-(1-√5)/2*a1)``````````````3。
an=[(1-√5)/2]^(n-2)*(a2-(1+√5)/2*a1)``````````````4。
将式3*(1+√5)/2-式4*(1-√5)/2,化简得an=(1/√5)*{[(1+√5)/2]^n - [(1-√5)/2]^n}。
方法四:母函数法。
对于斐波那契数列{a(n)},有a(1)=a(2)=1,a(n)=a(n-1)+a(n-2)(n>2时)
令S(x)=a(1)x+a(2)x^2+……+a(n)x^n+……。
那么有S(x)*(1-x-x^2)=a(1)x+[a(2)-a(1)]x^2+……+[a(n)-a(n-1)-a(n-2)]x^n+……=x
.因此S(x)=x/(1-x-x^2).
不难证明1-x-x^2=-[x+(1+√5)/2][x+(1-√5)/2]=[1-(1-√5)/2*x][1-(1+√5)/2*x].
因此S(x)=(1/√5)*{x/[1-(1+√5)/2*x]-x/[1-(1-√5)/2*x]}.
再利用展开式1/(1-x)=1+x+x^2+x^3+……+x^n+……
于是就可以得S(x)=b(1)x+b(2)x^2+……+b(n)x^n+……
其中b(n)=(1/√5)*{[(1+√5)/2]^n - [(1-√5)/2]^n}.
因此可以得到a(n)=b(n)==(1/√5)*{[(1+√5)/2]^n - [(1-√5)/2]^n}
运行代码:
/* *Copyright (c) 2014,烟台大学计算机学院 *All gight reserved. *文件名称:temp.cpp *作者:邵帅 *完成时间:2014年11月15日 *版本号:v1.0 */ #include<iostream> using namespace std; int fib(int n); int main() { cout<<fib(20)<<endl; return 0; } int fib(int n) { int sum=0; if (n==1) return 0; else if (n==2) return 1; else { sum=fib(n-1)+fib(n-2); return sum; } }
运行结果:
输入一个整数n,要求输出对应的二进制形式
二进制整数n转换为二进制的方法是“除2取余法”,即将n除以2后得到的余数,由后到前“串”起来,得到对应的二进制数,如图。
运行代码:
/* *Copyright (c) 2014,烟台大学计算机学院 *All gight reserved. *文件名称:temp.cpp *作者:邵帅 *完成时间:2014年11月15日 *版本号:v1.0 */ #include <iostream> using namespace std; void dec2bin(int n); int main() { int n; cout<<"请输入一个整数:"; cin>>n; cout<<n<<"对应的二进制形式为:"; dec2bin(n); cout<<endl; return 0; } void dec2bin(int n) { int m; if (n==0) return; else { m=n%2; dec2bin(n/2); cout<<m; } }运行结果:
心得:关于递归函数的使用,真的是考验逻辑性的时候到了,不仅看到一个程序需要构建出它的运行方式,还要勾勒出它每一步的运行轨迹,才能正确的使用递归函数,最重要的,还是逻辑性吧。
@ Mayuko