转一道题的解法 既学知识又拿分,竟然每人看! (100分)

  • 主题发起人 主题发起人 铁盒子
  • 开始时间 开始时间

铁盒子

Unregistered / Unconfirmed
GUEST, unregistred user!
孙庞猜数的手算推理解法
孙膑,庞涓都是鬼谷子的徒弟;
一天鬼出了这道题目:他从2到99中选出两个不同的整数,把积告诉孙,把和告诉庞;
庞说:我虽然不能确定这两个数是什么,但是我肯定你也不知道这两个数是什么。
孙说:我本来的确不知道,但是听你这么一说,我现在能够确定这两个数字了。
庞说:既然你这么说,我现在也知道这两个数字是什么了。

1)按照庞的第一句话的后半部分,我们肯定庞知道的和S肯定不会大于54。

因为如果和54<S<54+99,那么S可以写为S=53+a,a<=99。如果鬼谷子选的两个数字
恰好是53和a,那么孙知道的积M就是M=53*a,于是孙知道,这原来两个数中至少有
一个含有53这个因子,因为53是个素数。可是小于100,又有53这个因子的,只能是
53本身,所以孙就可以只凭这个积53*a推断出这两个数术53和a。所以如果庞知道的
S大于54的话,他就不敢排除两个数是53和a这种可能,也就不敢贸然说“但是我肯定
你也不知道这两个数是什么”这种话。

如果53+99<S<=97+99,那么S可以写为S=97+a,同以上推理,也不可能。

如果S=98+99,那么庞可以立刻判断出,这两个数只能是98和99,而且M只能是98*99,
孙也可以知道这两个术,所以显然不可能。

2)按照庞的第一句话的后半部分,我们还可以肯定庞知道的和S不可以表示为两个素数
的和。

否则的话,如果鬼谷子选的两个数字恰好就是这两个素数,那么孙知道积M后,就可以
得到唯一的素因子分解,判断出结果。于是庞还是不敢说“但是我肯定你也不知道这两
个数是什么”这种话。

根据哥德巴赫猜想,任何大于4的偶数都可以表示为两个素数之和,对54以下的偶数,
猜想肯定被验证过,所以S一定不能是偶数。

另外型为S=2+p的奇数,其中p是奇素数的那些S也同样要排除掉。

还有S=51也要排除掉,因为51=17+2*17。如果鬼谷子选的是(17,2*17),那么孙知道
的将是M=2*17*17,他对鬼谷子原来的两数的猜想只能是(17,2*17)。(为什么51要单
独拿出来,要看下面的推理)

3)于是我们得到S必须在以下数中:
11 17 23 27 29 35 37 41 47 53

另外一方面,只要庞的S在上面这些数中,他就可以说“但是我肯定你也不知道这两个
数是什么”,因为这些数无论怎么拆成两数和,都至少有一个数是合数(必是一偶一
奇,如果偶的那个大于2,它就是合数,如果偶的那个等于2,我们上面的步骤已经保
证奇的那个是合数),也就是S只能拆成
 a) S=2+a*b 或 b) S=a+2^n*b
这两个样子,其中a和b都是奇数,n>=1。
那么(下面我说的“至少两组数”中的两组数都不相同,而且的确存在(也就是那些
数都小于100)的理由我就不写了,根据条件很显然)
 a)或者孙的M=2*a*b,孙就会在(2*a,b)和(2,a*b)至少两组数里拿不定主意(a和
  b都是奇数,所以这两组数一定不同);
 b)或者M=2^n*a*b,
  如果n>1,那么孙就会在(2^(n-1)*a,2*b)和(2^n*a,b)至少两组数里拿不定主意;
  如果n=1,而且a不等于b,那么孙就会在(2*a,b)和(2b,a)至少两组数里拿不定主
  意;
  如果n=1,而且a等于b,这意味着S=a+2*a=3a,所以S一定是3的倍数,我们只要
  讨论S=27就可以了。27如果被拆成了S=9+18,那么孙拿到的M=9*18,他就会在
  (9,18)和(27,6)至少两组数里拿不定主意。
 (上面对51的讨论就是从这最后一种情况的讨论发现的,我不知道上面的论证是否
 过分烦琐了,但是看看51这个“特例”,我怀疑严格的论证可能就得这么烦)



