智力题

来源:互联网 发布:相与枕藉乎舟中的乎 编辑:程序博客网 时间:2024/04/16 18:56
看到一个智力题,做了一会不想没成功,郁闷,看来还是数学功底不够啊。
 
 两个聪明人闲来无事,邀他们的秘书玩这样一个游戏:
 秘书在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

原创粉丝点击