题干:
思路:
首先这个题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))
——————————————————————————————————————————————————
对于这道题我的探究就差不多到此,毕竟是一道水题,没必要想太多~