案例十五:猴子偷桃

分析:

第一只猴子把桃子分成份,多了一个,一开始试图假设每份桃子数量是x。然后算出第2只猴子将桃子分成份的每份桃子数量,…。如下表所示
后来发现公式越来越复杂,以至于无法表示出来

其实本题应该倒过来,从第只猴子开始算,因为每一轮的桃子数量肯定是越来越少的。假设第n只猴子分桃子,每份k个,还多了1个,如下表所示,那么第n轮桃子总数是tot=n*k+1。这个总数是上一轮的(n-1)份,tot必须能被(n-1)整除,而且上一轮桃子数应该为n*tot/(n-1)+1,如果顺利,可以从第n轮倒推到1轮,从而可以求出第1轮原有的桃子数,求出k后,最终的tot就是第一轮原有桃子数,就是本题的答案

前面所说的“顺利”是指:从第n轮往前递推,当前这一轮桃子总数tot是上一轮(n-1)份桃子总和,所以tot必须能够被(n-1)整除。要求从第n轮,递推n-1次,都能顺序递推。从1开始从小到大枚举k的取值,第一个符合要求的k值就是本题要求的

本题还有一个坑,虽然题目保证桃子数在int型范围内,但是当n=9时,第一轮桃子数已经接近于int型范围的上限了,程序中还有n*tot/(n-1)的运算,所以运算的中间结果仍有可能会超出int型范围,所以本题tot,k这2个变量必须定义成long long型
当然,如果把这个运算改成tot/(n-1)*n,也是能通过评测的,注意tot肯定能被(n-1)整除,另外,这个运算表示tot先除(n-1),再把得到的上乘以n

代码如下:

#include<iostream>
using namespace std;
int main()
{
	int n, x; cin >> n;
	long long k; //第n只猴子将桃子分成n份,每份桃子树
	long long tot; //每一轮桃子数 
	for(k=1; ;k++){  //枚举k的取值,第一个符合条件的k就是所求的值,循环条件空缺
		tot = n*k+1;
		int i;
		for(i=n-1;i>=1;i--){
			if(tot%(n-1)!=0) break; //break语句只能退出一重循环 
			tot = n*tot/(n-1)+1; //递推	 
		}
		if(i<1) break; //成功递推到了第1只猴子分桃子时 	
	}
	cout << tot << endl;
    return 0;
}

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值