逻辑面试题:一个逻辑学教授,有三个学生,3个人玩猜数字的游戏
作者 | 小K
出品 | 公众号:小K算法 (ID:xiaok365)
1.故事起源
一个逻辑学教授,有三个学生,而且三个学生都非常聪明!
有一天教授给他们出了一个题:
教授在每个人脑门上贴了一张纸条
每个人的纸条上都写了一个正整数,且某两个数的和等于第三个数
每个人可以看见另两个数,但看不见自己的
教授问第一个学生:你能猜出自己的数吗?回答:不能。
问第二个,不能;第三个,不能。
教授再问第二次:
第一个,不能;第二个,不能;第三个,我猜出来了,是144!
教授很满意的笑了,请问你能猜出另外两个人的数吗?
2.场景重现
要破解这个问题,就要先扮演这个角色,我们来场景模拟一下,3个同学围绕站成一个圈。
为方便描述,用下面的图形来表示。
因为只能看到别人的数,看不到自己的,所以小K的视角是这样的。
同样小A的视角是这样的。
小B的视角是这样的。
发现了什么规律吗,我们总结一下:
每个人自己的数只能是另两数之和或者之差,所以每个人都有2种可能。
每个人都无法确认自己到底是哪一个,也不能从其他人那里得到更多信息。
因此,看上去貌似是个死局。
再仔细思考,既然只有2种可能,那能不能排除一种可能,这样只剩下另一种肯定就是正确答案了。关键是如何去寻找这个突破口呢?
3.寻找突破口
要排除不可能的解,必须要从边界入手,如果没有任何条件限制,那这就是一个无解的问题。
再回到问题描述,“每个人的纸条上都写了一个正整数”,这就是最关键的信息,它暗示了很多其它信息。如果有一个人计算出来的数不是正整数,那这一种情况就被排除。
这个数不可能是负数,因为2个不相等的数,一定是用大的减去小的,那剩下的非正整数就只能是0,也就是有2个数相等的情况。
假设小K看到的是这样的场景,那一定能猜到自己的数就是10。
现在有了一点进展,但还是不够,因为2个数相等也只是一种巧合,大部分的时候,你看到的数都不相等,感觉还是很难走下去。
先别想得太复杂,咱们来降维打击。
4.从小规模分析
关注小K很久的同学应该已经发现了,小K最喜欢用的手段,就是从小规模开始分析问题,再逐层推进。
如果2个数相等,抽象一下,不就是一个最简单的1+1=2的问题吗?
如果是下面这种情况,会在第1轮由第1人直接猜出。
同样对于另外2个人也是一样,能在自己的轮次直接猜出。
我们似乎已经解决了3种场景了,应该是走对了,继续往下推,再扩大数据规模。不过相等的我们已经列举完了,都可以归类为1+1=2的问题,那怎么推广到不等呢?
5.第1人猜不出
第1轮询问,如果第1人猜不出,对于后面的人来说给出了另一个信息,就是这3个数肯定不是(2,1,1),因为如果是(2,1,1)那第1人肯定就猜出来了啊。
那怎么利用这个信息呢?
如果小A看到的场景刚好是这样,(2,y,1),那y不是1,肯定就是3了呀。
总结一下前面的情况。
6.第2人猜不出
如果第2人猜不出,对于第3人来说,也给出了很多信息,说明一定不是(2,1,1),(1,2,1),(2,3,1)。
如果第3人刚好看到的是(2,1,z),(1,2,z),(2,3,z),那就可以直接猜出。
总结第1轮分别能被3人猜出的情况如下:
而且我们发现,每一个人能猜出的情况,是由前2个人能猜出的情况迭代过来的。因为前面的人猜不出就排除了一种可能,只剩下另一种,自然能被后面的人猜出。
7.第2轮
如果第1轮第3人也没猜出,就会进入下一轮。
第2轮第1人能猜出的情况如下:
同理第2轮第2人能猜出的情况如下:
第2轮第3人能猜出的情况如下:
回到开始的问题,第3个同学在第2轮猜出自己是144,所以上面的16个解中,第3个数字能被144整除的,都是符合条件的解。
正确的解有5个:(3,1,4),(1,3,4),(2,7,9),(4,5,9),(3,5,8)。
对应的另外两个数分别是:(108,36),(36,108),(32,112),(64,80),(54,90)。
8.任意情况
比如为(98,27,71)的情况,根据上面的规律,最终还是会回归到1+1=2的问题。
结论:
3个数要先约掉公约数,等比例的情况都是相同的
任意情况,都会在有限轮次之后被某个人猜出来
最先猜出来的人,一定是数字最大的人
所有逻辑推理的根基都是1+1=2
每多一轮,解的个数以斐波那契数列递增
9.代码实现
9.1 定义及初始化
struct Node {int x, y, z, level;
};
Node f[10000];
int last1, last2, tail;
void init() {f[0] = Node{2, 1, 1, 1};f[1] = Node{1, 2, 1, 2};f[2] = Node{2, 3, 1, 2};f[3] = Node{1, 1, 2, 3};f[4] = Node{2, 1, 3, 3};f[5] = Node{1, 2, 3, 3};f[6] = Node{2, 3, 5, 3};last1 = 3;last2 = 1;tail = 7;
}
9.2 关键算法
// 第round轮,第person人,猜出自己是x
void solve(int round, int person, int x) {int n = (round - 2) * 3 + person, total;for (int i = 0; i < n; ++i) {total = tail;for (int j = last2; j < total; ++j) {if (i % 3 == 0) {f[tail++] = Node{f[j].y + f[j].z, f[j].y, f[j].z, 4 + i};} else if (i % 3 == 1) {f[tail++] = Node{f[j].x, f[j].x + f[j].z, f[j].z, 4 + i};} else {f[tail++] = Node{f[j].x, f[j].y, f[j].x + f[j].y, 4 + i};}}last2 = last1;last1 = total;}for (int i = last1; i < tail; ++i) {int temp = 0;switch (person) {case 1:temp = f[i].x;break;case 2:temp = f[i].y;break;case 3:temp = f[i].z;break;}if (x % temp == 0) {int s = x / f[i].z;printf("(%d, %d, %d), level=%d\n", f[i].x * s, f[i].y * s, f[i].z * s, f[i].level);}}
}
9.3 主过程
int main() {init();solve(2, 3, 144);return 0;
}
9.4 数据测试输出
(108, 36, 144), level=6
(36, 108, 144), level=6
(32, 112, 144), level=6
(64, 80, 144), level=6
(54, 90, 144), level=6
10.总结
第一眼看上去觉得简单,初步思考发现没有思路,感觉有难度,认真一步一步的分析下去,又会发现其实还是很简单,关键在于能否发现本质规律。这是一道极强的逻辑推理,大家一定要认真分析领悟,相信你可以学到很多的知识,打开思维模式。
本文原创作者:小K,一个思维独特的写手。
文章首发平台:微信公众号【小K算法】。
如果喜欢小K的文章,请点个关注,分享给更多的人,小K将持续更新,谢谢啦!
关注下方公众号,分享硬核知识
往期精彩回顾
经典智力面试题:一家人过桥
微软面试题:红帽子与黑帽子
图解堆排序算法
逻辑面试题:一个逻辑学教授,有三个学生,3个人玩猜数字的游戏相关推荐
- 模拟登录,给三次机会,并提示还有几次。如果登录成功,就可以玩猜数字小游戏了。
1.猜字谜小游戏 *随机生成一个数 *从键盘录入一个数与随机数进行比较,判断是大了还是小了 * */ package test1;import java.util.Scanner;public cla ...
- 过年了教你自己动手写一个小游戏给表弟玩-猜数字小游戏
目录
- 如何用计算机猜数字,杭电2010计算机复试笔试题 2道acm简单题(2010):1.猜数字游戏;2.字符串提取数字并求和;...
//第一题是猜数字的游戏. //题目:随即产生一个3位的正整数,让你进行猜数字, //如果猜小了,输出:"猜小了,请继续". //如果猜大了,输出:"猜大了,请继续&qu ...
- 第三次学JAVA再学不好就吃翔(part28)--猜数字小游戏
学习笔记,仅供参考 面向对象 猜数字小游戏 随机生成一个1 ~ 100之间的数,我来猜是几: import java.util.Scanner;class GuessNumTest {public s ...
- 初识JAVA:猜数字小游戏案例---系统产生一个1-100之间的随机数,猜出这个数是多少?
package com.pku.wuyu.io; import java.util.IllegalFormatCodePointException; import java.util.Random; ...
- c语言生成随机数猜数字大小,产生一个随机数,进行猜数字小游戏
产生随机数 Random:用于产生随机数 使用步骤: 1.导包 import java.util.Random; 2.创建对象 Random r = new Random(); 3.获取随机数 int ...
- html写一个猜数字游戏,JS实现网页端猜数字小游戏
本文实例为大家分享了JS实现网页端猜数字游戏的具体代码,供大家参考,具体内容如下 题目描述 电脑产生一个0到100之间的随机数字,并且要求用户来猜,如果用户猜的数字比这个数字大,电脑会提示" ...
- 教你如何用C语言设计一个有趣的猜数字小游戏
目录 前言 猜数字游戏 打印菜单 处理玩家选择的操作 编写猜数字游戏函数 游戏中要猜数字从哪来?(配置随机数生成器) 时间戳 开始生成随机数 game函数内部编写 完整代码 总结 前言 好久不见,今天 ...
- python编写一个简单的猜数字小游戏
该脚本包含了python基础的部分内容,python初学者既可以学习借鉴,也可以向朋友去装13. 本次编写的内容需要导入一个第三方模块random,可获得规定范围的随机数. 首先打开pycharm中下 ...
最新文章
- 【青少年编程】【二级】货运飞船
- 5G时代到来,人工智能设备如何重塑TMT行业
- HDLBits 系列(18) BCD码计数器的设计
- JAVA语法——汉诺塔问题
- 【Python教程】删除字符串中字符的四种方法
- Prime Count 求大区间素数个数
- leetcode 566. Reshape the Matrix | 566. 重塑矩阵(Java)
- java根据模板生成PDF
- 逆波兰表达式中缀表达式转换为后缀表达式
- SVN版本管理系统的使用(CentOS+Subversion+Apache+Jsvnadmin+TortoiseSVN)
- python迭代器与生成器_python的迭代器与生成器实例详解
- Java基础学习总结(37)——Java23中设计模式(Design Patterns)详解
- smarty手册-smarty中foreach循环语句详解
- 怎么把代码放图片里面进行注入_揭秘代码分层后的新世界
- toolchain安装教程支持_Ubuntu安装ARM架构GCC工具链(ubuntu install ARM toolchain)最简单办法...
- java三三剩二五五剩三,大年三十彩灯悬,彩灯齐明光灿灿,三三数时能数尽,五五数时剩一盏,七七数时刚刚好,八八数时还缺三,...
- body onload
- C#WinForm中在dataGridView中添加中文表头
- 去中心化金融 (DeFi)
- PCF8574AT驱动LCD1602