题目
输入格式:
输入在一行中给出一个不超过10000的正整数N。
输出格式:
在一行中输出兔子总数达到N最少需要的月数。
输入样例:
30
输出样例:
9
我的思路
通过题目,容易想到最基础的办法,构造一个链表,结点的数量即是兔子的数量,单位为对,链表中元素的值可以设定为兔子的年龄,每生出1对兔子,新建一个结点插入链表尾部,并将其年龄月份值为0,而要能生兔子,实际上是该年龄月值到达3,由此可以见,可写一个循环,遍历链表,即可,若年龄达到3,则新建结点,插入链表尾部,否则,该结点年龄值+1。而循环的条件就是结点总数>输入的正整数N。
这是最初的思路,考虑该题输入格式N不超过10000,那么可以建立一个数组,不用对链表操作,先将数组所有元素赋值为0,a[0]=1,month=1,遍历即可。
代码
#include <stdio.h>
int a[66666]={0};
int main(){
int n;
scanf("%d",&n);
int sum=1;
int month=1;
int i;
a[0]=1;
while(sum<n){
month++;
for(i=0;i<sum;i++){
if(a[i]<2) a[i]++;
else sum++;
}
}
printf("%d",month);
}
现在我们来解释,为什么a[0]=1,这点显然,month=1,循环开始前,第一队兔子相当于1个月。再看for循环,if(a[i]<2) a[i]++;看第一次循环a[0]=1;month++;a[0]<2,a[0]++,a[0]=2;然后下次循环刚好month=3,a[0]可以生兔子了,生出来的兔子其实相当于已经第一个月了。而我在初始化时赋值的是0,所以只需要a[i]>=2即可生兔子。相当于刚生出来的兔子,第一个月a[i]=0,第二个月a[i]=1,第三个月a[i]=2,开始生兔子。
斐波那契数列
写完后又发现了个事,仔细思考,可以发现,兔子的数列,第一个月1,第二个月1,第三个月1+1,第四个月2+1,第五个月3+2.....
设第i个月为x,第i+1个月为y,第i+2个月为z
第i+2个月z=y+x。写成y+x,是可以理解为,i+2个月的兔子数(对数)=上一个月(i+1月)兔子数+i月兔子数(因为i到i+2,i看成第一个月,那么i+2就是第三个月,刚好第i月的所有兔子都能生兔子)
这样想就更便捷了。
##该函数返回第n个月兔子数量单位(对)
int sum(int month)
{
if (month==1 || month==2)
return 1;
else
return sum(month-1)+sum(month-2);
}