線性篩素數 尤拉篩 字首和優化

2022-08-31 23:36:24 字數 1074 閱讀 7980

關於素數的定義:在大於1的自然數中,除了1和它本身以外不再有其他因數。

判斷乙個數是否是素數:

int x;  //

要求的數

for(int i=2;i<=sqrt(x);++i)

}

埃氏篩法(時間複雜度:$o(nloglogn)$):

int num_prime = 0;  //

素數的數量

int prime[5005]; //

放素數

int check[5005

];for(int i=2;i<5000;++i)

for(int j=2*i;j<5000;j+=i)

}

這種方法比遍歷每乙個數從2到對數本身來取餘判斷是否為零的效率要高,可是裡面仍然有重複篩選的現象。如下圖所示,$2*2+2=6$,$2*3=6$,當資料區間大起來之後效率也會變得很差。

線性篩素數(時間複雜度:$o(n)$):

int num_prime = 0;  //

素數的數量

int prime[5005]; //

放素數

int check[5005

];for(int i=2;i<5000;++i)

for(int j=0;j5000;++j)}}

首先我們要理解:任何乙個合數都可以表示成乙個質數和乙個數的乘積,例如$8%2==0$,表明當i=8的時候與第乙個素數進行判斷就可以停止進行下一輪了,如果再進行$8*3=24$,但$24=(2*4)*3=2*(4*3)=2*12$,表明篩24的最佳時機應該是i=12的時候,因為這時候12與其最小素因子2就可以一次篩出來了,並且不會與之前的24發生重複篩選的浪費.因此我們就可以按照乙個數的最小素因子篩選來保證不出現重複篩選的情況,從而大大地提高了效率。

因為每一行都是相應最小素因子可以組成的數,因此可以證明所有的合數都會被篩掉

字首和優化可以用來加快求區間和:求[left,right] -> sum[right] - sum[left-1] (left-1是因為sum[left]包含left元素)

線性篩素數(尤拉篩)

尤拉篩是o n 複雜度的篩素數演算法,1秒內埃篩能處理1e6的資料,而1e7的資料就必須用尤拉篩了。埃篩的基本思想是 素數的倍數一定是合數。尤拉篩基本思想是 任何數與素數的乘積一定是合數 演算法概述 遍歷 2,n 的所有數i,內層迴圈遍歷已經找到的素數prime j 將i prime j 標記為合數...

素數線性篩法(尤拉篩)

之前寫的埃式篩法複雜度達o n log n lo gn o n logn logn o n lo gn l ogn 在大數字的時候可能複雜度還不夠理想。這種做法對於乙個合數有可能會篩了多次,導致重複做功。引入尤拉篩法能夠解決這種多次篩同乙個數字的情況,理論演算法複雜度o n o n o n 精髓在於...

素數線性篩 尤拉Euler篩

prime陣列中的素數是遞增的,當i能整除prime j 那麼i prime j 1 這個合數肯定被prime j 乘以某個數篩掉。因為i中含有prime j prime j 比prime j 1 小,即i k prime j 那麼i prime j 1 k prime j prime j 1 k ...