今日闲来无事看到某帖子上的编程面试题,拿来练练手吧。
abcde五人打渔,打完睡觉,a先醒来,扔掉1条鱼,把剩下的分成5分,拿一份走了;b再醒来,也扔掉1条,把剩下的分成5份,拿一份走了;然后cde都按上面的方法取鱼。问他们一共打了多少条鱼,写程序和算法共打了多少条鱼的结果有很多。(提示:最少打的鱼的结果是3121条鱼)
这个可以将问题倒置思考。最开始有n条鱼,x个人逐个过来放上眼前鱼总数的 n/4 + 1 条鱼,那么第x个人放完后 有多少鱼?
通过高中那时的推导法(名字还给老师了)推出了公式:第n-1个人 与 他拿走后余下鱼的数量 f(n)的关系【这里之所以用n-1是因为 推导出的函数是等比数列,令其为n次方比较好看 ^ ^,而且很巧合的是编码时候这个n-1也很合适,因为第0个是不需要满足条件的^ ^ 】
经过一番分析核对,公式如此: 【最后一位拿走后余下 a 条鱼,共 n 个人拿过鱼,0<=k<=n】
f(n) = (a* 5^n + 4* 5^(n-1) + ... 4^k * 5^(n - k) + 4^n-1 * 5 + 4^n) / 4^n
= (5/4) ^n * (a+4) - 4
f(n) ~ p(n-1)
根据题目要求:f(n)必须为整数,则需要调整a以得出f(n)吧。
代码如下:
#include "stdio.h"
#include <math.h>
#include <ctype.h>
/* 核心算法 */
int Fish_amount_speed(int p_num)
{
int n = p_num ;
int i_up = 0;
int i_up_1 = pow(5.0,n);
int i_up_2 = pow(4,(n+1));
int i_down = pow(4.0,n);
for (int i = 1;1;i++)//i 已经是p0值,所以要计算的 人数里面 共有 p_num -1个,正好是结果需要值
{
i_up = (i+4)*i_up_1 + i_up_2;
if(i_up%i_down == 0) return (i_up/i_down);
}
return 0;
}
int main()
{
int people_max = 5;
int fish_get_last = 1;
int fish_cnt_min = Fish_amount_speed(people_max);//计算
printf("最少是%d条\n",fish_cnt_min);
for (int i = 0;i < people_max;i++)
{
printf("第%d个人拿走了%d条\n",i+1,((fish_cnt_min-1)/5));
fish_cnt_min = (fish_cnt_min-1)/5 * 4;
}
return 0;
}
结果输出:
最少是3129条
第1个人拿走了 625条
第2个人拿走了 499条
第3个人拿走了 399条
第4个人拿走了 319条
第5个人拿走了 255条
press any key to continue
题目来自: