Fibonacci引申的一个问题

来源:互联网 发布:武媚娘传奇知乎 编辑:程序博客网 时间:2024/04/30 14:02

题目就是这样的,原题中是扩展的Fibonacci数列,但是为了简化问题,我就把题目中的X,Y都置1了。简单的说就是取一个Fibonacci数列,两个数相乘,左边那个从F0取到Fn,右边那个从Fn取到F0(图片中的F0*F1应改为F0*Fn)。不能使用数组和递归,说实话,用递归怎么解决我也还没思考过。

首先我自己写了个程序,没想到的是和作者的解法完全不一样。其实我的想法还是比较简单的Fibonacci的递推式是Fn=Fn-1+Fn-2,那么在知道Fn和Fn-1的情况下就可以通过Fn-2=Fn-Fn-1求得Fn-2.从题目中的形式来看是从数列的两边取数,然后往中间逼近。现在逆向思维一下,如果我之前已经知道数列中间的几个数字,我同样可以往两边递推。所以在程序开始的时候,我先要求得F(n/2)然后给往左递推的两个数字赋值,和往右递推的两个数字赋值。这时数列中数字的个数是奇和偶的情况可能要做些微的调整。此时我已经能够分别从数列的左侧和右侧得到对应的数字了,那么问题也就可以解决了。具体的一些细节请参见源代码吧。

unsigned long EX_FIB(unsigned long n){    unsigned long   F1=1,F2=1,temp,F3,F4,ans=0;    int i;    for(i=1;i<n/2;i++)   //找到数列的中间的那个数    {        temp=F2;        F2=F1+F2;        F1=temp;    }    if(n&0x01)     //若为奇数    {        F3=F1+F2;        F4=F2+F3;        ans=F3*F2*2+F1*F4*2;        for(i=0;i<n/2-1;i++)//从中间向两边扩展数列,保存至F2        {            temp=F1;            F1=F2-F1;            F2=temp;            temp=F4;            F4=F3+F4;            F3=temp;            ans+=F4*F1*2;        }        return ans;    }    else    {        ans=F2*F2;        F3=F1+F2;        F4=F3+F2;        temp=F1;        F1=F2-F1;        F2=temp;        ans+=F1*F4*2+F2*F3*2;        for(i=0;i<n/2-2;i++)        {            temp=F1;            F1=F2-F1;            F2=temp;            temp=F4;            F4=F3+F4;            F3=temp;            ans+=F4*F1*2;        }        return ans;    }}

但是之后看作者的解答之后,发现他的解法和我完全不同。当然还是依旧比我简洁很多很多。作者的想法其实有点类似于递归,将有n个数字的式子看成一个整体,然后在由n+1个数字的序列的时候利用之前的式子。当然,其中用到了一些数学的推算,使式子更易于用程序语言来编写,下面就贴上推导过程吧~



其实最终得到的式子就是An+1=(An-1)+An+Fn+(Fn+1),在写程序中只要保存An-1和An,Fn+Fn+1,并且随着n的增大,不断更新即可。其中用到的核心思想我觉得还是递归吧,由已经得到的小规模问题的解得出更大规模的问题的解,不断重复达到目标。这也是计算机最擅长做的大笑大笑大笑

0 0