海盗一行七人,在海上打劫了一艘富商的商船,得到很多金币。
当晚为了庆祝战果喝了很多酒后,回到各自的船舱睡的不省人事。
第二天第一个海盗醒来,
从抢来的金币中拿出一枚扔向大海,以表达对海神的敬意。
然后将剩下的金币平分成七份,自己带走其中一份离开。
第三天第二个海盗醒来,
他不知道第一个海盗已经走了,
于是也从抢来的金币中拿出一枚扔向大海。
然后将剩下的金币平分成七份,自己带走其中一份离开。
随后的五天,剩下的五个海盗依次醒来。
他们也都不知道已经有同伴在他们之前离开,
所以每个人都重复了上一个人分金币时的动作。
终于海盗走光了,海盗船独自在海上漂泊,撞上一座岛屿。
岛上的村民庆幸的发现船上剩余的金币。
请问,富商最少损失了多少金币,村民们又捡到了多少金币?
思路:
1,每天都是扔一个,再平分成七份,所以每天海盗醒来看到的金币数量%7结果都是1。
2,本题可以正推,也可以反推。推的过程中唯一的判定标准就是不能出现小数。
正推:
因为我们不知道金币初始数量,所以只能在一个足够大的范围类去循环检测。
排除题目无解的可能,我们就用while死循环来检测,知道找到答案才跳出。找到答案的标准就是能够顺利的分到第七天,不出现小数。代码如下:
void main(){
int currentday,total = 8,i;
while (1)
{
currentday = total; //先将我们假设的总数拷贝一份
for (i = 0; i < 7; i++)
{
if ((currentday - 1) % 7 == 0) //检查是否符合分配原则
{
currentday = (currentday - 1) * 6 / 7; //如果符合就分配,刷新剩余总数
}
else
{
total++; //如果不符合分配标准就调整我们假设的总数
break; //分配动作提前终止
}
}
if (i == 7) //如果能按照分配原则,顺利分七次,说明我们已经将总数调整为正确答案
{
break;
}
}
printf("商人被抢劫的金币数量是:%d\n村民们捡到的金币数量是:%d", total, currentday);
getchar();
}
反推:
假设最后一天的海盗带走的数量是1,也就是说最后一天他醒来时看到的数量是8,以这个为基准往前推一天就是8/6 * 7+1,所以要确定的是8/6 * 7不可以为小数:
void main()
{
int currentday = 6, total,i;
while (1)
{
total = currentday;
for (i = 0; i < 7; i++)
{
if (total % 6 == 0)
{
total = total / 6 * 7 + 1;
}
else
{
currentday++;
break;
}
}
if (i == 7)
{
break;
}
}
printf("商人被抢劫的金币数量是:%d\n村民们捡到的金币数量是:%d", total, currentday);
getchar();
}