C语言实现之100-1000以内素数的等差数列

来源:互联网 发布:网络用语km是什么意思 编辑:程序博客网 时间:2024/05/21 06:29

接上一篇,还是我同学给的题目,最后一个。一开始有点问题,现在改正了。

*写的比较仓促,如果有更简便、执行效率更高的方法还请不吝赐教,当然我的如果有问题请大家给指出。

题目:

        在小于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 <stdio.h>#include <string.h>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个)

总结:

      前几个一直都是用递归,这个用循环吧,可能就是循环那想起来有点乱,但是想清楚其实嵌套的并不复杂。当然我不知道我写的对不对,如果有错还麻烦你告诉我。我也不知道我的这种写法是不是麻烦,这是我很直观想到的方法,如果大家有更好的方法还请不吝赐教。终于发完了,困死我了睡觉