题目描述: 两个确定的数字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]))