接上一篇,还是我同学给的题目,最后一个。一开始有点问题,现在改正了。
*写的比较仓促,如果有更简便、执行效率更高的方法还请不吝赐教,当然我的如果有问题请大家给指出。
题目:
在小于10的素数中有3、5、7组成的等差数列,在小于30的素数中有11、17、23、29组成的等差数列。
试找出区间[100,1000]内的素数构成的最大等差数列(即等差数列包含的素数个数最多)并打印输出。
分析:
(1)要在100-1000中找等差数列,为了提高效率,肯定是先生成100-1000之间的素数表之类的东西,然后再从中找。
(2)注意的是,公差有可能会比较大,以至一个素数和它之后数个素数之后的素数存在等差关系。
思路:
我是这样想的,先生成一个素数表,牺牲点内存省点劲,这个表建1001个元素,直接用下标指代元素,用0表示素数,1表示非素数,因为从100开始,所以之前的就不管了。等差值从2直到900,依次尝试,并从101开始,如果加上公差之后不是素数,则找下一个素数,再从下一个素数开始,直到下一个素数找过1000,在尝试下一个公差,以此搜索所有可能,将长度最大数列的第一个元素、公差和长度记录下来,判断完所有的之后打印出来。
实现:
(这里检索素数用的是筛选的方法,将其中能整出比自己小的素数的数字踢出,应为他们一定是合数,剩下的就是素数了)
#include
#include
int primeNum[1001];
/********************************************************
*函 数:void setPrime() *
*参 数:无 *
*功 能:判断100-1000的素数并将对应下标的数组值置位 *
*返 回:无 *
*********************************************************/
void setPrime()
{
int flag; //标志位,表示存在除1,和他自身之外能被他整除的数字
int loop;
int site = 2;
memset(primeNum, 0, 1000 * sizeof(int)); //初始化数组所在内存区
while(1)
{
flag = 1; //标志位初始化置为
for(loop = site + 1; loop <= 1000; loop++)
{
//判断当时是否是素数(避免重复判断)
if(!primeNum[loop])
{
if(loop % site == 0)
{
primeNum[loop] = 1; //不是素数置位1
}
else
{
if(flag)
{
flag = 0; //清空标志位
site = loop;
}
}
}
}
if(flag)
{
break; //没找到过说明在此之后不再有素数(即查找完毕)
}
}
}
/***************************************************************
*函 数:int getNextPrime(int site) *
*参 数:当前的素数 *
*功 能:判断100-1000的素数中指定素数的下一个素数 *
*返 回:如果100-1000以内有下一个素数返回次数,否则返回-1 *
****************************************************************/
int getNextPrime(int site)
{
while(site < 1001 && primeNum[++site]);
return site > 1000 ? -1 : site;
}
/*****************************
*函 数:int main() *
*参 数:无 *
*功 能:主函数 *
*返 回:无 *
*****************************/
int main()
{
int loop = 1; //公差
int circle;
int lastA = 2; //记录上一次的公差
int lastStart = 101; //记录上一次的数列起始位置
int lastCount = 0; //记录上一次数列长度
int count; //记录此次数列长度
int start; //记录此次数列起始位置
int flag = 1; //标志位,表示以此判断中第一次遇到素数
setPrime();
while(++loop <= 900)
{
for(circle = 101; circle < 1001; circle += loop)
{
//判断标志位,是不是此次判断的第一个
if(flag)
{
flag = 0; //清空标志
start = circle; //记录数列开始元素
count = 0; //重置数列元素个数
}
if(primeNum[circle])
{
flag = 1; //置位标志位
circle = getNextPrime(circle); //判断下一个素数
if(circle < 0)
{
break; //不存在下一个素数,跳出循环,继续进行公差递增后的判断
}
else
{
continue; //继续判断
}
}
count++; //如果执行到这,说明当前的数列目前还满足条件,总量计数递增
}
//判断此次判断的数列总数是否比之前的大
if(count > lastCount)
{
lastCount = count; //记录当前的数列总数
lastA = loop; //记录当前的公差
lastStart = start; //记录当前的数列起始元素
}
}
//循环输出最大数列的所有元素
while(lastCount--)
{
printf("%d ", lastStart);
lastStart += lastA; //计算下一个元素
}
return 0;
}
结果:
101 281 461 641 821
(5个)
总结:
前几个一直都是用递归,这个用循环吧,可能就是循环那想起来有点乱,但是想清楚其实嵌套的并不复杂。当然我不知道我写的对不对,如果有错还麻烦你告诉我。我也不知道我的这种写法是不是麻烦,这是我很直观想到的方法,如果大家有更好的方法还请不吝赐教。终于发完了,困死我了
。