1. 程式人生 > 實用技巧 >P3383 【模板】線性篩素數

P3383 【模板】線性篩素數

線性篩法求質數

做法

  1. 用陣列 \(v\) 來儲存每個數的最小質因子

  2. 列舉2~n之間的數

  3. \(v[i] == i\) 則該數為質數,將其儲存

  4. 窮舉2~\(v[i]\)的質數 \(p\) (不包含\(v[i]\)),則\(v[i*q]\) = \(q\)

    1. 因為 \(p\) 小於\(v[i]\), 所以合數 \(v[i*p]\) 的最小質因子是 \(p\)

推論

  1. 從頭往後挨個列舉,只要滿足\(v[i] = i\),就加入prime[]

  2. 並把對應的\(v[i*q](q\le v[i])\)更新,從而達到類似DP的動態類取數問題

  3. \(prime\) 陣列儲存 \(n\)

    中的質數,這樣就可以打印出每一個質數啦

  4. 時間複雜度 \(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;
}