區間篩法
求n之前的所有素數
原理
1.如果採用利用文章中第乙個o(sqrt(n))的演算法,進行n次迴圈即可得到答案。顯然,這樣o(nsqrt(n))肯定超時,所以我們需要進行優化。**2.如果我們判斷出a是素數,那麼我們就可以確定a的倍數都是合數。因此可以將這些倍數刪除,這樣就可以去掉一些不必要的判斷。
3.進一步,我們會發現有些合數我們進行了多次刪除。例如:對於合數6,它是2的倍數,也是3的倍數,所以我們進行了兩次刪除,因此我們可以進一步優化。
我們需要確保每乙個合數只能被最小質因子篩掉。這一步我們通過核心**
if(i%prime[j]==0)break;
實現。(在**之後解釋)
#define maxn 100000100
int num[maxn]
;int prime[maxn]
;//儲存得到的素數 ,但是prime[0]是記錄素數個數
intget_prime()
}}
注釋if
(i%prime[j]==0
)break
;//如果i%prime[i]==0滿足,
//則代表i*prime[j+1]能夠用乙個更小的素數和更大的合數相乘得到,因此跳出迴圈
//可以理解為ab%a==0,所以ab*c(a//例如:當i=6時,num[6*2]=1,而6%2=0,所以有6*3=18=9*2
另乙個模板
來自kuangbin的模板,用乙個陣列,節省了空間,但難度大一點
const
int maxn =
1e7+5;
void
getprime()
}}
求[a,b]中的素數
原理
1.首先明確:b以內的所有合數的最小質因數一定不會大於b**\sqrt
b。證明:
設s的最小質因數a
>
ba>\sqrt
a>b
,則s>=a*a>b。與條件矛盾。
2.通過[2,
b)
[2,\sqrt)
[2,b)
的素數表,把埃氏篩法用到[a,b)上。
也就是說,從[2,
b)
[2,\sqrt)
[2,b)
篩得素數得同時,也將它得倍數從[a,b)刪去。最後就只剩下[a,b)中得素數了。
typedef
long
long ll;
int is_prime_1[maxn]
;int is_prime_2[max_sqrt_b]
;void
segment_sieve
(ll a,ll b)
for(ll j=
max(
2ll,
(a+i-1)
/i)*i;j=i)//篩[a,b]; j的初始值是在[a,b)中i的最小倍數;2ll表示2是longlong 型別}}
}
數論 埃氏篩法
這學期的離散數學課程學了一點初等數論,其中的埃氏篩法當時課上沒有太懂,課後看了 挑戰程式設計競賽 一書終於弄懂了。這本書確實很好!演算法簡潔優美。如果只對乙個整數進行素性測試,通常o n 的演算法就足夠了。但如果要對許多整數進行素性測試,則有更為高效的演算法,其中就包括埃拉託斯特尼篩法,簡稱埃氏篩法...
埃氏篩法 素數篩
埃式篩法 給定乙個正整數n n 10 6 問n以內有多少個素數?做法 做法其實很簡單,首先將2到n範圍內的整數寫下來,其中2是最小的素數。將表中所有的2的倍數劃去,表中剩下的最小的數字就是3,他不能被更小的數整除,所以3是素數。再將表中所有的3的倍數劃去 以此類推,如果表中剩餘的最小的數是m,那麼m...
素數篩法(埃氏篩,線性篩)
時間複雜度o nloglogn void prime int b prime i 1則是合數 原理很簡單,所有合數可以表示為乙個質數跟另乙個數的積,列舉每個已知素數的倍數就能標記完。但很明顯,這樣做會有重複。比如12 3 4 2 6,在2這個素數進行倍數標記時會標記,在3這個素數進行倍數標記時同樣會...