python斐波那契数列前20项_斐波那契数列变形题(Python求解)

587d37ab7f39c6032df7f17464b153df.png

上周数据团的学习群中,有个同学抛出一个用Python编写函数求解的问题,激发了近500条的讨论,下面是题目:

一个农场有一头牛,每头牛的寿命都是六年,然后每头牛在第三年和第五年都会生一头牛,问,若干年后有多少条牛。用Python进行编写函数,输入年份求解。

接下来介绍下我的解题思路:

第一步:按照题意,每年牛的数量最直接关联的是上年的牛=上一年牛龄1至5数量之和(牛龄6在本年死去)+上一年牛龄3与5数量之和(每头牛在第三年和第五年都会生一头牛),这个时候就可以把每年的牛数量与牛龄组成一个列表,这一步就是把问题拆解成最小的组成结构,然后按照这个我编写Python。

def cow_quantity(year):
    df = pd.DataFrame({'第1年':[1,0,0,0,0,0]},
                 index = ['1岁数量','2岁数量','3岁数量','4岁数量','5岁数量','6岁数量'])
    #生成第一年的数据
    for i in range(year+1):  #按照需要求的年来遍历,没一年加一列
        if i%2 == 1 and i > 1: #如果是奇数年,上一年有牛龄3与5的牛,这里我是观察到规律优化了下
            df['第{}年'.format(i)] = df.shift(1)['第{}年'.format(i-1)]
            df['第{}年'.format(i)][0] = df['第{}年'.format(i-1)][:5].sum()
        if i%2 == 0 and i > 1:  #如果是偶数年,上一年没有牛龄3与5的牛
            df['第{}年'.format(i)] = df.shift(1)['第{}年'.format(i-1)]
            df['第{}年'.format(i)][0] = 0
    return(df)
print(cow_quantity(19).sum())
cow_quantity(15)

接下来运行代码,查看输出结果看有没有需要调整的,我输出了每年的牛数量之和与每年的列表。

首先是每年的数量之和。

c7bfdd985fbb3c939be4ae536500f1f1.png

然后是列表:

149b9dcb6b56a3bfd5cd342b83989785.png

经过检测数据结果是正确的,但面临几个问题:

  1. 每次求需要年数的牛数量,这个程序都需要从头开始运算,计算量很大,如果 运算第1000年的数量之和需要比较长时间,数据再大些计算力不足以支撑运算。
  2. 只按最开始的规律编写了计算,还没有推导简化规律,直到不能推导

第二步:解决第一步遇到的问题

首先观察每年牛的数量汇总列表(即第一个图),除了没两年牛的数量是相同的没找到能解出牛数量的规律。

然后观察计算列表(即第二个图),这个时候发现每个牛龄的行数据都是一个变形后的斐波那契数列,1岁数量的行在斐波那契数列每两项中间加了一个0,下面每一行的数据都是上一行的数据右移一位得到的。这个时候我想到了可以用斐波那契数列的通项式来求得对应年数的牛数量之和。

3b697eee75c6d096b81b558aeba1fc54.png
#按照通项式写出代码
def cow_quantity_formula(year):
    import math
    if year % 2 == 0:
        n = year/2
        quantity = (1/math.sqrt(5))*((((1+math.sqrt(5))/2))**n-(((1-math.sqrt(5))/2)**n)) + (1/math.sqrt(5))*((((1+math.sqrt(5))/2))**(n-1)-(((1-math.sqrt(5))/2)**(n-1))) + (1/math.sqrt(5))*((((1+math.sqrt(5))/2))**(n-2)-(((1-math.sqrt(5))/2)**(n-2)))
    if year % 2 == 1:
        n = (year+1)/2
        quantity = (1/math.sqrt(5))*((((1+math.sqrt(5))/2))**n-(((1-math.sqrt(5))/2)**n)) + (1/math.sqrt(5))*((((1+math.sqrt(5))/2))**(n-1)-(((1-math.sqrt(5))/2)**(n-1))) + (1/math.sqrt(5))*((((1+math.sqrt(5))/2))**(n-2)-(((1-math.sqrt(5))/2)**(n-2)))
    return(int(quantity))
cow_quantity_formula(19)

推导简化后的函数求第1000年牛的数量之和用时32毫秒。

这个推导结果优点是计算速度快了,缺点是不够准确(因为通项式中的根号5不是整数)。可以在满足一些条件时使用这个方法。另外数据团中还有其他同学用其他方式编写的代码,用了最简单的计算方式,优点是计算时间快,耗费计算机资源小。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值