早晨突然发现前些日子,某个酒足饭饱的午后,黄哥问的一个傻问题——当时也没有听清楚——居然是一道编程题!而且是很有难度的一道,呵呵,难得黄哥能问出这种问题!!决定解决之~~~~~~~~~~~~
题目为(ACM/ICPC Regional Contest Southeastern European 2001. Problem C. Secret Numbers),原文如下:
Secret Numbers
Problem
Two natural numbers a and b are chosen (1<a<b). Person M is told the multiple of a and b (a*b), and person S is told the sum of a and b (a+b). The discussion between M and S goes like this:M: I do not know the numbers a and b.
S: I do not know them either, but I knew you would not know them.
M: Now I know the numbers!
S: Now I know them, too!
Input
The input file contains pairs of natural numbers x and y (2<=x<y<=550), one pair per line. The input is guaranteed to be correct.
Output
For each pair x, y, find all pairs of a and b, such that x<=a<b<=y and that the given discussion is possible. Write these pairs in a single line, and finish that line with "no more pairs." if there are a and b found in the given range, or write simply "no pairs." if there are not. Separate the numbers of a pair with a comma, terminate each pair with a semi-colon, and separate different pairs with a blank after the semi-colon, as shown in the example below.
Sample Input
2 10 2 20
Output for the Sample Input
no pairs. 4,13; no more pairs.
简单解释一下:
有两个数a和b(1<a<b)。M先生知道a*b的值,S先生知道a+b的值,两人有如下的对话:
M先生: 我不知道a和b的值。
S先生: 我也不知道,而且之前我还知道你不知道。
M先生: 我现在知道a和b的值了。
S先生: 我现在也知道a和b的值了。
给定x和y(2<=x,y<=550),求所有满足对话场景的(a,b)且x<=a<b<=y。假设二位先生都足够聪明且没有撒谎!
你有想法了吗???
幸好足够聪明的博得先生,在参考了N本书后,终于搞定了这个问题!下面来分析一记:
解题的关键是MS两位先生的四句话,而且这四句话是步步递进的,也就是任何满足后一句的数对,必然满足前一句!如果可以将这四句话用四个逻辑判别函数( f1(a,b)~f4(a,b) )表示,就可以在给定的范围内求出所有的满足f4(a,b)的数对!
首先,根据题意先设有两个集合:
M(a,b)={ (x,y)| x*y=a*b 且 1<x<y }
S(a,b)={ (x,y)| x+y=a+b 且 1<x<y }
可以得到如下表格:
| MS两位先生的话 | 实现函数 | 条件 | 返回值 |
| M:我不知道a和b的值。 | bool f1(int a,int b) | |M(a,b)|>1 | true |
|
else |
false | ||
| S:我也不知道,而且之前我还知道你不知道。 | bool f2(int a,int b) | 1、f1(a,b)==true 2、|S(a,b)|>1 3、任取(p,q)∈S(a,b)使得f1(p,q)==true |
true |
|
else |
false | ||
| M:我现在知道a和b的值了。 | bool f3(int a,int b) | 1、f2(a,b)==true 2、只有一对(p,q)∈M(a,b) 满足f2(p,q)==true |
true |
|
else |
false | ||
| S:我现在也知道a和b的值了。 | bool f4(int a,int b) | 1、f3(a,b)==true 2、只有一对(p,q)∈S(a,b) 满足f3(p,q)==true |
true |
|
else |
false |
具体的实现就看代码吧!
执行一下,输入两个数(2~550之间)比如输入2、100就可以知道在 2~100 之间,满足条件的有四组:(4,13)、(4,61)、(16,73)、( 64,73)。
至此程序应该是对的了,但由于没有找到哪个Online Judge上有这题,所以并没有递交过。那就欢迎大家的指正了!!!
参考书目:《算法艺术与信息学竞赛》