斐波那契数列
斐波那契数列
一、简介
斐波那契数列(Fibonacci),又称黄金分割数列,由数学家斐波那契最早以“兔子繁殖问题”引入,推动了数学的发展。故斐波那契数列又称“兔子数列”。
斐波那契数列指这样的数列:1,1,2,3,5,8,13,……,前两个数的和等于后面一个数字。这样我们可以得到一个递推式,记斐波那契数列的第i项为F i,则F i=F i-1+F i-2.
兔子繁殖问题指设有一对新生的兔子,从第三个月开始他们每个月都生一对兔子,新生的兔子从第三个月开始又每个月生一对兔子。按此规律,并假定兔子没有死亡,10个月后共有多少个兔子?
这道题目通过找规律发现答案就是斐波那契数列,第n个月兔子的数量是斐波那契数列的第n项。
二、性质
如果要了解斐波那契数列的性质,必然要先知道它的通项公式才能更简单的推导出一些定理。那么下面我们就通过初等代数的待定系数法计算出通项公式。
令常数p,q满足F n-pF n-1=q(F n-1-pF n-2)。则可得:
F n-pF n-1=q(F n-1-pF n-2)
=q2(F n-2-pF n-3)
=…=q n-2(F2-pF1)
又∵F n-pF n-1=q(F n-1-pF n-2)
∴F n-pF n-1=qF n-1-pqF n-2
F n-1+F n-2-pF n-1-qF n-1+pqF n-2=0
(1-p-q)F n-1+(1+pq)F n-2=0
∴p+q=1,pq=-1是其中的一种方程组
∴F n-pF n-1= q n-2(F2-pF1)=q n-2(1-p)=q n-1
F n=q n-1+pF n-1=q n-1+p(q n-2+p(q n-3+…))=q n-1+pq n-2+p2q n-3+…+p n-1
不难看出,上式是一个以p/q为公比的等比数列。将它用求和公式求和可以得到:
而上面出现了方程组p+q=1,pq=-1,可以得到p(1-p)=-1,p2-p-1=0,这样就得到了一个标准的一元二次方程,配方得p2-p+0.25=1.25,(p-0.5)2=1.25,p=±√1.25+0.5。随意取出一组解即可:
这就是著名的斐波那契数列通项公式。有了它,斐波那契数列的一些性质也不难得出了。
比如斐波那契数列相邻两项的比值趋向于黄金分割比,即:
根据斐波那契数列通项公式,可以得到
因为n是趋向于正无限的,因此我们可以知道:
那么我们就可以把分子和分母的第二项同时省略掉,即
这就是斐波那契数列的魅力之一——它和黄金分割比有密切的关系。下面将给出斐波那契数列的几个性质及其证明。
1)F1+F2+F3+...+F n=F n+2-1
证明:原式=(F3-F2)+(F4-F3)+...+(F n+2-F n+1)=F n+2-1.
2)F1+F3+F5+...+F2n+1=F2n+2
证明:原式=F2+(F4-F2)+(F6-F4)+...+(F2n+2-F2n)=F2n+2
3)F12+F22+...+F n2=F n F n+1
证明:利用数学归纳法,显然n=1时满足,下面证明若n=k时满足,n=k+1时也满足.
已知F12+F22+...+F n2=F n F n+1,F12+F22+...+F n+12=F n F n+1+F n+12=(F n+1+F n)F n+1=F n+1F n+2,因此n+1后仍然满足.上述公式成立.
4)F1F2+F2F3+...+F n F n+1=(F n+22-F n F n+1-1)/2
证明:数学归纳法,n=1时满足.已知F1F2+F2F3+...+F n F n+1满足,那么
F1F2+F2F3+...+F n F n+1+F n+1F n+2=(F n+22-F n F n+1-1)/2+F n+1F n+2
=(F n+22-F n F n+1+2F n+1F n+2-1)/2=[(F n+22+2F n+1F n+2+F n+12)- F n F n+1-F n+12-1]/2
=(F n+32-F n+1F n+2-1)/2,因此上式成立.
5)F n2=F n-1F n+1+(-1)n+1
证明:数学归纳法,n=2时满足.已知前面的n都满足,那么
F n2=F n-12+F n-22+2F n-2F n-1=F n-12+F n-3F n-1+(-1)n-1+2F n-2F n-1=F n-1F n+F n-12+(-1)n-1
=F n-1F n+1+(-1)n+1,因此上式成立.
6)F n+m=F m-1F n+F m F n+1(n>m>1)
证明:利用通项公式,设α=,β=1-α=
注意到1/α+α=sqrt(5)=1/β+β,1/α+β=0=1/β+α,上式就变成了
这就是上述公式的证明.
三、斐波那契数列与自然
斐波那契数列中的斐波那契数会经常出现在我们的眼前——比如松果、凤梨、树叶的排列、某些花朵的花瓣数(典型的有向日葵花瓣),蜂巢,蜻蜓翅膀,超越数e(可以推出更多),黄金矩形、黄金分割、等角螺线,十二平均律等。
斐波那契数还可以在植物的叶、枝、茎等排列中发现。例如,在树木的枝干上选一片叶子,记其为数0,然后依序点数叶子(假定没有折损),直到到达与那些叶子正对的位置,则其间的叶子数多半是斐波那契数。叶子从一个位置到达下一个正对的位置称为一个循回。叶子在一个循回中旋转的圈数也是斐波那契数。在一个循回中叶子数与叶子旋转圈数的比称为叶序(源自希腊词,意即叶子的排列)比。多数的叶序比呈现为斐波那契数的比。
图为斐波那契弧线。
关于递推式的拓展研究
一、错位排列问题
有n个数,求有多少种排列使这n个数都不在原来的位置上。
比如n=2时,有一种排列。
设f(n)表示n个数的错位排列数量,分两种情况讨论:
1.第n个数在第p(p≠n)个数的位置上,第p个数在第n个数的位置上,则此时共有f(n-2)
种选择。由于p有(n-1)种值,则总共有(n-1)f(n-2)种排列方法;
2.否则,共有(n-1)f(n-1)种排列方法。
综上所述,f(n)=(n-1)(f(n-1)+f(n-2)),f(1)=0,f(2)=1。那这个数列的通项公式是什么呢?直接对这个数列不好进行操作,可以转化一下。设错位排列的概率函数为g(n),其中
g(1)=0,g(2)=0.5。在f(n)的递推式两边同时除以n!即可得到。
两边同时乘n得到
ng(n)=(n-1)g(n-1)+g(n-2)
n(g(n)-g(n-1))=g(n-2)-g(n-1)
注意到e-1的泰勒展开式跟它好像有点像,是
因此有如下的等式:
同时,我们也可以得到了函数f的通项公式为:
这就是一些关于错位排序的性质。
二、类斐波那契数列的研究
我们知道斐波那契数列递推式为f(n)=f(n-1)+f(n-2),那么假如有更多项呢?
假设f(n)=f(n-1)+f(n-2)+f(n-3),其中f(1)=f(2)=f(3)=1.我们暂时称这个数列为类斐波那契数列,那么它的通项公式又如何呢?
令a,b,c满足f(n)+af(n-1)+bf(n-2)=c(f(n-1)+af(n-2)+bf(n-3))
则得到c-a=1,ac-b=1,bc=1,消元得c3-c2-c-1=0,利用牛顿迭代可以计算出c=1.83928675521416……,则a=0.83928675521416……,b=0.54368901269208……
所以f(n)+af(n-1)+bf(n-2)=c n-3(1+a+b),记t=1+a+b,两边同时除以c n构造更多的常数项:
为了方便,我们记,则:
令p,q,r满足g(n)-pg(n-1)-q=r(g(n-1)-pg(n-2)-q),则得到:
这个方程会发现没有实数解,于是我们只能使用复数了:
p=-0.228...-0.32963360796702 (i)
q=0.297...+0.863 (i)
r=-0.228...+0.32963360796702 (i)
继续上面的递推式,则有g(n)-pg(n-1)-q=r n-2(g(2)-pg(1)-q)。记T= g(2)-pg(1)-q,则:
g(n)=pg(n-1)+r n-2T+q=p(pg(n-2)+r n-3T+q)+r n-2T+q
=p n-1g(1)+p n-2T+p n-3rT+…+r n-2T+q+pq+…+p n-2q
因此也就可以得到f的递推式了:
不难得到,t=2.38297576790624…,T=0.12876722129781…+0.101…i。
递推式中的c,p,q,t,T都是常数,但除了c以外都是复数,因此计算上会比较困难。在附录中附上C++的程序,附复数计算的模板和使用递推式计算类斐波那契数列的程序。
三、递推式和矩阵
如果对于每个线性递推式都要先计算它的通项公式才能够快速地得到某一项,那这个方法太过于复杂了。于是我们可以使用矩阵来加速递推。
比如斐波那契数列的递推式也可以写成:
因此就有如下结果:
其中矩阵的幂次方可以使用快速幂算法在O(logn)的时间内解决,因此我们就可以在O(logn)的时间内计算出斐波那契数列的第n项(排除高精度的时间),且精度要比虚数和小数精确的多。
附录
利用通项公式计算类斐波那契数列的代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const double EPS = 1E-15;
struct Complex{
double a, b;//num=a+bi
Complex& operator=(const Complex& c){
a = c.a;
b = c.b;
return *this;
}
Complex(){
a =
b = 0;
}
Complex(double t1, double t2 = 0){
a = t1;
b = t2;
}
Complex operator+(const Complex& c) const {
return Complex(a + c.a, b + c.b);
}
Complex operator-(const Complex& c) const {
return Complex(a - c.a, b - c.b);
}
Complex operator*(const Complex& c) const {
double ta = a * c.a - b * c.b;
double tb = b * c.a + a * c.b;
return Complex(ta, tb);
}
Complex operator/(const Complex& c) const {
Complex t = c;
t.b = -t.b;
t = (*this) * t;
double div = c.a * c.a + c.b * c.b;
t.a /= div;
t.b /= div;
return t;
}
bool operator==(const Complex& c) const {
return fabs(a - c.a) + fabs(b - c.b) < EPS;
}
bool operator!=(const Complex& c) const {
return !((*this) == c);
}
Complex operator+(double c) const { return (*this) + Complex(c); } Complex operator-(double c) const { return (*this) - Complex(c); } Complex operator*(double c) const { return (*this) * Complex(c); } Complex operator/(double c) const { return (*this) / Complex(c); }
void print(){ printf("%.14lf+%.14lfi\n", a, b); }
};
Complex csqrt(const Complex& c){
Complex r = Complex(1, 1), t = Complex();
while (r != t){
t = r;
r = r - (r * r - c) / 2 / r;
}
return r;
}
Complex cpow(Complex c, int e){
Complex res = Complex(1, 0);
for (; e; e >>= 1){
if (e & 1) res = res * c;
c = c * c;
}
return res;
}
int main(){
double c = 2, t = 0;
while (fabs(c - t) > EPS){
t = c;
c -= (c * c * c - c * c - c - 1) / (3 * c * c - 2 * c - 1);
}
double a = c - 1, b = 1 / c;
printf("%.14lf\n", 1 + a + b);
t = 1 + a + b;
Complex r = (csqrt(Complex(a * a / c / c - 4 * b / c / c)) - a / c) / 2;
r.print();
Complex p = Complex(-a / c) - r, q = Complex(t / c / c / c) / (Complex(1) - r);
p.print(), q.print();
Complex T = Complex(1 / c / c) - Complex(1 / c) * p - q;
T.print();
int n = 7;
scanf("%d", &n);
Complex res = cpow(Complex(c), n) * (cpow(p, n - 1) / Complex(c) + T * (cpow(r, n - 1) - cpow(p, n - 1)) / (r - p) + (q * cpow(p, n - 1) - q) / (p - Complex(1)));
res.print();
system("pause");
return 0;
}