素數是一類很有用的數,至今為止,沒有任何人發現素數的分布規律,也沒有人能用一個公式計算出所有的素數。但素數的判斷和建立是有法可循的。
常用方法一:最佳化的枚舉法(效率O(n*sqrt(n))),按照素數的定義從2-枚舉到SQRT(N)。方法簡單易懂,這個用於判斷可以,但是建立的話時間過長。
int isprime(int n){ for (int i=2;i<=sqrt(n);i++) { if (n%i==0) return 0; } return 1;}
常用方法二:篩法。(效率O(n))
篩法的意思遵循一個原則,素數i的倍數一定不是素數。
(以下為轉載)
一個簡單的篩素數的過程:n=30。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
第 1 步過後2 4 ... 28 30這15個單元被標成false,其餘為true。
第 2 步開始:
i=3; 由於prime[3]=true, 把prime[6], [9], [12], [15], [18], [21], [24], [27], [30]標為false.
i=4; 由於prime[4]=false,不在繼續篩法步驟。
i=5; 由於prime[5]=true, 把prime[10],[15],[20],[25],[30]標為false.
i=6>sqrt(30)演算法結束。
第 3 步把prime[]值為true的下標輸出來:
for(i=2; i<=30; i++)
if(prime[i]) printf("%d ",i);
結果是 2 3 5 7 11 13 17 19 23 29
篩法還可以最佳化,於是有了方法三:最佳化篩法。
把所有偶數都去掉,時間複雜度進一步降低。
模板:
int prime(int a[],int n){ int i,j,k,x,num,*b; n++; n/=2; b=(int *)malloc(sizeof(int)*(n+1)*2); a[0]=2; a[1]=3; num=2; for (i=1;i<=2*n;i++) b[i]=0; for (i=3;i<=n;i+=3) for (j=0;j<2;j++) { x=2*(i+j)-1; while (b[x]==0) { a[num++]=x; for (k=x;k<=2*n;k+=x) b[k]=1; } } return num;}
關於素數,還有一些好玩的性質:
1、哥德巴哈猜想,著名的素數問題,任何一個大於4的偶數都可以拆成2個素數。
2、孿生素數問題,差為2的素數有無窮對。
3、反證法的第一個試刀案例,歐幾裡得證明了世界上沒有最大的素數,這玩意沒有最大隻有更大
4、目前人類(電腦?)算出來的最大素數為2^43112609-1,一個723W+位的數字.....