1. 程式人生 > >歐拉篩(求質數)

歐拉篩(求質數)

sta tar locks ide running nbsp 圖片 sizeof rim

先上代碼:

技術分享圖片
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<time.h>
using namespace std;
int prime[10000001];//存素數 
bool vis[10000001];//保證不做素數的倍數 
int main()
{
    int n, cnt = 0;
    scanf("%d", &n);
    clock_t start = clock();
    memset(vis, false, sizeof(vis));//初始化 
    memset(prime, 0
, sizeof(prime)); for(int i = 2; i <= n; i++) { if(!vis[i]) { prime[cnt++] = i; for(int j=1;j*i<=n;j++) { vis[j*i]=true; } } } clock_t ends = clock(); cout <<"Running Time : "<<(double
)(ends - start)/ CLOCKS_PER_SEC << endl; printf("%d\n", cnt); return 0; }
View Code

這並不是完整的歐拉篩,上面的代碼從2開始把素數的倍數全部標記為非質數,計算一千萬以內的質數個數只需要0.23s

完整歐拉篩代碼:

技術分享圖片
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<iostream>
using namespace std;
int prime[10000001];
bool
vis[10000001]; int main() { int n, cnt = 0; scanf("%d", &n); clock_t start = clock(); memset(vis, false, sizeof(vis)); memset(prime, 0, sizeof(prime)); for(int i = 2; i <= n; i++) { if(!vis[i]) prime[cnt++] = i; for(int j = 0; j<cnt && i*prime[j]<=n; j++) { vis[i*prime[j]] = true; if(i % prime[j] == 0) break; } } clock_t ends = clock(); cout <<"Running Time : "<<(double)(ends - start)/ CLOCKS_PER_SEC << endl; printf("%d\n", cnt); return 0; }
View Code

計算一千萬以內的質數個數只需要0.12s

先講講為什麽可以這樣算質數吧

首先,先將所有的數標記為質數,然後從2開始,因為2是質數所以它的倍數肯定不是質數,然後3同理,4已經被標記為非質數了跳過,5質數,6也被標記為非質數了跳過.....

然後講一講為什麽第一個會比第二個快

為什麽會這樣了?

首先,第一個代碼標記2的倍數是標記過1次6,而標記3的倍數時有標記了一次6,所以重復標記花費了時間

而第二個代碼,因為這句代碼而沒有進行重復標記:

for(int j = 0; j<cnt && i*prime[j]<=n; j++)
{
  vis[i*prime[j]] = true;
  if(i % prime[j] == 0) break;//重點
}

當 i % prime[j] == 0,相當於i=k*prime[j],所以i*preime[i+1]=k*prime[j]*preime[i+1],是質數的倍數,而後面會對他進行標記,所以這次就跳過,終止循環.

第一個代碼也可以這樣寫:

技術分享圖片
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<time.h>
using namespace std;
int prime[10000001];//存素數 
bool vis[10000001];//保證不做素數的倍數 
int main()
{
    int n, cnt = 0;
    scanf("%d", &n);
    clock_t start = clock();
    memset(vis, false, sizeof(vis));//初始化 
    memset(prime, 0, sizeof(prime));
    for(int i = 2; i <= n; i++)
    {
        if(!vis[i])
        {
            prime[cnt++] = i;
        }
        for(int j = 0; j<cnt && i*prime[j]<=n; j++)
        {
            vis[i*prime[j]] = true;
        }
    }
    clock_t ends = clock();
    cout <<"Running Time : "<<(double)(ends - start)/ CLOCKS_PER_SEC << endl;
    printf("%d\n", cnt);
    return 0;
}
View Code

歐拉篩(求質數)