Question:
这里有一大堆桃子。这是5个猴子的公共财产。它们要平均分配。
第一个猴子来了。它左等右等,别的猴子都不来,便动手把桃子均分成5堆,还剩了1个。它觉得自己辛苦了,当之无愧地把这1个无法分配的桃子吃掉,又拿走了5堆中的1堆。
第二个猴子来了。它不知道刚才发生的情况,又把桃子均分成5堆,还是多了1个。它吃了这1个,拿1堆走了。
以后,每个猴子来了,都是如此办理。
请问:原来至少有多少桃子?最后至少剩多少桃子?
这个问题是由大物理学家狄拉克提出来的。1979年春天,著名美籍物理学家李政道,在和中国科学技术大学少年班同学座谈时,也向他们提出过这个题目。当时,谁也没有能够当场做出回答,可见这个题目有点难。
Solution:
---------------------------1-------------写出递归公式,解方程---------------------------
设原有苹果S(1)个,第一个猴子取走A(1)个,剩余苹果S(2)个,依次类推,列得差分方程:
4[S(n)-1]=5S(n+1)
A(n)=S(n)-1/5
求得通解:
S(n)=(S1+4)(0.8)^(n-1)-4
分析知,S1+4=5^5时,A(5)取得最小值,具体值分别为:
S1=3121 A1=624
S2=2496 A2=499
S3=1996 A3=399
S4=1596 A4=319
S5=1276 A5=255
这个用到的是差分方程的解题法,主要的方法在《离散数学》和《高等数学》上有得介绍。
---------------------------2-------------写出递归函数,编程序---------------------------
一看就知道这个一个递归的过程,因为每个猴子的那苹果过程都是相似的,而且上次的拿苹果可以作为下一个猴子拿苹果的输入。
take(num,i)函数,描述这个拿苹果的过程。num 是当前的苹果数;i还有几个猴子没有拿去拿苹果。
我们可以重,1开始递增来尝试,直到有符合条件(就是5个猴子能经历分的过程)的苹果数。
具体的程序如下:
#include<stdio.h>
#include<stdlib.h>
bool take(int,int);
main ()
{
int apple =6; //想想为什么一开始就知道从6开始尝试
bool signal=0;//一个标记变量,找到符合的苹果树则循环结束
while(!signal)
{
signal = take(apple,5);
apple++; //这个程序的关键点,好的程序不会一个一个的递增的,大家应该想想增量
}
system("pause");
return 0;
}
//这是一个递归函数,描述每次猴子拿苹果的相同过程
bool take(int num,int i)
{
if(i==0) //5个猴子都拿完了,条件满足
return true;
num = num-1;
if(num%5!= 0||num <= 0)//不能分成5堆的苹果数是不符合的,直接返回
return false;
else
{
printf("%d---%d/n",num+1,i);
return take(4*num/5,i-1);
}
}
为什么写这个题目呢?
跟一个同学去吃饭,他最近要准备研究生的复试和上机考试。这个题目是,他去找导师的时候,导师给他们出的一个编程题,考的就是递归的思想,很基础的一个题目,可是,当场只有一个人能做出来。
上课的时候,老师也跟我们抱怨,现在的大学生的编程能力太差,虽然考试考的很好。学校对本科生的要求并不是很高,都是很多基础的东西。学计算机的人,还是要多点摸一摸程序,而不是游戏呀!
p.s
有两本书,给小学生看的,可以提高数学的兴趣——《帮你学数学》、《奇妙的数王国》