第四期POWER8大賽(計算質數)

這是一個實現計算素數的問題。但由於這 個問題本身的特殊性(輸出某範圍內所有素數),我給出一個方案,或許和大家的一樣。

bool數組A:A[i]=True表示 2*i+1 爲素數。如果要找10億以內的素數,就要申請一個5億bit的bool數組A,佔用空間略小於100M,這種小範圍的情況還是可用的。A全部初始化爲TRUE;

解法就很簡單,按照下面的步驟來做就行了:

1.首先把A[0]=FALSE,賦值。

1.從A[0]開始,如果A[i]==TRUE,則進行以下步驟:

a) 求出A[i]所代表的數字x = 2*i+1;把x的x倍到n倍(nx<=10億)的數字在bool數組A中所指示的A[i]賦值爲FALSE,(如果本來爲TRUE)。

b)做完後繼續下一個A[i]

以上過程完成後A數組就記錄了除2以外的所有素數了。下面把他們讀出來:

a)輸出2;

b)從A[0]開始如果A[i]==TRUE;輸出2*i+1;


這個算法非常簡單,複雜度遠遠低於O(nlog(n));按照我的理解時間複雜度應該已經較低了。這個方法的基本思想是排除法。和大家的方法相比,不知道是不是英雄所見略同啊!

至於複雜度的估算這裏給個提示:每一個A[i]被訪問的次數等於這個A[i]的指示的數分解因子後,不同因子的個數,比如如果2*i+1=3*3*7*13*23那麼A[i]會被訪問4次,並嘗試賦值A[i]爲FALSE。


和大家討論之後,得到啓發,發現可以實現一個線性算法,如下:

這是一個質數算法和前一個有很多相同的地方,一些基本的假設這裏繼續申明一遍:

假設要找1-M範圍內的所有質數

布爾數組A[M+1],A[i]=TRUE表示有 i是質數;全賦值爲TRUE,A[0],A[1]賦值爲0;

質數隊列B(足夠長可以順序存下所有質數);len_B=1,,len_B[0]=2;

1.        從i=3開始;如果A[i]==TRUE則將i存入B數組中,len_B++。

2.        按照以下方法找到i並的置換爲FALSE:

a)        從B的素數集合中取len_B次,取出的len_B個質數的乘積所指示的位置賦值爲FALSE;遍歷窮盡所有取法組合(同一個質數可以取多次,比如3放入B後,會對2*2=4,2*3=6,3*3=9進行置換)【怎麼遍歷才能最方便的取遍所有組合?】

3.        對下一個A[i]進行同上的操作;

這種做法的正確性我就不多說了。至於複雜度方面:每個數的標記最多隻會被翻轉一次,因爲它只有一種因子分解的方法。如果遍歷組合的時候沒有無效計算(簡單一點就是你編程的時候沒有類似於if的判斷),那就必定是線性時間了。

 

遍歷所有組合的時候怎樣才能避開無效計算呢?及怎麼在 2*3*2 和2*2*3、3*2*2這些中只找到一個並且一次呢,其實我們只要加上一個限制就是取數組計算乘積時加上一個限制後取的質數大於或等與先取的質數(因爲數組B是升序的,所以這裏也不用進行比較),就可以保證不需要進行無效計算了。

說到這裏,這個求質數的方法已經從理論可行了,當然實現可能還是另一回事,畢竟有些問題在開發的時候纔會突顯出來。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章