Python刷OJ———蓝桥杯历年(水题)母牛问题

题干:

在这里插入图片描述

思路:

首先这个题n小于55,数据真的小,普通的递归可以解决
不妨把牛分为四个等级:

f1:小牛一级
f2:小牛二级
f3:小牛三级
f4:成年母牛

F(N)表示第N年牛的数量, fx(N)表示第N年三级小牛的数量

(1)那么显然,F(N) = F(N - 1) + f4(N - 1) + f3(N - 1) ,这是因为f3牛下一年就要生产了,所以增加数量是原本有的f4加上f3的数量

(2)

  • f4(N - 1)是上一年的f4+ 上一年f3牛,也就是f4(N - 1) = f4(N - 2) + f3(N - 2)

  • f3(N - 1)牛是由上一年f2牛进化而来,也就是f3(N - 1) = f2(N - 2)

    综合上面两个以及(1),得到:F(N) = F(N - 1) + f4(N - 2) + f3(N - 2) + f2(N - 2)

(3)再根据上述进化理论推导一次

  • f4(N - 2) = f4(N - 3) + f3(N - 3)

  • f3(N - 2) = f2(N - 3)

  • f2(N - 2) = f1(N - 3)

    综合上面,得到:F(N) = F(N - 1) + f4(N - 3) + f3(N - 3) + f2(N - 3) + f1(N - 3)

    而又某一年的牛首先等于各等级牛数量的和!!

    于是:F(N) = F(N - 1) + F(N - 3)

推导完毕

————————————————————————————————————————————————

代码1:根据子结构,直接递归就行
def cow(n):
    print(n)
    if n <= 3:
        return n
    return cow(n - 1) + cow(n - 3)


while True:
    d = int(input())
    if d == 0:
        break
    print(cow(d))

看起来多么的简洁易懂啊对吧,实际上电脑快算炸了!!!极其不推荐这种方法!!!
也可坑是我才疏学浅,不懂得优化,反正我是不知道怎么把这个优化成尾递归。。欢迎大佬的改进意见
——————————————————————————————————————————————————

代码2:

直接用矩阵模拟每一年的增长情况,结合快速幂(不懂快速幂的自行百度)

这总算法虽然很清晰,但是实际上因为n最大才55,所以这种方法在速度上的优势完全体现不出来

而对于斐波那契系列的题,这种方法却是终极大法,比如算第100万个斐波那契数,别的方法起码要以分钟来计算时间,而矩阵加快速幂仅仅不到一秒!
(感兴趣可以看:https://blog.csdn.net/CxsGhost/article/details/103832939


我测试了2万个数据的一次性输入,完全可以在一秒内完成,对付这道题足矣:

import numpy as np


def cow(n):
    f4 = 1
    f3 = 0
    f2 = 0
    f1 = 0
    matrix_1 = np.array([[f4],
                         [f3],
                         [f2],
                         [f1]], dtype=np.int64)
    matrix_2 = np.array([[1, 1, 0, 0],
                         [0, 0, 1, 0],
                         [0, 0, 0, 1],
                         [1, 1, 0, 0]], dtype=np.int64)
    n = n - 1
    while n != 1:  # 快速幂部分
        if n % 2 == 0:
            matrix_2 = np.dot(matrix_2, matrix_2)
            n /= 2
        elif n % 2 == 1:
            matrix_1 = np.dot(matrix_2, matrix_1)
            matrix_2 = np.dot(matrix_2, matrix_2)
            n = (n - 1) / 2
    matrix_1 = np.dot(matrix_2, matrix_1)
    return np.sum(matrix_1)


data = []
while True:
    d = int(input())
    if d == 0:
        break
    data.append(d)
result = map(cow, data)
for r in result:
    print(r)

——————————————————————————————————————————————————

代码3:

这也是一种直接模拟增长的方法,如果你看懂了我之前的推导,那你一定读的懂下面的函数

用列表的三个元素分别代表:

  • F(N - 2)
  • F(N - 1)
  • F(N)

然后一年年的累加。
这个代码更适合这道题,我试了20万个数据的一次性输入
本段代码用时约3s, 而矩阵模拟约6秒(因为n比较小,快速幂算法反而拖慢了速度,去掉直接乘或许更快。)

def cow(n):
    middle = [2, 3, 4]
    if n == 1:
        return 1
    elif n == 2:
        return 2
    elif n == 3:
        return 3
    elif n == 4:
        return 4
    else:
        for each in range(5, n+1):
            middle.append(middle[0] + middle[2])
            middle.pop(0)
        return middle[2]


put = []
while True:
    d = int(input())
    if d == 0:
        break
    put.append(d)
for r in put:
    print(cow(r))

——————————————————————————————————————————————————

对于这道题我的探究就差不多到此,毕竟是一道水题,没必要想太多~

发布了34 篇原创文章 · 获赞 106 · 访问量 4612

猜你喜欢

转载自blog.csdn.net/CxsGhost/article/details/104150547