现在我们知道,当且仅当庞得到的和数S在
C={11, 17, 23, 27, 29, 35, 37, 41, 47, 53}
中,他才会说出“我虽然不能确定这两个数是什么,但是我肯定你也不知道这两个数
是什么”这句话

孙膑可以和我们得到同样的结论,他还比我们多知道那个M。

4)孙的话“我现在能够确定这两个数字了”表明,他把M分解成素因子后,然后组合成
关于鬼谷子的那两个数的若干个猜想中,有且仅有一个猜想的和在C中。否则的话,他
还是会在多个猜想之间拿不定主意。

庞涓听了孙的话也可以得到和我们一样的结论,他还比我们多知道那个S。

5)庞的话“我现在也知道这两个数字是什么了”表明,他把S拆成两数和后,也得到了
关于鬼谷子的那两个数的若干个猜想,但是在所有这些拆法中,只有一种满足4)里的
条件,否则他不会知道究竟是哪种情况,使得孙膑推断出那两个数来。

于是我们可以排除掉C中那些可以用两种方法表示为S=2^n+p的S,其中n>1,p为素数。
因为如果S=2^n1+p1=2^n2+p2,无论是(2^n1,p1)还是(2^n2,p2)这两种情况,孙膑都
可以由M=2^n1*p1或M=2^n2*p2来断定出正确的结果,因为由M得到的各种两数组合,
只有(2^n,p)这样的组合,两数和才是奇数,从而在C中,于是孙膑就可以宣布自己知道
了是怎么回事,可庞涓却还得为(2^n1,p1)还是(2^n2,p2)这两种情况犯愁。

因为11=4+7=8+3,23=4+19=16+7,27=4+23=16+11,35=4+31=16+19,37=8+29=32+5,
47=4+43=16+31。于是S的可能值只能在
17 29 41 53
中。让我们继续缩小这个表。

29不可能,因为29=2+27=4+25。无论是(2,27)和(4,25),孙膑都可以正确判断出来:
 a)如果是(2,27),M=2*27=2*3*3*3,那么孙可以猜的组合是(2,27)(3,18)(6,9),
  后面两种对应的S为21和15,都不在C中,故不可能,于是只能是(2,27)。
 b)如果是(4,25),M=4*25=2*2*5*5,那么孙可以猜的组合是(2,50)(4,25)(5,20)
  (10,10)。只有(4,25)的S才在C中。
可是庞涓却要为孙膑的M到底是2*27还是4*25苦恼。

41不可能,因为41=4+37=10+31。后面推理略。

53不可能,因为53=6+47=16+37。后面推理略。

研究一下17。这下我们得考虑所有17的两数和拆法:
(2,15):那么M=2*15=2*3*5=6*5,而6+5=11也在C中,所以一定不是这个M,否则4)
的条件不能满足,孙“我现在能够确定这两个数字了”的话说不出来。
(3,14):那么M=3*14=2*3*7=2*21,而2+21=23也在C中。后面推理略。
(4,13):那么M=4*13=2*2*13。那么孙可以猜的组合是(2,26)(4,13),只有(4,13)
的和在C中,所以这种情况孙膑可以说4)中的话。
(5,12):那么M=5*12=2*2*3*5=3*20,而3+20=23也在C中。后面推理略。
(6,11):那么M=6*11=2*3*11=2*33,而2+33=35也在C中。后面推理略。
(7,10):那么M=7*10=2*5*7=2*35,而2+35=37也在C中。后面推理略。
(8,9):那么M=8*9=2*2*2*3*3=3*24,而3+24=27也在C中。后面推理略。

