PTA 兔子繁衍问题
题目描述
一对兔子,从出生后第3个月起每个月都生一对兔子。小兔子长到第3个月后每个月又生一对兔子。假如兔子都不死,请问第1个月出生的一对兔子,至少需要繁衍到第几个月时兔子总数才可以达到N对?
输入格式
输入在一行中给出一个不超过10000的正整数N。
输出格式
在一行中输出兔子总数达到N最少需要的月数。
输入样例
30
输出样例
9
解题
依题可知:
第一个月兔子总数为1
第二个月兔子总数仍为1
第三个月这一对兔子开始生兔子,因此兔子总数为1+1=2
第四个月兔子继续繁殖,因此总数为2+1=3
第五个月这对兔子生下的第一对兔子也开始繁殖,因此总数变为3+2=5
……
月份:1 2 3 4 5 6 ...
数量:1 1 2 3 5 8...
由上述推导可知,除了第一个月和第二个月兔子没有开始繁殖总数为1,后面每个月的总数均为前面两个月总数之和,因此可以写出以下代码:
#include<stdio.h>
int main(){int n;int a[10001];scanf("%d",&n);int sum=0;a[0]=1,a[1]=1;sum=a[0]+a[1];int i=2;//a[0],a[1]已知,因此从第三个数组开始加起while(sum<n){//兔子总数未达到要求,继续进入循环a[i]=a[i-2]+a[i-1];sum+=a[i];i++;}printf("%d",i+2);return 0;
}
错误分析
错误的累加逻辑:原代码中的sum
变量累加了所有月份的增量(即斐波那契数列的项),而实际总数应为斐波那契数列的当前项。例如,第三个月的总数应为2对,但原代码将sum
计算为1(初始值) + 2(第三个月的增量)= 3,导致错误。
月份计算错误:原代码在退出循环后,通过i
的值进行月份判断,但未正确关联数组索引与月份。正确的月份应为索引i
加1(例如,索引2对应第三个月)。
答案
这是斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N)。
这个数列的应用有很多比如:兔子繁衍问题、数字谜题、杨辉三角、黄金分割、矩形面积、自然界中的“巧合”、尾数循环等等。
修正说明
- 直接比较斐波那契项:每月总数即斐波那契数列的项
a[i]
。当a[i] >= n
时,找到所需月份。 - 调整月份输出:数组索引
i
对应的实际月份为i + 1
,确保输出正确的最小月份。 - 简化逻辑:移除不必要的
sum
累加和复杂判断,直接遍历斐波那契数列直至找到符合条件的项。
最终修改如下:
#include<stdio.h>
int main() {int n;scanf("%d", &n);if (n <= 0) {printf("0");return 0;}if (n == 1) {printf("1");return 0;}int a[10001];a[0] = 1;a[1] = 1;int i;for (i = 2; i < 10001; i++) {a[i] = a[i-1] + a[i-2];if (a[i] >= n) {printf("%d", i + 1);return 0;}}// 处理可能的数组越界情况(根据题目约束可调整数组大小)return 0;
}