猴子分桃


尚学堂Java培训所谓的笔试题目,当时想倒过来推,以为做对了,其实根本没有考虑清楚。从网上转载了下面这篇文件,写得很详细:


问题描述:

老猴子辛苦了一辈子,给那群小猴子们留下了一笔巨大的财富——一大堆桃子。老猴子决定把这些桃子分给小猴子。

第一个猴子来了,它把桃子分成五堆,五堆一样多,但还多出一个。它把剩下的一个留给老猴子,自己拿走其中的一堆。

第二个猴子来了,它把桃子分成五堆,五堆一样多,但又多出一个。它把多出的一个留给老猴子,自己拿走其中的一堆。

后来的小猴子都如此照办。最后剩下的桃子全部留给老猴子。

这里有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.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值