|
楼主 |
发表于 2003-6-19 20:57:12
|
显示全部楼层
采用分步范围缩小的方法。
1. 两个人刚拿到数字时,没有其他条件,可以确定的是孙数字的范围是 4 - 9801, 是2-99的乘积的范围。庞的数字范围是4-198, 即2-99的和的范围。
2.庞说自己不知道两个数字,孙也一定不知道两个数字。
这说明孙根据乘积不能唯一的分解出两个数,孙就可以从4-9801中去掉所有的唯一分解的数。(好多人说排除两个素数,这是不准确的,例如8=2*4,不是两个素数但是只能唯一的分解,也应该排除)。
而这时庞可以排除的数就更多了,他可以确定孙的数字不是唯一分解数,也就是说:庞的数字分成两个数的和,这两个数的乘积必须还可以按其它方式分解,否则庞不能肯定孙的数的唯一分解性质。例如:庞的数字为6,他觉得原来的数字可以是[2,4], [3,3]. 但是2*4=8, 如果孙有数字8就可以肯定了,既然庞说孙无法肯定,可以排除庞有6的可能。
for M = 4 to 198
for I = 2 to 99
分解M为两个数 I, M-I. 如果M-I不在2-99范围就继续.
计算乘积 I * (M-I) ,如果乘积的分解是唯一就排除M. 否则记录M和乘积的列表。
这一步的结果是:
庞的数可能 孙的相应的可能
11 [18, 24, 28, 30]
17 [30, 42, 52, 60, 66, 70, 72]
23 [42, 60, 76, 90, 102, 112, 120, 126, 130, 132]
27 [50, 72, 92, 110, 126, 140, 152, 162, 170, 176, 180, 182]
29 [54, 78, 100, 120, 138, 154, 168, 180, 190, 198, 204, 208, 210]
35 [66, 96, 124, 150, 174, 196, 216, 234, 250, 264, 276, 286, 294, 300, 304, 306]
37 [70, 102, 132, 160, 186, 210, 232, 252, 270, 286, 300, 312, 322, 330, 336, 340, 342]
41 [78, 114, 148, 180, 210, 238, 264, 288, 310, 330, 348, 364, 378, 390, 400, 408, 414, 418, 420]
47 [90, 132, 172, 210, 246, 280, 312, 342, 370, 396, 420, 442, 462, 480, 496, 510, 522, 532, 540, 546, 550, 552]
53 [102, 150, 196, 240, 282, 322, 360, 396, 430, 462, 492, 520, 546, 570, 592, 612, 630, 646, 660, 672, 682, 690, 696, 700, 702]
3. 孙说它知道了, 所以孙的数字只能出现在上面的其中一行,否则它不能确定。把列表中重复出现的数字去掉, 结果是:
11 [18, 24, 28]
17 [52]
23 [76, 112, 130]
27 [50, 92, 110, 140, 152, 162, 170, 176, 182]
29 [54, 100, 138, 154, 168, 190, 198, 204, 208]
35 [96, 124, 174, 216, 234, 250, 276, 294, 304, 306]
37 [160, 186, 232, 252, 270, 336, 340]
41 [114, 148, 180, 238, 288, 310, 348, 364, 378, 390, 400, 408, 414, 418]
47 [132, 172, 246, 280, 370, 442, 480, 496, 510, 522, 532, 540, 550, 552]
53 [102, 240, 282, 360, 430, 492, 520, 570, 592, 612, 630, 646, 660, 672, 682, 690, 696, 700, 702]
孙取右侧的任何一个数字都可以确定庞的数字,所以能解出结果。
4.庞说它也知道了。庞如果确定孙的数字?除非庞的数字唯一决定孙的数字,上面的数字中
只有 和为17 和 积为52 了。 下面的谁都会解了。
[code:1]
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
bool only(int N) {
int count = 0;
for(int i=2; i< int(sqrt((double)N)) + 1; i++) {
if(i > 99) break;
if(N/i > 99) continue;
if(N/i*i == N) {
count++;
if(count == 2) return false;
}
}
return true;
}
vector<int> only_list;
vector<int> M_set;
vector< vector<int> > N_set;
bool find(vector<int> v, int a) {
vector<int>::iterator it;
for(it = v.begin(); it != v.end(); it++)
if(*it == a) return true;
return false;
}
void show(vector<int> v) {
vector<int>::iterator it;
cout << "[";
for(it = v.begin(); it != v.end(); it++)
cout << *it << " ";
cout << "]";
}
void my_del(vector<int>& a, vector<int>::iterator ia) {
vector<int>::iterator tmp;
for( tmp = ia+1 ; tmp<a.end(); tmp++ ) {
*ia = *tmp;
ia++;
}
a.erase(ia);
}
void remove_between(vector<int>& a, vector<int>& b) {
vector<int>::iterator ia, ib;
for(ia=a.begin(); ia<a.end(); ia++) {
int del = 0;
for(ib=b.begin(); ib<b.end(); ib++)
if(*ia == *ib) {
del = 1;
my_del(b,ib);
}
if(del) my_del(a,ia);
}
}
void remove_same(vector< vector<int> >& v) {
int len = v.size();
for(int i=0; i<len-1; i++)
for(int j=i+1;j<len;j++)
remove_between(v[i],v[j]);
}
int main()
{
for(int i=4;i<=99*99;i++)
if(only(i)) only_list.push_back(i);
vector<int> N_list;
for(int M=4; M<199; M++) {
N_list.clear();
int ok = 1;
for(int i=2; i<100; i++) {
int j = M - i;
if(j>99) continue;
if(j<2) break;
int N = i * j;
if(find(only_list,N)) {
ok = 0;
break;
} else {
if(!find(N_list,N)) N_list.push_back(N);
}
}
if(ok) {
M_set.push_back(M);
N_set.push_back(N_list);
}
}
remove_same(N_set);
for(int i=0; i<M_set.size(); i++) {
cout << M_set[i] << " ";
show(N_set[i]);
cout << endl;
}
cout << "\n";
for(int i=0;i<N_set.size();i++) {
if(N_set[i].size() != 1) continue;
int b = - M_set[i];
int c = N_set[i][0];
cout << "sum: " << -b << ",product: " << c << endl;
int D = int(sqrt((double)b*b-4*c));
int x1 = (-b+D)/2;
int x2 = (-b-D)/2;
cout << "2 numbers are: " << x1 << " , " << x2 << endl;
}
return 0;
}
[/code:1] |
|