趣味推理题目:知道问题

题目描述: 两个确定的数字x和y满足如下条件:1<x<y和x+y<=100。把 s=x+y 告诉S,p=x*y告诉P,两人间发生如下对话。 P说:我不知道这两个数字。

S说:我早已知道你不知道这两个数字。

P说:我现在知道这两个数字了。

S说:我也知道这两个数字了。

答案是x = 4, y = 13,问:P与S分别如何得到答案?

乍一看,P和S好像是两个谜语人。但实际上,对话中已经蕴含了解题的必要信息。我们梳理一下现有信息。

首先是两个题目限制条件:

        1 < x < y              (1)

        x + y <= 100        (2)

P知道:

        p = x * y               (3)

S知道:

        s = x + y               (4)

其中(4)蕴含一个推论:

        P无法推出x和y     (5)

我们先来从P的视角分析一下问题。

当P同时拥有了信息(1)(2)(3)(5)时,就可以推出x与y的值。

先来想一下,为什么P无法通过条件(1)得出答案。如果说p有两个质因数,如p = 77 = 7 * 11,那一眼就能看出来x = 7,y = 11。但如果因数中存在合数,则不能确定x与y。

因此我们得出推论:

        x为合数 或 y为合数        (6)

由此我们就知道(5)是怎么来的了,根据(5) → (6)可以外推得出结论:

        对满足x > 1, y > 1, x + y = s的任意一组解,都有x为合数 或 y为合数        (7)

当拥有(1)(2)(3)(7)四条信息时,就可以得出题解。

现在我们通过程序计算一下。

def isPrime(x):            #判断质数
    flag = True
    if x == 2:
        pass
    elif x > 2:
        for i in range(2, x):
            if x % i == 0:
                flag = False
    return flag

for x in range(2, 50):
    for y in range(x + 1, 101 - x):
        if (x * y == 52):
            if isPrime(x) or isPrime(y):
                flag1 = True
                s = x + y
                for i in range(2, s):
                    if isPrime(i) and isPrime(s - i):
                        flag1 = False

                if flag1 == True:
                    print("x = {}, y = {}".format(x, y))

运行程序可以直接得出结果x = 4, y = 13。

我们再从S的视角看一下。

S拥有的是(1)(2)(4)(7)四条信息,随后增加一条:

        (1)(2)(3)(7) → x, y         (8)

(1)(2)(7)是两人共有的信息,加上(3)能够得到x与y的值,加上(4)却得不到。

这是为什么?我们在满足x + y = 17的条件下,假定一个解,比如x = 6, y = 11,此时把x * y的值修改一下,从4 * 13 = 52改成6 * 11 = 66,再运行程序可以得到两个结果:x = 2, y = 33和x = 6, y = 11。

之所以出现上述情况,是因为当x + y != 52时,S可以得到多组解。即当且仅当x + y = 52时,S能够得到唯一的一组解。我们运行一下如下程序:

def isPrime(x):        #判断质数
    flag = True
    if x == 2:
        pass
    elif x > 2:
        for i in range(2, x):
            if x % i == 0:
                flag = False
    return flag

for x in range(2, 17):
    y = 17 - x
    if y <= x:
        break
    else:
        p = x * y
        a = []          #这个列表用于存储解
        for temp1 in range(2, p):           #临时寻找一组值,假定其为解
            for temp2 in range(temp1, p):
                if temp2 < temp1:
                    break
                else:
                    if temp1 * temp2 == p:
                        a.append([temp1, temp2])
        print(a)
        tempa = []          #用前法解题,看能得到几组解
        for group in a:
            if isPrime(group[0]) or isPrime(group[1]):
                flag1 = True
                temps = group[0] + group[1]
                for i in range(2, temps):
                    if isPrime(i) and isPrime(temps - i):
                        flag1 = False

            if flag1 == True:
                tempa.append([group[0], group[1]])
    print(p, tempa)         #输出不同乘积对应的解

运行这个程序,我们得到如下结果:

30 [[2, 15], [5, 6]]
42 [[2, 21], [3, 14]]
52 [[4, 13]]
60 [[3, 20], [4, 15], [5, 12], [6, 10]]
66 [[2, 33], [6, 11]]
70 [[2, 35], [7, 10]]
72 [[3, 24], [4, 18], [6, 12], [8, 9]]

那么我们可以看到,只有当乘积为52时,能够得到唯一的一组解。那么答案就很明了,S之所以能够得出解,是因为:

        存在唯一的p = x * y使得当x, y满足(1)(2)(4)(7)时有唯一解         (9)

那么,想要得出题目的解,只需把不满足(9)的解都舍去,即只留下上述结果有唯一解的一行,即52 [[4, 13]]。

完整版求解代码如下。

def isPrime(x):
    flag = True
    if x == 2:
        pass
    elif x > 2:
        for i in range(2, x):
            if x % i == 0:
                flag = False
    return flag

"""寻找一组x与y的解,满足x + y = 17, p = x * y进行一次因数分解后,都有x或y为合数,
但是只有一个p的值能得到一组解。"""
for x in range(2, 17):
    y = 17 - x
    if y > x:
        p = x * y
        a = []
        for temp1 in range(2, p):           #临时寻找一组值,假定其为解
            for temp2 in range(temp1, p):
                if temp2 < temp1:
                    break
                else:
                    if temp1 * temp2 == p:
                        a.append([temp1, temp2])
        tempa = []          #用前法解题,看能得到几组解
        for group in a:
            if isPrime(group[0]) or isPrime(group[1]):
                flag1 = True
                temps = group[0] + group[1]
                for i in range(2, temps):
                    if isPrime(i) and isPrime(temps - i):
                        flag1 = False

            if flag1 == True:
                tempa.append([group[0], group[1]])
                #若得到一组以上的解,则说明不是这个值
        if len(tempa) == 1:
            print("x = {}, y = {}".format(tempa[0][0],tempa[0][1]))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值