n个水手分椰子
有n个水手来到一个岛上,采了一堆椰子后,因为疲劳都睡着了。一段时间后,第一个水手醒来,悄悄地将椰子等分成n份,多出m个椰子,便给了旁边的猴子,然后自己藏起一份,再将剩下的椰子重新合在一起,继续睡觉。不久,第二名水手醒来,同样将椰子了等分成n份,恰好也多出m个,也给了猴子。然而自己也藏起一份,再将剩下的椰子重新合在一起。以后每个水手都如此分了一次并都藏起一份,也恰好都把多出的m个给了猴子。第二天,n个水手醒来,发现椰子少了许多,心照不宣,便把剩下的椰子分成n份,恰好又多出m个,给了猴子。
有n个水手来到一个岛上,采了一堆椰子后,因为疲劳都睡着了。一段时间后,第一个水手醒来,悄悄地将椰子等分成n份,多出m个椰子,便给了旁边的猴子,然后自己藏起一份,再将剩下的椰子重新合在一起,继续睡觉。不久,第二名水手醒来,同样将椰子了等分成n份,恰好也多出m个,也给了猴子。然而自己也藏起一份,再将剩下的椰子重新合在一起。以后每个水手都如此分了一次并都藏起一份,也恰好都把多出的m个给了猴子。第二天,n个水手醒来,发现椰子少了许多,心照不宣,便把剩下的椰子分成n份,恰好又多出m个,给了猴子。
对于给定的整数n,m(约定0<m<n<9从键盘输入),试求原来这堆椰子至少有多少个?
题解:
从最后一个人开始递推。分f[i]表示第i个人平分椰子每堆椰子的个数。所以他面临的椰子个数总数是f[i]*n+m。而这个椰子总是正好是上一个人平分之后拿走一堆剩余下来的。所以求上一个人每堆椰子的个数时要知道,这个数一定是整数。递推公式是f[i-1]=(f[i]*n+m)/(n-1),要满足所有f[i]都为整数,所以第一堆椰子个数进行枚举。最少是n-1-m个,然后每次增加n-1个,这样就能保证上一个人平分椰子个数是整数。就这样了。
#include<limits>
#include<queue>
#include<vector>
#include<list>
#include<map>
#include<set>
#include<deque>
#include<stack>
#include<bitset>
#include<algorithm>
#include<functional>
#include<numeric>
#include<utility>
#include<sstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<ctime>
#define LL long long
#define eps 1e-8
#define pi acos(-1)
#define INF 0x7fffffff
#define delta 0.98 //模拟退火递增变量
using namespace std;
LL f[20];
int main(){
int n,m,i;
scanf("%d%d",&n,&m);
int k=n-1;
f[1]=n-1-m;
while(i<=(n+1)){
double g=(f[i-1]*n+m)*1.0/(n-1);
//g=g*(n-1)-m;
if (floor(g)==g){
f[i]=g;
i++;
}
else{
f[1]+=k;
i=2;
}
}
printf("原来椰子最少的个数是%lld\n",f[n+1]*n+m);
k=1;
for (i=n+1;i>=1;i--){
printf("第%d个人面临的椰子个数是:%lld=%lld*%d+%d,藏掉%lld个\n",k++,f[i]*n+m,f[i],n,m);
}
return 0;
}