[算法]淺談求n范圍以內的質數(素數)


汗顏,數學符號表達今天才學會呀-_-#

下面是百度百科對質數的定義

質數(prime number)又稱 素數,有無限個。
質數定義為在大於1的自然數中,除了1和它本身以外不再有其他 因數
求質數的方法自然不少,但主要還是有三大方法,它們運用在不同的領域,根據數據也會變化;

1、傻子求質數法

這種方法十分無腦,任何一個人都能想出來,但這種方法竟然還有幾個優化ORZ

時間復雜度是O($N^{2}$);

1.1、無優化版本

 1 void prime()
 2 {
 3     int N = 10000;
 4     int primes[N],pos=0;
 5     register int i,j;
 6     for(i=2;i<N;i++){
 7         bool Flag=0;
 8         for(j=2;j<i;j++)
 9             if(i%j==0)Flag=1;
10         if(Flag==0)primes[++pos]=i; 
11     }
12 }

這也是所有求質數中最朴素的求法,自然在平常當中不會使用。

然而有些奇葩題目,求質數的次數很少,就可以用這個啦。↖(^ω^)↗

證明:質數定義為在大於1的自然數中,除了1和它本身以外不再有其他因數 ——百度百科。

1.2、n/2 優化版本

 1 void prime()
 2 {
 3     int N = 10000;
 4     int primes[N],pos=0;
 5     register int i,j;
 6     for(i=2;i<N;i++){
 7         bool Flag=0;
 8         for(j=2;j<=i/2;j++)
 9             if(i%j==0)Flag=1;
10         if(Flag==0)primes[++pos]=i; 
11     }
12 }

 

這種優化就比上一種快一倍(時間復雜度),但仍然有缺陷,能不能再快一點??_?

證明:x/2以上的數增加就會重復。

1.3、n開平方優化版本

 1 void prime()
 2 {
 3     int N = 10000;
 4     int primes[N],pos=0;
 5     register int i,j;
 6     for(i=2;i<N;i++){
 7         bool Flag=0;
 8         for(j=2;j<=sqrt(n);j++)
 9             if(i%j==0)Flag=1;
10         if(Flag==0)primes[++pos]=i; 
11     }
12 }

 這個就是傻子求法的最終版本了,時間復雜度已經優化到了極限(個人認為)。囧rz

證明:因為x=$\sqrt{N}^{2}$的平方,所以sqrt(x)以上的數增加就會重復。

 


 2、埃氏(Eratosthenes)篩法

埃拉托斯特尼篩法,簡稱埃氏篩或愛氏篩,是一種由希臘數學家埃拉托斯特尼所提出的一種簡單檢定素數的算法。要得到自然數n以內的全部素數,必須把不大於根號n的所有素數的倍數剔除,剩下的就是素數。——百度百科

這種篩法大概是我初一學了快一個學期,開始學質因數時,自己過不了找質數一個題,然后接觸的一個算法。

埃氏的篩法思想精華,主要是把質數的倍數剔除,剩下的那些就是質數。+_+

這種算法的時間復雜度是O(nloglogn)。

 1 void prime()
 2 {
 3     int N=10000;
 4     register int i,j;
 5     bool prim[N];
 6     memset(prim,0,sizeof(prim));
 7     prim[1]=1;
 8     for(i=2;i<=sqrt(N);i++)
 9         if(prim[i]==0) 
10             for(j=i+i;j<=N;j+=i)
11             prim[j]=1;
12 }

3、歐拉(Euler)篩選法

歐拉篩法就是所謂中的高級篩法,時間復雜度削減到了O(N)。

它的思想是在埃氏篩法的基礎上,讓每個合數只被它的最小質因子篩選一次,以達到不重復的目的。

 1 void prime()
 2 {
 3     int N=10000;
 4     int prim[N],bz[N],top=0;
 5     memset(bz,0,sizeof(bz));
 6     register int i,j;
 7     for(i=2;i<=N;i++){
 8         if(!bz[i])prim[++top]=i;
 9          for(j=0;j<=top&&i*prim[j]<=N;j++){
10                  bz[i*prim[j]]=1;
11                  if(i%prim[j]==0)break;
12           }
13     }
14 }

自己還有很多東西都沒有學到,不知道什么時候才能脫掉蒟蒻的外套呢。

博主是初中蒟蒻,能力弱,還請大家多多提出改進建議:-D      ——2018.11.27

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM