質數篩

懒羊羊爱吃灰太狼發表於2024-08-17
  • 判斷一個數是不是質數,最基礎的方法:
bool isprime(int n) {
    if(n <= 1) return 0;
    for(int i = 2; i <= sqrt(n); i ++) {
        if(n % i == 0) return 0;
    }
    return 1;
}

這個方法雖然能判斷是不是質數,但效率很低,如果要判斷的這個數很大,那麼多半是會TLE,所以我們需要更高效的演算法;

  • 埃式篩:
ll is_prime[maxn];  //記錄質數 
bool vis[maxn];  //判斷是不是質數

void isprime(ll n)
{
	vis[0] = 1;
	ll cnt = 0;  //記錄質數個數 
	for(ll i = 2; i <= n; i ++){
		if(!vis[i]){
			is_prime[++cnt] = i;
			for(ll j = 2 * i; j <= n; j += i){
				vis[j] = 1;  //記錄質數的倍數是不是質數 
			}
		}
	}
} 

埃式篩就會比普通方法要快得多,但它也有個缺點,就是同一個數會被篩很多次,這導致時間上有所損失,所以有什麼辦法可以只篩一次呢?當然有:

  • 尤拉篩(也稱線性篩)
ll is_prime[maxn];  //記錄質數 
bool vis[maxn];  //判斷是不是質數

void isprime(ll n)
{
	vis[0] = 1;
	ll cnt = 0;  //記錄質數個數 
	for(ll i = 2; i <= n; i ++){
		if(!vis[i]){
			is_prime[++cnt] = i;
			if(i <= sqrt(n)){
				for(ll j = i * i; j <= n; j += i){
					vis[j] = 1;  //記錄質數的倍數是不是質數 
				}
			}
		}
	}
}

相關文章