1. 程式人生 > >【數論】線性篩質數

【數論】線性篩質數

一次 數論 [1] utc syn else == ring tdi

核心思想:

保證每個合數只會被它的最小質因數篩去,因此每個數只會被標記一次,所以時間復雜度是O(n)

此過程中保證了兩點

  1. 合數一定被幹掉了...
  2. 每個數都沒有被重復地刪掉

代碼

#include<iostream>
#include<cstdio>
#include<cstring>
#define f(i,a,b)    for(register int i=a;i<=b;++i)
#define fd(i,a,b)    for(register int i=a;i>=b;--i)
using namespace std;
const int N=10000000+7;
int n,m,f[N],tot;
bool visit[N];
//visit[i]如果被標記了 那麽就不是素數
inline int read() {
	int data=0,w=1;
	char ch=0;
	while(ch!=‘-‘ && (ch<‘0‘ || ch>‘9‘)) ch=getchar();
	if(ch==‘-‘) w=-1,ch=getchar();
	while(ch>=‘0‘ && ch<=‘9‘) data=data*10+ch-‘0‘,ch=getchar();
	return data*w;
}

inline void write(int x) {
	if(x<0) putchar(‘-‘),x=-x;
	if(x>9) write(x/10);
	putchar(x%10+‘0‘);
}

inline void pd(int Max) {
	visit[1]=1;
	f(i,2,Max) { //枚舉每一個數 順便枚舉倍數
		if(!visit[i])//要是沒標記到那麽就是素數
			f[++tot]=i;
		for(int j=1; j<=tot && i*f[j]<=Max; j++)
			//這裏是枚舉前面的每一個素數
		{
			visit[i*f[j]]=1;//把前面的素數倍數都標記上
			if(i % f[j]==0)    break;//如果不是最小質因子就退出
			/****************************
			    為什麽這句話可以忽略掉不是最小質因子 而保證時間復雜度呢
			    首先 visit[]裏面的素數都是嚴格遞增的
			    如果當前的i含有visit[j] 不妨設 i=visit[j]*k
			    下一個數 P=i*visit[j+1]肯定可以寫成 P=visit[j]*k*visit[j+1]
			    所以P肯定會在 i=k*visit[j+1] 的時候篩掉
			    所以這句話可以使得是最小質因子就退出
			*****************************/
		}
	}
}

int main() {
//    ios::sync_with_stdio(false);
	n=read();
	m=read();
	pd(n);
	f(i,1,m) {
		int a=read();
		if(visit[a])    puts("No");
		else puts("Yes");
	}
	return 0;
}

代碼引自luogu

【數論】線性篩質數