Fibonacci引申的一个问题

题目就是这样的,原题中是扩展的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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值