下面是解答全部用C++编写,复制后保存为CPP文件可以在VC++6.0里直接编译运行)
程序A:
//---------------------------------------------------------------------------------------------------------------------
#include<iostream>
#include<string>
#include<math.h>
using namespace std;
//采用小素数表,以及选择恰当的上界以及步长可以提高效率 //小素数表,可以减少无用试探,规模可以自己决定
const int littlePrime[12] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 };
//问题类
class GoldbachConjecture
{
public:
//判断num是否是素数
bool isPrime(int num)
{
if( num <= 1 )
{
return false;//小于等于0时当然不是素数
}
int i,j,max;
max = int( sqrt(num) );//最大试探值,num如果能被整除,则可以写为m*n,如果m<=n
//则显然有m<=sqrt(num),以sqrt(num)可以免掉后半段的重复试探
//先从质数表开始
for( i = 0; i<12 && littlePrime<=max; i++ )
{
if( num % littlePrime == 0 )//可以被整除,是合数,返回false
return false;
}
//如果表里的数还没过界,则从41开始试探
if( i==12 )
{
for( j = 41; j<=max; j=j+2 )//显然偶数不用试探了,因为进入这里前提是2不能整除num
{
if( num % j == 0 )//可以被整除,是合数,返回false
return false;
}
}
//试探完,可以确定num是素数
return true;
}
bool getPrimePair(int num)//找出满足条件的素数对,找不到输出0
{
if( num<=3 )//小于等于3显示无法找到,输出0
{
cout<<0<<endl;
return false;
}
if( num%2 == 1 )//奇数可以迅速处理,其中一个数一定是2,因为只有2是偶素数
{
if(isPrime(num-2)) //num-2是素数,则2 num-2是满足条件的素数对,显然2最小
{
cout<<2<<' '<<num-2<<endl;
return true;
}
else//否则一定没有,直接输出0
{
cout<<0<<endl;
return false;
}
}
//剩下就是处理关键的大偶数了
int i,j,k,max;
max = num/2;//只用试前半,后半是重复的,由于是和,取num/2
//从素数表开始试探
for( i = 0; i<12&&littlePrime<=max; i++ )
{
j = num - littlePrime;
if( isPrime(j) )//素数表里的已经是素数,只用判断j是否为素数
{
//j同时也是素数,由于从小到大试探,且上限定为num/2
//则肯定满足输出对前一个数不大于后一个数
//并且前一个数是满足条件的所有素数对中最小的数
cout<<littlePrime<<' '<<j<<endl;
return true;
}
}
//超过素数表,从41开始找素数继续试探
if( i==12 )
{
for( k = 41; k<=max; k=k+2 )
{
//41往后偶数肯定不是素数,每次+2
if( isPrime(k) && isPrime(num-k) )
{
//找到素数对,输出
cout<<k<<' '<<(num-k)<<endl;
return true;
}
}
}
//过界,可以肯定找不到合题意的素数对
cout<<0<<endl;
return false;
}
};
int main()
{
int i;
//建立一个问题对象
GoldbachConjecture GC;
//得到数
cin>>i;
//输出结果
GC.getPrimePair(i);
return 0;
}
//------------------------------------------------------------------------
程序B:
//------------------------------------------------------------------------
#include<iostream>
#include<string>
#include<math.h>
//有n个雷,建立一个有n个结点的图,只有当两个雷距离在5米之内,两个雷的结点之间才有
//边相连,用邻接矩阵存放图,只要从触发雷对应结点开始启遍历该结结点所在的连通分量,
//则所有访问的结点都是可以被触发的
//维护一个访问数组,然后从前往后输出访问标志为ture的结点输出序号即可实现升序输出
using namespace std;
//距离最大值的平方,用来两个雷是否可以互相引爆
const int maxLengthSqrt = 25;
//问题类
class Mines
{
public:
int numMines; //雷数
int FirstTrigger; //第一个触发的雷的序号,指的存放图对应序号,为(实际序号-1)
bool **disGraph;//图的邻接矩阵
//构造函数,num为雷数,first为第一个触发的雷的序号
//listMinesPos是一个长度为2*num的数组,每个雷的坐标X,Y存入连续两个单元
//按照序号依次存入listMinesPos
Mines(int num, int* listMinesPos, int first )
{
numMines = num;
FirstTrigger = first;
//分配矩阵空间
disGraph = new bool* [numMines];
int i,j;
for(i=0; i<numMines; i++)
{
disGraph = new bool[numMines];
for(j=0; j<numMines; j++)
{
//赋初值
disGraph[j] = false;
}
}
//任意两个结点计算距离,判断是否有边相连
for(i=0; i<numMines; i++)
{
for( j = i+1; j<numMines; j++ )
{
//距离平方<=最大距离平方,则连上一条边
if(getDisSqrt(listMinesPos[2*i],listMinesPos[2*i+1],
listMinesPos[2*j],listMinesPos[2*j+1])<=maxLengthSqrt)
{
//注意是无向图,对称存放
//当然可以用三角矩阵压缩存放,不过会增加复杂度和可读性
disGraph[j] = true;
disGraph[j] = true;
}
}
}
}
~Mines()
{
//记得归还动态分配的空间
int i;
for(i=0; i<numMines; i++)
{
delete []disGraph;
}
delete []disGraph;
}