top1编程
← 返回题目
题解

兔子繁殖问题

1 条题解

  • 0
    @ 2026-8-6 0:54:26

    P4750 兔子繁殖问题(入门)

    解题思路

    这个故事说的是一对"兔子夫妻"的家族壮大过程。年初的时候,围栏里只有 1 对小兔子。按照题目规定:小兔子只要长 1 个月就能变成大兔子,而大兔子每个月都会生出一对新的小兔子。我们要算出到年底(也就是第 12 个月底)一共有多少对兔子。

    我们可以把每个月底围栏里的兔子对数记下来,看看规律:

    • 第 1 个月底:只有年初那 1 对小兔子,共 1 对;
    • 第 2 个月底:小兔子长成了大兔子,还没生宝宝,仍然只有 1 对;
    • 第 3 个月底:大兔子生出一对小兔子,变成 2 对;
    • 第 4 个月底:原来的大兔子又生一对,第 3 个月出生的小兔子也长大了,共 3 对。

    你会惊喜地发现:从第 3 个月开始,每个月的对数 = 上个月的对数 + 上上个月的对数。这就是著名的斐波那契数列!用数学式子写就是 f(n) = f(n-1) + f(n-2),其中 f(1) = 1,f(2) = 1。

    为什么这个式子是"对"的呢?可以把问题反过来想:第 n 个月底的对数,等于"上个月底就已经在的对数"加上"这个月刚刚出生的小兔子对数"。而这个月出生的小兔子,正好是上上个月底那些兔子生出来的,数量就等于 f(n-2)。所以 f(n) = f(n-1) + f(n-2)。

    这道题输入为空,我们只需要在程序里递归求出 f(12) 并输出即可。递归函数有两个"出口":n 等于 1 或 2 时直接返回 1,其他情况就调用自己,把规模变小。最终到年底一共是 144 对兔子。

    参考代码

    // 兔子繁殖问题:年初1对小兔,小兔1个月长大成大兔,大兔每月生1对小兔,递归求到年底对数
    #include <iostream>
    using namespace std;
    
    // 递归求第n个月底共有多少对兔子:f(n)=f(n-1)+f(n-2)
    int f(int n) {
        if (n == 1) return 1;   // 第1个月底:只有年初那1对小兔子
        if (n == 2) return 1;   // 第2个月底:小兔刚长成大兔,还没生小兔,仍1对
        return f(n - 1) + f(n - 2);   // 上个月的总对数 + 这个月新出生的小兔对数
    }
    
    int main() {
        cout << f(12) << endl;   // 年初到年底正好12个月
        return 0;
    }
    

    复杂度分析

    递归函数 f(n) 会调用 f(n-1) 和 f(n-2),调用关系像一棵树一样向下展开,如果不做优化,总共大约要调用 2^n 次。这里 n 只有 12,2^12 = 4096 次,运行时间 O(2^n) 完全没问题。空间上,递归的最大深度是 n,也就是 12 层,占用 O(n) 的栈空间。程序最后输出 f(12) = 144,这就是到年底围栏里兔子的对数。

    • 1