題目描述:用線行篩篩選素數,將指定範圍的素數找出,達到o(n)的效果。
思路時間複雜度
0(n)
思路任意值必然可以被分解為:a=b1^c1*b2*c2*...
例如9=3^3,15=3*5,55=5*11
即所有的合數都可以被拆解為素數倍數的乘積。
當我們從2開始找到素數與含有素數的合數,將合數標記為非素數
,每個合數都將被最小因素數標記,且只標記一次。
所以該公式雖然為雙重迴圈,但實際時間複雜度為o(n);
注意if(i%primes[j]==0)break;
當這條命令執行時,有兩種可能
1.被最小素數標記。
2.自己就是素數。
在第二種情況下往往會使合數遍歷得很大,比如i=7
遍歷到49
才會停止,而35
就被7
標記,而非2
。
cpp**
#include
using
namespace std;
const
int n=
1e6+10;
bool st[n]
;int primes[n]
,cnt;
//prime質數,cnt計數當前值的位置
intget_primes
(int n)}}
intmain()
以下解釋來自博主__simon_的文章尤拉線性篩素數
原理是利用了每個合數必有乙個最小素因子,每個合數僅被它的最小素因子篩去正好一次,當 i 能整除 prime[ j ],那麼i * prime[ j+
1] 這個合數肯定被 prime[j] 乘以某個數篩掉,因為 i 中有prime[j]且 i * prime[ j+
1]中也有prime[ j ]。
舉個例子:
當 i =
8,prime=
2,3,
5,7;i * prime=
16,24,
40,56;
因為8%2=
0,所以24,40,56
,可以不篩,直接break
;就如上面那句話所說的,當8能整除2時,8乘以 下乙個素數3 的值24,將會被12乘以2篩掉。
即24=8*
3=(2
*4)*
3=2*
(4*3
)=2*
12; 被12篩掉
40=8
*5=(
2*4)
*5=2
*(4*
5)=2
*20; 被20篩掉
56=8
*7=(
2*4)
*7=2
*(4*
7)=2
*28; 被28篩掉
這些數後面會被篩掉,即 i =
12,20,28時。所以現在就不用篩選,降低時間複雜度。
線性篩素數(尤拉篩)
尤拉篩是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 ...