OpenJudge NOI 2.1 7217:猴子吃桃

【题目链接】

OpenJudge NOI 2.1 7217:猴子吃桃

【题目考点】

1. 递推
2. 枚举

【解题思路】

解法1:递推 枚举

记:第i只猴子面对的桃子数为 a i a_i ai

  • 设第n只猴子拿到的桃子数为m,第n只猴子面对的桃子数 a n = m ⋅ n + 1 a_n=m\cdot n+1 an=mn+1

  • a n a_n an是第n-1只猴子扔掉1个桃子并拿走1份桃子后剩下的n-1份桃子,那么一定应该有 a n % ( n − 1 ) = 0 a_n\%(n-1)=0 an%(n1)=0。如不满足则结束递推。如果满足,则第n-1只猴子面对的桃子数 a n − 1 = a n ⋅ n n − 1 + 1 a_{n-1}=a_{n}\cdot\frac{n}{n-1}+1 an1=ann1n+1

  • a n − 1 a_{n-1} an1是第n-2只猴子扔掉1个桃子并拿走1份桃子后剩下的n-1份桃子,,那么一定应该有 a n − 1 % ( n − 1 ) = 0 a_{n-1}\%(n-1)=0 an1%(n1)=0。如不满足则结束递推。如果满足,则那么第n-2只猴子面对的桃子数 a n − 2 = a n − 1 ⋅ n n − 1 + 1 a_{n-2}=a_{n-1}\cdot\frac{n}{n-1}+1 an2=an1n1n+1

  • a 2 a_{2} a2是第1只猴子扔掉1个桃子并拿走1份桃子后剩下的n-1份桃子,那么一定应该有 a 2 % ( n − 1 ) = 0 a_2\%(n-1)=0 a2%(n1)=0。如不满足则结束递推。如果满足,则那么第1只猴子面对的桃子数 a 1 = a 2 ⋅ n n − 1 + 1 a_1=a_2\cdot\frac{n}{n-1}+1 a1=a2n1n+1

  • a 1 a_1 a1是第1只猴子面对的桃子数量,即为题目所求的:当猴子数量为N时海滩上最少的桃子数。

因此一般递推公式为:
a i = a i + 1 ⋅ n n − 1 + 1 a_i=a_{i+1}\cdot\frac{n}{n-1}+1 ai=ai+1n1n+1

已知后面项的值,和从后向前的递推公式,推出前面的项。这与我们平时做的已知前面的项,和从前向后的递推公式,推出后面的项没有本质区别。
如果感觉不习惯,我们可以这样定义递推状态:
记:倒数第i只猴子面对的桃子数为 b i b_i bi
显然,倒数第i只就是正数第n-i+1只。
那么倒数第1只猴子面对的桃子数为 b 1 = a n = m ⋅ n + 1 b_1=a_n=m\cdot n+1 b1=an=mn+1
递推公式变为:
b i = b i − 1 ⋅ n n − 1 + 1 b_i=b_{i-1}\cdot\frac{n}{n-1}+1 bi=bi1n1n+1,前提是 b i − 1 % ( n − 1 ) = 0 b_{i-1}\%(n-1)=0 bi1%(n1)=0
所求的是第1只猴子面对的桃子数 a 1 a_1 a1,也就是倒数第n只猴子面对的桃子数 b n b_n bn
题目没给n的范围,可以默认n不大于100。因此数组长度设为100。

从小到大枚举第n只猴子拿到的桃子数m

  • 如果可以从 b 1 b_1 b1经过不断递推推出 b n b_n bn, 则 b n b_n bn是海滩上最少的桃子数。
  • 如果中途发现b中某一项不是n-1的倍数,那么停止这趟递推,m取下一个值,重新开始递推。

【注意】:虽然题目指明结果在int可以表示的范围内,也就是 b i b_i bi都在int的范围内。但如果写成b[i-1]*n/(n-1),那么b[i-1]*n的值可能超出int类型的范围。为解决这一情况,在计算时可以使用long long类型。或者写b[i-1]/(n-1)*n先除再乘,可以保证中间结果都不超出int类型的范围。

【题解代码】

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n, m, i, b[105];//b[i]:倒数第i只猴子面对的桃子数
	cin >> n;//n:后字数 
	for(m = 1; true; m++)//m:第n个猴子拿到的桃子数 
	{
		b[1] = m*n+1;
		for(i = 2; i <= n; ++i)
		{
			if(b[i-1] % (n-1) != 0)
				break;
			b[i] = b[i-1]/(n-1)*n+1;//b[i-1]*n的结果可能超出int类型的范围,所以先除再乘,可以保证中间结果都不超出int类型的范围 
		}
		if(i > n)//如果上面的循环进行到了最后,求出了b[n]
		{
			cout << b[n];//b[n]:倒数第n只猴子面对的桃子数,也就是海滩上的桃子数 
			return 0;			
		}
	}
	return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值