编程训练[C语言]——质数筛法

实现一个程序,输入n,输出1~n的非质数,n最大为100。

【样例】

Input
20

Output(一行输出五个数,每个数占宽度6)
     1      2      3      5      7 
    11     13     17     19 

【代码】
(所用算法和常见错误讲解在注释里)

//  算法描述:任何数都可以写成若干质数的乘积,比如18=2*3*3,16=2^4,现将一个数分解成若干质数的积,
//  然后将这些质数中的最小值作为p,剩余质数的积作为q,则任何质数都能写成(p^k)*q的形式。
//
//  指数筛法就是将一系列的数字中,非质数进行删除,比较笨的办法是将质数从小到大排列,然后依次删除质数的若干倍,但是这样会有重复删除,
//  影响效率(比如删除2的若干倍和3的若干倍均会删除6)。
//
//  不会重复删除的方式:如果已知p是质数,先删除p的2,3……次方,然后找出比p大没有删除的数作为q,删除pq,p^2*q,……,直到p^k*q超过范围,则选取比q大没有被删除的数作为新的q进行同上操作,
//  直到pq的值超过范围,则寻找下一个比p大没有被删除的数作为新的p,重复上面的过程。

#include<stdio.h>

#define MAXSIZE 105

//返回比a[currentIndex]大尚未被删除的数在数组中的下标
int NextIndex(int *a,int currentIndex,int size){
    int index;
    for(index=currentIndex+1;index<size;index++){
        if(a[index]!=0)
            break;
    }
    if(index>=size){
        return -1;
    }
    else{
        return index;
    }
}

//用于计算a的b次方
int Sqrt(int a,int b){
    int result=1;
    if(b!=0){
        for(int i=1;i<=b;i++){
            result*=a;
        }
        return result;
    }
    else{
        return 1;
    }
}

int main(){
    int a[MAXSIZE];
    int size;
    int p,q;
    int printcount=0;
    while(scanf("%d",&size)==1){
        for(int i=0;i<size;i++){
            a[i]=i+1;
        }
        for(p=2;p<=size;p=NextIndex(a,p-1,size)+1){
            if(p==0)break;  //不要忽略这一句,否则容易陷入死循环
//            printf("p is %d\n",p);
            for(int i=2;Sqrt(p,i)<=size;i++){   // 易错点:容易误将p也删去,正确的做法是从p^2开始删除,然后依次删除p^3……
                a[Sqrt(p,i)-1]=0;
            }
            for(q=NextIndex(a,p-1,size)+1;p*q<=size;q=NextIndex(a,q-1,size)+1){     //错点,for的第3个参数少了“+1”,导致陷入死循环,q的值一直是4
//                printf("q is %d\n",q);
                if(q==0){
                    break;
                }
                else{
                    for(int j=1;Sqrt(p,j)*q<=size;j++){
                        a[Sqrt(p,j)*q-1]=0;
                    }
                }
            }
        }
        for(int i=0;i<size;i++){
            if(a[i]!=0){
                if(printcount%5==0){
                    printf("\n");
                }
                printf("%6d ",a[i]);
                printcount++;
            }
        }
        printf("\n");
        printcount=0;
    }
    return 0;
}

发布了36 篇原创文章 · 获赞 41 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/umbrellalalalala/article/details/87935775