先熟悉一下斐波那契数列
比如下边这个数列
0,1,1,2,3,5,8,13,21...
在递归上这个方法定义为 F(0)=0;F(1)=1;F(n)=F(n-1)+F(n-2);
接下来我们推一下斐波那契数列的通项公式(待定系数法)
设常数r,s使得
F(n)-rF(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(3)-r*F(2)=s*[F(2)-r*F(1)]
由上面的式子可得 F(n)-r*F(n-1)=s^(n-2)*[F(2)-r*F(1)];
则由上面公式可以求得F(n)=(s^n-r^n)/(s-r)
由r+s=1 -rs=1
得 s=(1+sqrt(5))/2 s=(1-sqrt(5))/2
则F(n)=sqrt(5)/5[s^n-r^n]
下面给出一个例题加以分析
题目描述
其中a、b是满足以下两个条件的常数:
给定f0, f1, a, b和 n,请你写一个程序计算F(n),可以假定F(n)是绝对值不超过109的整数(四舍五入)。
输入
输出
样例输入
0 1 1 1 20
样例输出
6765
根据上边笔者给出的公式推论 可以得到这个题中的公式推论
F(n)=k^n*(f(1)-m*f(0))-m^n(f(1)-k*f(0))/(k-m)
其中m=(a+sqrt(a^2+4b))/2,k=(a-sqrt(a^2+4b))/2
附上实现代码(在下边代码中笔者使用的是递归求幂次 读者也可使用快速幂来求解)
#include<iostream>
#include<math.h>
#include<cstdio>
using namespace std;
int n;
double f0,f1,a,b,m,k,ans;
/*在c/c++中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了inline修饰符,表示为内联函数。
栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间。*/
inline double s(double a,int b)
{
if(b == 0)
return 1;
double k = s(a , b/2);
if(b % 2 == 0)
return k * k;
else
return k * k * a;
}
int main()
{
cin>>f0>>f1>>a>>b>>n;
if(f0 == 0 && f1 == 0)
{
printf("0");
return 0;
}
m = (a+sqrt(a*a+4*b))/2;
k = (a-sqrt(a*a+4*b))/2;
ans = (s(k,n)*(f1-m*f0)-s(m,n)*(f1-k*f0))/(k-m);
printf("%.0lf\n",ans);
return 0;
}