先熟悉一下斐波那契数列
比如下边这个数列
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]
下面给出一个例题加以分析
题目描述
考虑以下定义在非负整数n上的递归关系:
其中a、b是满足以下两个条件的常数:
给定f0, f1, a, b和 n,请你写一个程序计算F(n),可以假定F(n)是绝对值不超过109的整数(四舍五入)。
其中a、b是满足以下两个条件的常数:
给定f0, f1, a, b和 n,请你写一个程序计算F(n),可以假定F(n)是绝对值不超过109的整数(四舍五入)。
输入
输入文件一行依次给出5个数,f0 ,f1,a,b和n,f0,f1是绝对值不超过109 ,n是非负整数,不超过109。另外,a、b是满足上述条件的实数,且|a|,|b|≤106 。
输出
一行,F(n)的值
样例输入
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; }