/**
*sp.cpp - 解决S先生P先生问题
*author: cuichaox@gmail.com
*
*/
#include <iostream>
#include <cassert>
#include <cmath>
using namespace std;
const int MAX_NUM=99;
//判断一个数是否是素数
bool is_prime(int num);
//满足条件1
bool by_condition_1(int x, int y);
//满足条件2
bool by_condition_2(int x, int y);
//满足条件3
bool by_condition_3(int x, int y);
int main()
{
for(int x=2;x<=MAX_NUM;x++)
for(int y=x;y<=MAX_NUM;y++)
if( by_condition_1(x,y) &&
by_condition_2(x,y) &&
by_condition_3(x,y))
{
cout<<"X = "<<x<<", ";
cout<<"Y = "<<y<<endl;
}
return 0;
}
/**
*判断是否是[2,MAX_NUM]间的素数,为了提高效率,生成素数表.
*@param num 要判断的数
*@return 是否是素数
*
*/
bool is_prime(int num)
{
assert(num >=2);
assert(num <=MAX_NUM);
static bool table[MAX_NUM+1];
static bool is_ready = false;
if(!is_ready)
{
table[0] = false;
table[1] = false;
table[2] = true;
for(int i = 3; i<=MAX_NUM; i++)
{
bool prime_flag = true;
for(int j=2; j<=sqrt(i); j++)
if(table[j] && i%j == 0)
{
prime_flag = false;
break;
}
table[i] = prime_flag;
}
is_ready = true;
}
return table[num];
}
/**
* 满足条件1
* S:我不知道这两个数,但我知道你也不知道
*=>把X+Y拆分成设定范围内两个正整数的和,猜测这两个数,拆分方法不是唯一的;
* 并且,S可以看出,P看到的肯定不能是两个素数的积
*=> X+Y不是4,并且,X+Y不可能是两个素数的和
*/
bool by_condition_1(int x, int y)
{
assert(x<=y);
int sum = x+y;
if(sum == 4)
return false;
for(int i=2; i<=sum/2; i++)
{
if(sum-i<=MAX_NUM && is_prime(i) && is_prime(sum -i))
return false;
}
return true;
}
/**
* 满足条件2
* P:现在我知道这两个数是什么了
* =>把X*Y分解成设定范围内的两个正整数的积,猜测两个数,分解方法虽然不唯一
* 但,能够满足条件1情况的,只有一种分解方法,所以P能够推理出这两个数
*/
bool by_condition_2(int x, int y)
{
assert(x<=y);
int product =x*y;
//统计满足条件1的分解可能
int count_condition_1 =0;
for(int i =2; i<=sqrt(product); i++)
{
if(product %i == 0 && (product/i) <= MAX_NUM)
{
if(by_condition_1(i,product/i))
if(++count_condition_1 >=2)
break;
}
}
if( count_condition_1 == 1)
return true;
return false;
}
/**
*满足条件3
* S:我也知道了
*=>把X+Y拆分成两个正整数的和,猜测这两个数,拆分方法虽然不是唯一的
* 但满足条件2的,只有一种拆分方法.
*/
bool by_condition_3(int x, int y)
{
int sum = x+y;
//统计所有满足条件2的拆分可能
int count_condition_2 = 0;
for(int i=2; i<=sum/2; i++)
{
if(by_condition_2(i,sum-i))
if(++count_condition_2 >= 2)
break;
}
if(count_condition_2 == 1)
return true;
return false;
}
|