问题描述:
老猴子辛苦了一辈子,给那群小猴子们留下了一笔巨大的财富——一大堆桃子。老猴子决定把这些桃子分给小猴子。
第一个猴子来了,它把桃子分成五堆,五堆一样多,但还多出一个。它把剩下的一个留给老猴子,自己拿走其中的一堆。
第二个猴子来了,它把桃子分成五堆,五堆一样多,但又多出一个。它把多出的一个留给老猴子,自己拿走其中的一堆。
后来的小猴子都如此照办。最后剩下的桃子全部留给老猴子。
这里有n只小猴子,请你写个程序计算一下在开始时至少有多少个桃子,以及最后老猴子最少能得到几个桃子。
分析:
设x个桃子,因为第一只猴子拿一个给老猴子,正好可以分成5堆,所以,(x-1)mod5=0,那么, (x+4)mod5=0。
让我们做点好事,借给猴子们4个桃子,反正最后剩一大堆,我们可以让老猴子还我们4个,呵呵,还可以收利哦。
我们借给猴子4个桃子,那么正好可以分成5堆,第一个猴子就拿了其中一堆(包括老猴子的一个)。但是,它并没有多得桃子。就是(x+4)*(1/5)=(x-1)*(1/5)+1,
因为它没有多得,所以剩下的桃子比原来剩下的多4个(我们借给它们的4个桃子)。那么剩下的桃子同理也恰好可以分成5堆,第二只猴子又拿走了一堆(同样,包括老猴子的一个),同理,第三,第四和第五。
假设n=5,最后,剩下的桃子是(x+4)*(4/5)*(4/5)*(4/5)*(4/5)*(4/5)=(x+4)*(4/5)^5,这应该是个整数,所以,(x+4)一定要能被5^5=3125整除,所以x+4最小是3125,此时,x为3121。
继续讨论:如果是n只猴子按照上述方法分桃 了,那么剩下的桃子是(x+4)*(4/5)*(4/5)*(4/5)*(4/5)*(4/5)*……=(x+4)*(4/5)^n,这应该是个整数,所以,(x+4)一定要能被5^n整除,所以x+4最小是5^n,此时,x为5^n-4。
因此可以知道老猴子得到了 n+(x+4)*(4/5)^n -4,因为每个猴子都给老猴子一个,在剩下的桃子中,又必须还我们四个。呵呵 到收利息的时候了哦!
特别说明:网上很多关于5个猴子分桃子的结果,都是错误的,正确答案是3121个桃子
程序:
(1)说明:当只有一个猴子时,该猴子得不到桃子,至少有桃子数为1,即为老猴子所得。
//别忘了头文件哦
#include "iostream.h"
#include "iomanip.h"
#include <math.h>
//输入参数n为猴子的数量
void getPeach(int n, int &total_num,int &old_monkey_obtain_num)
{
total_num=pow(5,n)-4;
old_monkey_obtain_num = n + (total_num+4)*pow(0.8,n)-4;
int temp=total_num;
int kk=0;
//输出每个猴子获得的桃子树,以及每次拿后剩下的桃子树
for (int i=1;i<=n;i++)
{
kk=(temp-1)/5;
temp=temp-1-kk;
cout<<kk<<setw(5)<<temp<<endl;
}
}
(2)当只有一个猴子时,若要求至少保证该猴子获得一个桃子,则稍微改下:
//输入参数n为猴子的数量
void getPeach(int n, int &total_num,int &old_monkey_obtain_num)
{
if (n==1)
{
total_num=6;
old_monkey_obtain_num =1;
}
else
{
total_num=pow(5,n)-4;
old_monkey_obtain_num = n + (total_num+4)*pow(0.8,n)-4;
}
int temp=total_num;
int kk=0;
//输出每个猴子获得的桃子树,以及每次拿后剩下的桃子树
for (int i=1;i<=n;i++)
{
kk=(temp-1)/5;
temp=temp-1-kk;
cout<<kk<<setw(5)<<temp<<endl;
}
}
问题扩展:
若堆数不为5,为任意正整数p( p >=2)
则
(1)剩下的桃子是(x+(p-1))*((p-1)/p)^n,这是个整数,所以,(x+(p-1))一定要能被p^n整除,所以x=p^n+(p-1)。
(2)老猴子得到了 n+(x+(p-1))*((p-1)/p)^n -(p-1)
Game over! oh,oh.