P3383 【模板】線性篩素數
阿新 • • 發佈:2020-11-05
線性篩法求質數
做法
-
用陣列 \(v\) 來儲存每個數的最小質因子
-
列舉2~n之間的數
-
若\(v[i] == i\) 則該數為質數,將其儲存
-
窮舉2~\(v[i]\)的質數 \(p\) (不包含\(v[i]\)),則\(v[i*q]\) = \(q\)
- 因為 \(p\) 小於\(v[i]\), 所以合數 \(v[i*p]\) 的最小質因子是 \(p\)
推論
-
從頭往後挨個列舉,只要滿足\(v[i] = i\),就加入prime[]
-
並把對應的\(v[i*q](q\le v[i])\)更新,從而達到類似DP的動態類取數問題
-
\(prime\) 陣列儲存 \(n\)
-
時間複雜度 \(O(n)\)
Code
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <vector> using namespace std; typedef long long ll; const int manx=1e8+10; const int mamx = 1e6 + 11; const int B = 1e6 + 11; const int mod = 1e9 + 7; const int inf = 0x3f3f3f3f; inline int read() { char c = getchar(); int x = 0, f = 1; for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1; for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48); return x * f; } int v[manx],prime[manx],m; void primes(int n){ memset(v,0,sizeof(v)); m = 0; for(int i = 2;i <= n; i++){ if(v[i] == 0){ v[i] = i; prime[++m] = i; } for(int j = 1;j <= m; j++){ if(prime[j] > v[i] || prime[j] >n/i)break;//i有比prime[j]更小的因子,或者超出n的範圍,則跳出迴圈 v[i*prime[j]] = prime[j]; } } //for(int i = 1;i <= m ;i++)cout<<prime[i]<<endl; sort(prime + 1,prime + 1 + m); } int main(){ int n = read(),q = read(); primes(n); for(int i = 1; i <= q; i++) { int x = read(); //cout<<prime[x]<<endl; } return 0; }