1. 程式人生 > >Eratosthenes篩法求素數

Eratosthenes篩法求素數

Eratosthenes篩法高效求素數

篩法的思想:對於不超過n的每個非負整數p,刪除2p,3p,4p,5p,…,當處理完所有數之後,還沒有被刪除的數就是素數 這是簡易版的篩法,也最好理解

for(int i=2;i<=n;i++) 
	   for(int j=i*2;j<=n;j+=i)
	      vis[j]=false;

還可以繼續改進,為什麼呢?給定外層迴圈變數i,內層迴圈的次數n/i-1<n/i。迴圈的總次數小於2/n+3/n+…+n/n=O(n * log n)。這個結論來自尤拉1+1/2+1/3+…+1/n=O(n*log n)+y,其中尤拉函式y約等於0.577218

改進:內層迴圈不必從i*2開始,它已經在i=2時被篩掉了

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
bool vis[9999];
void Eratosthenes()  //Eratosthenes篩法
{
	for(int i=2;i<=9999;i++)  //外層迴圈
	   for(int j=i*i;j<=9999;j+=i)   //內層迴圈
	      vis[j]=false;
}
int main()
{
	int temp,n;
	memset(vis,true,sizeof(vis));   //素數表初始化
	Eratosthenes();
	while(cin>>n)   //輸入區間上限
	{
	   temp=0;
	   for(int i=0;i<=n;i++)  //素數表初始化
	   {
	   	 if(temp%10==0&&temp!=0)
			{
				temp=0;
				cout<<endl;
			} 
	     if(vis[i])
		 {
		 	temp++;
		 	cout<<i<<" ";
	     }   
	   }
	}
	return 0;
}

素數定理:count(x)=x/ln x count(x)表示不超過x的素數個數,它和x/ln x比較接近,所以這個定理是可以用來求一個區間的素數個數的