文章目錄

这题来自马丁加德纳的趣味数学,这个号称“无解的难题”的最初形式, 也是流传最广泛的形式如下. 某天, 老师召集了他最聪明的两个学生P和S, 递给每人一张纸条, 然后说, 有两个不小于2的整数x和y,满足x != y, 且x + y < 100. 给P的纸条上写有两个数的乘积p = x * y, 给S的纸条上写有两个数的和s = x + y, 请他们确定这两个数具体的值是多少. 于是P和S进行对话:

  1. P: 我无法确定这两个数是多少.
  2. S: 我知道你无法确定这两个数是多少.
  3. P: 既然这样, 那我知道这两个数是多少了.
  4. S: 既然这样, 那我也知道这两个数是多少了.

请读者根据以上信息确定这两个数是多少.

稍加分析后,可以写出程序用计算机来找答案,当然手算也是可以的。

  1. P: 我无法确定这两个数是多少. 这里说的是乘积p有多种分解,所以无法确定x和y是什么。如28有2 14, 4 7两种分解。
  2. S: 我知道你无法确定这两个数是多少.这里说的是s = x + y中的x和y的乘积都满足条件1,即有多种分解。如11等于2 + 9, 3 + 8, 4 + 7, 5 + 6, 而2 9等于18有2 9, 3 6两种分解 3 8等于24有2 12, 3 8, 4 6三种分解,4 7等于28有2 14, 4 7两种分解, 5 6等于30有2 15, 3 10, 5 6三中分解。
  3. P: 既然这样, 那我知道这两个数是多少了. 这里说的是,在p的所有分解x * y中只有一个x + y满足条件2
  4. S: 既然这样, 那我也知道这两个数是多少了. 这里说的是在s = x + y中,只有一个x * y满足条件3

于是写Python代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# coding:utf-8
from math import sqrt


def pone(p, u):
c = 0
for x in range(2, int(sqrt(p)) + 1):
if p % x == 0 and x + int(p / x) < u:
c += 1
return c >= 2


def sone(s, u):
for x in range(2, int(s / 2)):
y = s - x
if not pone(x * y, u):
return False
return True


def ptwo(p, u):
c = 0
for x in range(2, int(sqrt(p)) + 1):
if p % x == 0 and x + int(p / x) < u:
y = int(p / x)
if sone(x + y, u):
c += 1
return c == 1


def stwo(s, u):
c = 0
for x in range(2, int(s / 2)):
y = s - x
if ptwo(x * y, u):
c += 1
return c == 1


if __name__ == "__main__":
u = 100
for x in range(2, int(u / 2)):
for y in range(x + 1, u - x):
p = x * y
s = x + y
if pone(p, u) and sone(s, u) and ptwo(p, u) and stwo(s, u):
print("x: %d, y: %d, p: %d, s: %d " % (x, y, p, s))
文章目錄