請使用除法的方法用最快的辦法來寫作程式。
解:
1. 質數的基本定義為除了1以及自己以外沒有其他的因數的數,
就可以稱為質數。
2. 沒有其他因數的條件其實等同於沒有其他質因數,
因為合成數可以拆成質數的乘積。
3. 另外,當某數x是合成數的話,那麼就會有x=i*j這樣的式子,
i、j為x的因數;
i、j要嘛就是一個大於根號x,一個小於根號x,
不然就是兩個都等於根號x,因為兩者相乘必須要等於x,
所以不能同時小於或同時大於根號x。
所以我們只要找小於等於根號x的正整數中是否有x的因數,
就可以確信x是否為質數。
4. 既然所有合成數都可以拆成質因數的乘積,
當搜尋一個數是否為質數時,只要看它前面存在的質數,
是否是它的因數,就可以判定了。
5. 有一些判斷是可以直接省略的,
比如2的倍數,除了2以外,絕對不會是質數;
同理,3的倍數也是相同,5的倍數也是。
當考慮不是2的倍數和3的倍數時,
剩下6n+1和6n+5兩種。
考慮到5的倍數的話,為:
30n+1、30n+7、30n+11、30n+13、30n+17、30n+19、30n+23、30n+29
間隔差距為:6 4 2 4 2 4 6 2 的循環,但這比較麻煩,
我們就先做6n+1和6n+5的循環,其他留待延伸題解決。
這種循環的間隔為2、4、2、4......。
觀察前面的質數:2 3 5 7 11不難發現可以從5到7這裡開始迴圈。
由於只有兩種間隔,我們設定dist=2、增加到待檢數字後,
用dist = 6-dist來變換,這樣就可以不停切換兩種間隔。
Code:
int* nPrime(int n) { int *prime = (int*)malloc(sizeof(int)*n); int i, isPrime, dist = 2, totalCnt = 3, primeCand = 5; prime[0] = 2; prime[1] = 3; prime[2] = 5; // isPrime: 1 -> TRUE, 0 -> FALSE. while(totalCnt < n) { primeCand += dist; dist = 6-dist; isPrime = 1; for( i = 0; prime[i]*prime[i]<=primeCand; i++ ) if(primeCand % prime[i] == 0) { isPrime = 0; break; } if(isPrime) prime[totalCnt++] = primeCand; } return prime; }在main中:
int main(int argc, char *argv[]) { int i, n, *prime; scanf("%d", &n); printf("\n"); prime = nPrime(n); for(i = 0; i < n; i++) printf("%4d: %d\n", i+1, prime[i]); system("PAUSE"); return 0; }
沒有留言:
張貼留言