猴子分香蕉问题 求解

end 2010-07-11 04:15:10
题目描述:
有n只猴子,分若干香蕉。
第一只把香蕉平均分成k分,又多出来了一个,取走一份和多出来的一个。
然后第二只同样把香蕉平均分成k分,又多出来了一个,取走一份和多出来的一个。
第三第四只同样如此。
最后第n只也把香蕉平均分成k分,又多出来了一个,取走一份和多出来的一个。
问原来最少有多少个香蕉。
[/color][size=5]http://yzfy.org
输入:
多组测试数据,一组数据占一行,每行就是n和k(2<= n,k <=30),
当输入0 0的时候结束。

输出:
计算香蕉的最少数目并输出。
你应该假定最后输出的结果不超过32位整数的表示范围。

样例输入:
2 2
2 3
3 3
0 0

样例输出:
7
7
25


这是题目要求 我不只求代码 求给讲解下怎么解决这个问题 我一点思路都没有 谢谢了
...全文
1531 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
linwq_ufida 2010-07-12
  • 打赏
  • 举报
回复
弱弱的问一下,输入3 3,怎么出来的25?
超级大笨狼 2010-07-12
  • 打赏
  • 举报
回复
这个数学证明一下就可以了。
michael122 2010-07-12
  • 打赏
  • 举报
回复
是倒推没错,固定k
设a_i是倒数第i次拿之前的香蕉数
设最后剩下香蕉数为 a0=m*(k-1) m为正整数
则 a_i=a_(i-1)×k/(k-1)+1

化简后 a_n=(m+1)*k^n/(k-1)^(n-1)-k+1
题目变成求最小的m,使得a_n为整数
当k=2时,m=1就行了
否则,取m+1=(k-1)^(n-1) 就行了
oyzdz1988 2010-07-12
  • 打赏
  • 举报
回复
楼上的公式太强大了,请介绍下怎么推导出来的吧~

我只知道用穷举来做了,可以从最后一只猴子倒推,先设每只猴子在分之前的香蕉数量分别为

X1 X2 X3 ... Xn,有这样的关系: X(i-1) = Xi + X(i-1)/k + 1;
(Xi-1) % k = 0;

这样,从Xn开始倒推,可先令(Xn-1) = 1*K,然后根据递推公式住上推导,出现不整除的情况则失败,

重新改变Xn, 即令(Xn-1) = t*k,t = 1, 2 , 3...

如果能推到X1,则成功,一共推导(n-1)次~代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

int main()
{
int n, k;
int preX, nextX;
int i, t, tmp, find;

scanf("%d%d", &n, &k);
t = 0;
find = 0;
while (++t)
{
nextX = k*t + 1;
for (i = 0; i < n-1; i++)
{
tmp = (nextX*k - 1 + k);
if (tmp % (k-1) == 0)
{
preX = tmp / (k-1);
}
else
{
break;
}

if ((preX - 1) % k == 0)
{
nextX = preX;
}
else
{
break;
}
}
if (i == n-1) find = 1;
if (find)
break;
}

printf("%d\n", preX);

return 0;
}
michael122 2010-07-12
  • 打赏
  • 举报
回复
k=2时,答案是 2k^n-k+1
k>2时,k^n-k+1

敲错了,2个都是n次方
凤朝凰 2010-07-12
  • 打赏
  • 举报
回复
记下,以后用的
michael122 2010-07-12
  • 打赏
  • 举报
回复
上面应该k=2时是2k^n-k+1 。。。 n次方,打错了
michael122 2010-07-12
  • 打赏
  • 举报
回复
错了。。。
k=2时,答案是 2k*n-k+1
k>2时,k*n-k+1

k<2就没什么意义了,不讨论了
michael122 2010-07-12
  • 打赏
  • 举报
回复
没推错的话,答案是k^n-k+1
LeonTown 2010-07-12
  • 打赏
  • 举报
回复
能解释一下吗?

[Quote=引用 5 楼 fanster28_ 的回复:]

#include <iostream>
int main()
{
for(int n,k,i,a;;scanf("%d%d",&n,&k)!=EOF;) {
if(n==0&&k==0)break;
if(k==2)n++;
i=k;a=1;
while(n) {
……
[/Quote]
michael122 2010-07-12
  • 打赏
  • 举报
回复
第一次分为8,8,9 拿走9
第二次分为5,5,6 拿走6
第三次分为3,3,4 拿走4
fanster28_ 2010-07-11
  • 打赏
  • 举报
回复
#include <iostream>
int main()
{
for(int n,k,i,a;;scanf("%d%d",&n,&k)!=EOF;) {
if(n==0&&k==0)break;
if(k==2)n++;
i=k;a=1;
while(n) {
if(n&1) a*=i;
i*=i;
n/=2;
}
printf("%d\n",a-k+1);
}
return 0;
}
qq120848369 2010-07-11
  • 打赏
  • 举报
回复
有些问题它就是一道数学问题,直接去找数学原型.
james2222 2010-07-11
  • 打赏
  • 举报
回复
mark
end 2010-07-11
  • 打赏
  • 举报
回复
说实话 这题让我用笔算都费尽 估计算不出来 别说写出程序来了
acdbxzyw 2010-07-11
  • 打赏
  • 举报
回复
推导出关于n和k的数学公式应该就ok了。

33,006

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