leetcode每日一題 204. 計數質數【簡單】
看到題第乙個想法就是判斷每個數是否是質數=》方法一
當然最簡單的想法會超時 然後就想到了如果某個數x是質數 那麼x的倍數必定是合數可以不用判斷
後來查了資料知道了原來有個學名 埃氏篩【埃拉託斯特尼篩法】=》方法二
這裡還對2的倍數進行了預處理 然而還是超時
def
countprimes
(n):
""" :type n: int
:rtype: int
"""import math
defisprime
(num)
:if num==
2or num==3:
return
true
if num==
1or num%2==
0:return
false
mid =
int(math.sqrt(num))+
1for i in
range(3
,mid,2)
:if num%i==0:
return
false
return
true
ret=
0for i in
range(2
,n):
if isprime(i)
: ret+=
1return ret
2. 埃氏篩
如果是質數 則將質數的倍數去除
大致流程:i去除
24,6,8,10…
39,15,21…
4非質數已去除
525,35………
def
countprimes2
(n):
""" :type n: int
:rtype: int
"""num =
set(
[i for i in
range(2
,n)]
)for i in
range(2
,n):
if i in num:
tmp=i*
2while tmp < n:
if tmp in num:
num.remove(tmp)
tmp +=i
return
len(num)
3. 尤拉篩def
countprimes3
(n):
""" :type n: int
:rtype: int
"""prime=
isprime =
[true]*n
for i in
range(2
,n):
if isprime[i]
:for p in prime:
if p*i>=n:
break
isprime[p*i]
=false
if i%p==0:
break
return
len(prime)
這裡用prime來儲存當前已判斷的質數 從小到大
isprime用來記錄是否是質數
**好理解 最關鍵的就是
if i%p==0:break這一條語句的目的是為了每乙個合數只讓最小質因數來判斷其為合數
所以將判斷次數變成了線性 並保證了不重複不遺漏
因為在prime中的質數是有序的 從小到大
即:prime[j] prime[j]*prime[j+1]*x
prime[j+1]並不是最小的能整除它的數 所以我們不需要繼續判斷prime[j]後面的質數與i相乘了
大致流程:
iprime
isprime變為false
2[2]43
[2,3]
6,94
[2,3]85
[2,3,5]
10,15,25
6[2,3,5]12…
……看了流程 我們可以總結
思想還是一樣 去除質數的倍數
實現方式與埃氏篩略有差別
埃氏篩:對於質數x 一次性去除所有x的倍數
而尤拉篩:對倍數i進行了遍歷 每次去除當前所有質數的i倍
我們以流程中的12舉例
當i=4時 我們先判斷4*2=8 為合數 此時i%prime[j] 即4%2 餘數為零
那麼這時我們退出 不再判斷 4*3=12 因為3並不是12的最小質因數
12的最小質因數為2
所以下面倍數i=6時 2*6=12 此時判斷12為合數
由此可見 每乙個合適有且僅有一次被判斷為合數 與埃氏篩相比大大減少了判斷次數
線性篩質數,線性求尤拉
本篇前半部分講線性篩質數,也叫尤拉篩,後半篇講解線性求尤拉函式。我們有一種篩質數的辦法,就是列舉每個質數,然後把這個質數的倍數都篩掉,這個做法比較簡單,在這裡不做過多介紹。尤拉篩就是在這個方法的基礎上,使得每個合數只會被它最小的那個質因子篩掉,保證了複雜度是線性的 memset isprime,1,...
線性篩(尤拉篩)
昨天的考試跪的一塌糊塗 第一題水過,第二題帶wa的樸素,最後題忘了特判左端點全跪,分數比起預計得分整整打了個對折啊!步入正題 線性篩 尤拉篩 一般的篩法 ppt裡叫埃拉託斯特尼篩法,名字異常高貴 的效率是o nlglgn 其實很接近o n 啊!對於一些例如n 10000000的殘暴資料會跪,於是,線...
尤拉篩 線性篩
實現 include using namespace std const int max n 1e8 int prime max n cnt bool st max n 使用bool陣列節省空間 void is prime int n intmain 每個合數只被自己最小的質因子篩去。現在證明在i ...