問題描述:使用篩法求質數。有一個很神奇的篩子,可以給它一個數i,這個篩子有辦法把i的所有倍數去掉。請用這個方法求出2到N之間的所有質數。要求,程序不能使用乘法和除法,只能用加或減,以求加快速度。
該問題的思路來自《C語言名題精選百則技巧篇》,很慚愧,我對這樣的涉及一些數學知識的題很少有解決的辦法,我需要在這一方面加強。
我把書中的思路歸納如下,並加上了我自己的一些想法。
1. 2的倍數都不是質數,所以不比考慮2的倍數。2是質數,所以考慮的數的集合是 2i+3,i=0,1,2,3,4.......
2. 求質數,只需要處理到num/2就可以了。在程序中MAX爲基準,算出2到2*MAX+3之間的質數,實際也是處理到MAX就停止了。
3. 程序不能使用乘法,只能使用加法和減法,所以就需要作一些數學方面的處理:2i+3是一個奇數,要去除它的倍數。在第1點中,已經去除了2的倍數,所以就不用管2i+3的偶數倍的數了,只需要處理2i+3的奇數倍的數了。所以,我們需要去除(2n+1)(2i+3),n=1,1,2,3,4....當然,不能去除2i+3本身。然後對(2n+1)(2i+3)做一個變形,朝着2N+3這樣的形式去變形(ps:這是我以前在數學證明題中經常做的)。變形過程:(2n+1)(2i+3)=2n(2i+3)+2i+3=2[n(2i+3)+i]+3;這就是2N+3的形式了(N就是n(2i+3)+i)。由於在程序中我們是以i作爲索引的,所以我們用篩子篩出爲止爲N的數,也就是刪除位置爲n(2i+3)+i的數。這樣,就不難寫出程序了。
代碼如下:
1 #include <stdio.h> 2 #define MAX 1000 3 #define SAVE 0 4 #define DELETE 1 5 6 int sieve[1000]={0}; //all to SAVE 7 8 int main() 9 { 10 int i,k; 11 int prime; 12 int count=1;//The sum number of the prime numbers 13 //2*i+3 is odd numbers 14 for(i=0;i<MAX;i++) 15 { 16 if(sieve[i]==SAVE) //it is a prime number 17 { 18 //I have a problem here.Why are the front several numbers prime number after one or two sieve process such as 5 or 7 or 11? I just think they are prime nubmers without proving it. 19 prime=i+i+3; 20 count++; 21 for(k=prime+i;k<=MAX;k+=prime) 22 sieve[k]=DELETE; 23 } 24 } 25 printf("%6d",2); 26 27 for(i=0,k=2;i<MAX;i++) 28 { 29 if(sieve[i]==SAVE) 30 { 31 if(k>10) 32 { 33 printf("\n"); 34 k=1; 35 } 36 int temp=i+i+3; 37 printf("%6d",temp); 38 k++; 39 } 40 } 41 printf("\nThe sum number is %d \n",count); 42 return 0; 43 }
總結:與一些數學變換相結合的程序題是我的一個弱項,自己總是想不到這樣的想法,最根本的原因就是這樣思考得太少了以及數學功底不夠。在以後需要多加強數學知識的學習以及數學與程序相結合的算法(數據結構)甚至是項目實踐等等練習。
參考資料:《C語言名題精選百則技巧篇》