兔子繁衍问题是一个经典的数学建模题目,源自13世纪意大利数学家斐波那契提出的著名数列。这个问题不仅具有理论价值,在生物学、经济学等领域也有广泛应用。题目要求我们计算在理想条件下,兔子种群数量随时间变化的规律。
假设初始有一对刚出生的兔子(第1个月),兔子成长周期如下:
我们需要计算第N个月时兔子的总对数。这个模型实际上定义了斐波那契数列:F(1)=1, F(2)=1, F(n)=F(n-1)+F(n-2)(n≥3)
通过分析兔子成长周期,可以建立递推关系:
这直接对应斐波那契数列的递推公式。理解这个关系是解决问题的关键。
最直观的解法是递归实现:
python复制def fibonacci(n):
if n == 1 or n == 2:
return 1
return fibonacci(n-1) + fibonacci(n-2)
注意:这种解法虽然简洁,但存在严重的性能问题。时间复杂度为O(2^n),当n较大时计算量呈指数级增长。
更高效的实现是使用迭代法:
python复制def fibonacci(n):
a, b = 1, 1
for _ in range(3, n+1):
a, b = b, a + b
return b
这种方法的时间复杂度为O(n),空间复杂度O(1),适合处理较大的n值。在PTA系统中,迭代法是更优的选择。
也可以使用动态规划表格存储中间结果:
python复制def fibonacci(n):
dp = [0] * (n + 1)
dp[1] = dp[2] = 1
for i in range(3, n+1):
dp[i] = dp[i-1] + dp[i-2]
return dp[n]
这种方法虽然空间复杂度为O(n),但更直观展示了动态规划的思想。
在实际编程中需要考虑非法输入:
python复制n = int(input())
if n < 1:
print("输入必须为正整数")
else:
print(fibonacci(n))
当n较大时(如n>50),结果会超出普通整型范围。在Python中不需要特殊处理,但在C/Java等语言中需要使用long或BigInteger。
对于需要多次查询的情况,可以预计算斐波那契数列:
python复制max_n = 100
fib = [1, 1]
for i in range(2, max_n):
fib.append(fib[i-1] + fib[i-2])
这样查询时可以直接返回fib[n-1],实现O(1)时间复杂度。
斐波那契数列有精确的数学表达式(比奈公式):
F(n) = (φ^n - (-φ)^(-n))/√5,其中φ=(1+√5)/2
Python实现:
python复制from math import sqrt
def fibonacci(n):
phi = (1 + sqrt(5)) / 2
return round(phi**n / sqrt(5))
注意:这种方法在n较大时会有浮点精度问题,适合理论分析而非精确计算。
更高效的O(log n)算法是利用矩阵快速幂:
python复制def matrix_mult(a, b):
return [
[a[0][0]*b[0][0] + a[0][1]*b[1][0],
a[0][0]*b[0][1] + a[0][1]*b[1][1]],
[a[1][0]*b[0][0] + a[1][1]*b[1][0],
a[1][0]*b[0][1] + a[1][1]*b[1][1]]
]
def matrix_pow(mat, power):
result = [[1,0],[0,1]] # 单位矩阵
while power > 0:
if power % 2 == 1:
result = matrix_mult(result, mat)
mat = matrix_mult(mat, mat)
power //= 2
return result
def fibonacci(n):
if n <= 2:
return 1
mat = [[1,1],[1,0]]
return matrix_pow(mat, n-1)[0][0]
这种方法适合处理极大的n值(如n>1e6),是算法竞赛中的常用技巧。
| 输入n | 预期输出 | 说明 |
|---|---|---|
| 1 | 1 | 最小边界值 |
| 2 | 1 | 基础情况 |
| 5 | 5 | 小规模测试 |
| 12 | 144 | 中等规模 |
| 30 | 832040 | 较大规模 |
python复制a, b = 1, 1
print(f"Month 1: {a}")
print(f"Month 2: {b}")
for month in range(3, n+1):
a, b = b, a + b
print(f"Month {month}: {b}")
比较递归和迭代结果是否一致,验证算法正确性。
对于大n值,检查是否出现整数溢出(在非Python语言中)。
对不同算法进行时间测试:
python复制import time
def time_test(func, n):
start = time.time()
result = func(n)
end = time.time()
return result, end-start
n = 35
print("递归:", time_test(fib_recursive, n))
print("迭代:", time_test(fib_iterative, n))
print("矩阵快速幂:", time_test(fib_matrix, n))
预期结果:递归算法耗时显著高于其他方法,体现算法选择的重要性。
错误表现:当n较大时递归版本会达到最大递归深度
解决方案:
python复制import sys
sys.setrecursionlimit(10000)
错误表现:在C/Java等语言中,n>46时int类型会溢出
解决方案:
常见错误:
正确做法:
python复制if n < 1:
return 0
elif n == 1 or n == 2:
return 1
递归算法的改进方案:
python复制from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(n):
if n <= 2:
return 1
return fibonacci(n-1) + fibonacci(n-2)
这样可以将时间复杂度从O(2^n)降到O(n),但空间复杂度为O(n)。