看到一个智力题,做了一会不想没成功,郁闷,看来还是数学功底不够啊。
两个聪明人闲来无事,邀他们的秘书玩这样一个游戏:
秘书在2和100之间选两个数,把和给一个人,乘积给另一个,
让他们算出这两个数。于是有了下面的对话:
- 光凭这个乘积,我算不出来。
- 我已经知道你算不出来。
- 那... 我算出来了。
- 那... 我也算出来了。
聪明的你,是否也算出来了?
找了半天,找到一个答案,连程序都有了,真是狠。还有一个更强的数学推理,没完全看懂(跟他推理的逻辑词语不严谨有关),贴在后面。
-- 推理过程:
- 光凭这个乘积,我算不出来。
必然是两个数不同时为质数
- 我已经知道你算不出来。
B知道A第一轮肯定猜不中, 那么这个和, 不可能拆成两个都是质数.
- 那... 我算出来了。
两个数的积, 所能拆出的组合中, 只有一种组合满足前面的两个条件
- 那... 我也算出来了。
两个数的和, 可以拆出的所有组合中, 只有一个组合能满足前面3个条件.
-- 注意: 当MAX_NUMBER>200时, 需要耗时会很长
-- BY OLDWAIN (OLDWAIN@ITPUB.NET), 2001.11
========================================================
*/
#include
#include
#include
//#include
#define MIN_NUMBER 2
#define MAX_NUMBER 100
#define min(a,b) (((a) < (b)) ? (a) : (b))
int isprime(int thenum)
// 判断是否为质数
{
int k;
if(thenum == 1 || thenum == 2)
return 1;
k = sqrt(thenum);
for(int i = 2; i <= k; i ++){
if(thenum % i == 0)
return 0;
}
return 1;
}
int canA1GuestIt(int i, int j)
//
// A第1轮不能猜中, 必然是两个数不同时为质数
//
{
if (isprime(i) && isprime(j)) return 1;
return 0;
}
int canB1GuestIt(int num1, int num2)
// B知道A第一轮肯定猜不中, 那么这个和, 不可能拆成两个都是质数.
{
int i, j, sumer;
sumer = num1 + num2;
for (i = 2; i <= sumer/2; i++)
{
j = sumer - i;
if (isprime(i) && isprime(j) )
return 1;
}
return 0;
}
int canA2GuestIt(int num1, int num2)
//两个数的积, 所能拆出的组合中, 只有一种组合(也即: 给定的num1, num2)满足前面第一轮的两个条件.
{
int i, j, rst, prod;
prod = num1 * num2;
rst = 0;
for (i = 2; i <= min(sqrt(prod), MAX_NUMBER/2); i++)
{
j = prod / i;
if ((i < j ) && (i != num1) && (i * j == prod))
{
if( ( canA1GuestIt(i, j) != 1) && (canB1GuestIt(i, j) != 1) )
rst++;
}
}
if ((rst == 0) /*&& (canB1GuestIt(i0, j0) != 1) */) return 1;
return 0;
}
int canB2GuestIt(int num1, int num2)
// 两个数的和, 可以拆出的所有组合中, 只有一个组合(也即: 给定的num1, num2)能满足前面3个条件.
{
int i, j, sumer, rst;
sumer = num1 + num2;
rst = 0;
for (i = 2; i <= sumer/2; i++)
{
j = sumer - i;
if ( (i != num1)
&& (canA1GuestIt(i,j) != 1)
&& (canB1GuestIt(i, j) != 1)
&& (canA2GuestIt(i,j))
)
rst++;
}
if (rst == 0) return 1;
return 0;
}
int main()
{
int i, j;
for (i = MIN_NUMBER; i< MAX_NUMBER; i++)
for (j = i+ 1; j <= MAX_NUMBER; j++)
{
if (canA1GuestIt(i, j))
continue;
if (canB1GuestIt(i, j))
continue;
if (1 != canA2GuestIt(i, j))
continue;
if (1 != canB2GuestIt(i, j))
continue;
cout<< i <<"/t"<< j << "/tSUM: " << i + j << "/tPRODUCT: " << i * j <
}
return 0;
};
数学推理:
根据积算不出来,表明这个乘积不可以唯一分解的,那就是说,不可能是素数或者两个素数的积,然后b说根据和知道a算不出来,那么b这个和中一定没有两个素数相加的情况,否则,如果他不可能知道a不知道,那么b得到的和一定是奇数,设为 m,而且m-2一定是个合数,由这一点,a就能算出来这两个数,那么表明a的积n的分解方式,只有一种能满足上述条件的,也就是说除了奇数X偶数的情况外,其它的都是偶数X偶数,所以那个奇数一定是个素数,不然比如8*9,就有24*3这种可能,那个偶数一定是2的方次,不然如果是12*5,还有4*15这种可能,b根据这两个数一个是素数,一个是2的方次,就可以知道这两个数是什么,很简单了,就是说这个数必须是
a+2^b的形式,而且,对于c不等于b,且2^c次方小于n的时候,n-2^c都不是素数,这样的情况只有17=4+13.
转自 http://blog.sina.com.cn/s/blog_58adc9e7010009l8.html