于是在S=17时,只有(4,13)这种情况,孙膑才可以猜出那两数是什么,既然如此,庞
涓就知道这两个数是什么,说出“我现在也知道这两个数字是什么了”。

听了庞涓的话,于是我们也知道,这两数该是(4,13)。
 
看不懂,刚开始时为什么S不能大于54我就不明白了,54以上的可以表示成53+a,没有什么意义嘛,难道53是一个很特别的数?“因为如果和54<S<54+99,那么S可以写为S=53+a,a<=99。如果鬼谷子选的两个数字
恰好是53和a,那么孙知道的积M就是M=53*a,于是孙知道,这原来两个数中至少有
一个含有53这个因子,因为53是个素数。”很是疑惑,比如说S=47+10=53+4的,孙知道的结果是470,不过他也不知道是47和10还是94和5啊
 
这样理解
庞肯定孙不知道这两个数是什么。
S=47+10=53+4的,如果孙知道的结果是470,孙是不知道是47和10还是94和5,
但是,庞不敢肯定孙不知道,因为庞并不知积是多少,如果积是53*4=212呢?
 
看明白了。
第一步應該先排除兩個素數的情況
然後,排除53以上的數是這樣考慮的。53為>50(100/2)的最小的素數,
S=53 + a(a一定得為合數),這樣無論如何分解,肯定有53這個因子
因為 M=53*a=52*a1*a2...,設a1=2,不可能有(53*2)*(a2*a3...)
因為53*2=106>100,a1也更不可能大於2了。所以可排除53以上的s

 
没错
甲说:“我不知道X和Y是多少,但你也不知道”
这句话表示,不是两个质数,因为如果是2个质数,那么乙肯定知道。
但甲只知道两数的和,怎么知道不是两个质数呢?肯定是和的所有分解都不会是两个质数相加。
由此可得到和的集合。
乙说:“我知道X和Y分别是多少了!”
甲说:“我也知道了”
表示所有相加组合中,两数的积的所有分解,的和,只有1个是在和的集合中。
下面是算法:(一个上午啊…………)
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
function IsZhi(a: integer): BOOLEAN;
function Check2(a: integer): BOOLEAN;
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
i, j: integer;
k:boolean;
begin
memo1.Lines.Clear;
for i := 6 to 60do
begin
for j := 2 to i div 2do
begin
if not IsZhi(j) then
begin
k := true;
continue;
end
else
if IsZhi(i - j) then
begin
k := false;
break;
end;
end;
if k then
memo1.Lines.Add(inttostr(i));
end;
Button2Click(nil);

end;

function TForm1.IsZhi(a: integer): BOOLEAN;
var
i: integer;
begin
result := true;
for i := 2 to a - 1do
if (a mod i) = 0 then
begin
result := false;
Exit;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
i, j, n, m, x, y: Integer;
begin
for i := 0 to memo1.Lines.Count - 1do
begin
n := StrToInt(memo1.Lines.Strings);
m := 0;
for j := 2 to n div 2do
begin
if Check2(j * (n - j)) then
begin
m := m + 1;
x := j;
y := n - j;
end;
end;
if m = 1 then
begin
showmessage(inttostr(x)+' -- '+inttostr(y));
Exit;
end;
end;
end;

function TForm1.Check2(a: integer): BOOLEAN;
var
i, n, m: Integer;
begin
result := false;
n := 0;
m := 0;
for i := 2 to a div 2 - 1do
begin
if a mod i <> 0 then
Continue
else
if (memo1.Lines.IndexOf(IntToStr(i + (a div i))) <> -1) and (i <> m) then
begin
m := a div i;
n := n + 1;
end;
end;
if n = 1 then
result := true;

end;

end.
 
多人接受答案了。
 
基本上明白,佩服孙哥,庞哥如此电算。
继续佩服中。我的脑袋为什么就没那么快呢。
 
不是很明白
 
后退
顶部