实现一个程序,输入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;
}