一道经典面试逻辑题的python解法

前言:

好早之前看到的一个逻辑题:有两个2到99之间的整数,a知道这两个数的和,b知道这两个数的积。

第一句:a对b说:我不知道这两个数是多少,但我确信你也不知道。

第二句:b说:我知道了。

第三句:a说:我也知道了。

问这两个数是多少? 题不难,只是手动去找没有python写程序找的快,而且用python程序可以在后面进行进一步的探索。

分析:

首先是a手上的数是两个数的和,那是在[4,198]之间。

第一句话分析:a确信b不知道这两个数

(1)

比如a手上的数字是8,那么要求的两个数字就有可能是(2,6),(3,5),(4,4)这三种情况,对应的b手上的数字就可能是12,15,16这三种情况,这是来自a的视角。

但简单分析,第一句话 a确信b不知道这两个数字是多少。那么b手上的数字肯定不可能是15,为什么呢?因为15只有一种分解情况(两个素数相乘):3*5。如果b手上是15,那么b肯定知道这两个数字是3和5了。

进而可以分析出 a 手上的数字肯定不是8, 因为a手上是8的话,那b手上可能的三种情况(12,15,16) 其中的15这种情况,b是可以分析出这两个数字分别是多少的,而a确信b不知道,所以可以排除8。

进一步,那a手上什么数字可以排除掉呢?通过上面的分析,

可以得出 结论(1):a是不能分解成两个素数的和,凡是可以分解成两个素数的和的情况,b是可以知道这两个数的

上python代码:


asum1里面存了a手上还可能的数,54个(排除了那些能分解成两个素数的数)

(2)

上面的54个可能里面全是奇数,没有偶数。

进一步分析:a 手上的数字也不能写成(53+2*x,x>=2)这种形式,因为如果可以分解成这种形式,b=53*2*x,因为两个数是小于等于99的,53*2>99了,也只有一种分解情况53,2*x,进而b也知道这两个数字了。

所以结论(2):比上限/2(99/2=49.5)大的第一个素数(53),+3(56)以后的数字就排除了。

为什么是+3,因为2*x最小是4.

所以经过第一句话后,a手上的数字asum2集合 还剩11个

[11, 17, 23, 27, 29, 35, 37, 41, 47, 51, 53]   <-asum2

把他们分解了,相乘得到b的粗略集合:



第二句话分析:b知道了

b在什么情况下可以说这样的话呢? 

比如b =24, 那么可能的分解(2,12),(3,8),(4,6)两种情况,那么对于的 a就是14,11和10三种情况,这是来自b的视角。

刚开分析了那么多得出a手上剩下的可能性:[11, 17, 23, 27, 29, 35, 37, 41, 47, 51, 53],这个集合的意思是当a手上是这些数的时候a才敢说第一句话,反言之a手上不是这些数时a就不敢说这些话。

那么24分解出来得到的 14,11和10三种情况:14,10不在a可能集合里,11在可能集合里。

11是唯一一个在a可能集合里的,所以b可以分析出a手上的数字是11,因为如果是其他两个数的话,a不敢说第一句话。

进而得出一个结论:b分解出来的所有两个数eg:(2,12),(3,8),(4,6)所组成的和eg:14,11和10, 有且只有一个存在在a的可能集合里



经过第二句话b手上可能数字有102个,存入bmul1

第三句话分析:a知道了

和第二句话一模一样的分析,a为什么能知道?唯一的可能性就是a手上的数的分解后组成的积有且只有一种情况在集合bmul1里(第二句话算出的集合b)



现在就只有唯一一个结果了。

输出结果





原题到这里就结束了,后面可以展开一些思考。

(1)既然得出的结论是4和13,不算大,而条件给的是2-99,那么有没有可能把条件范围给小一点,比如给2-20来降低题目难度呢,毕竟这样计算量要小很多。程序里面可以直接把初始条件从99改成20,结果是没有找到符合要求的两个数。为什么呢?

原因是虽然4和13小于20,但a看到的是17,那么有可能分解成8和9,在a的视角b的数字有可能是72,同时在b的视角的可以分解成2*36,这个36就一下大于20了哦。 

那么把题目换个有趣的问法,同样的对话,两个数字的范围是2-N,N至少取多大,才能保证至少有一个解? 

用程序解很简单,让N从10到99进行一次遍历,看从哪次开始有解了就输出

得到的结论是:N至少是64才有一个解,(4,13)

(2) 那么把N扩大,范围扩大,解会变多吗

如果范围扩大到2-999了,有了第二个解4,61。大家可以思考一下为什么范围在2-99的时候没有出现这个解

范围扩大到2-9999了,算出来了13个解,分别是: 

1 两个数和: 17 两个数积: 52

两个数为: [4, 13]

2 两个数和: 65 两个数积: 244

两个数为: [4, 61]

3 两个数和: 89 两个数积: 1168

两个数为: [16, 73]

4 两个数和: 127 两个数积: 1776

两个数为: [16, 111]

5 两个数和: 137 两个数积: 4672

两个数为: [64, 73]

6 两个数和: 163 两个数积: 4192

两个数为: [32, 131]

7 两个数和: 179 两个数积: 2608

两个数为: [16, 163]

8 两个数和: 185 两个数积: 724

两个数为: [4, 181]

9 两个数和: 191 两个数积: 8128

两个数为: [64, 127]

10 两个数和: 233 两个数积: 916

两个数为: [4, 229]

11 两个数和: 247 两个数积: 1912

两个数为: [8, 239]

12 两个数和: 343 两个数积: 9952

两个数为: [32, 311]

13 两个数和: 373 两个数积: 19776

两个数为: [64, 309]


  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值