1. 程式人生 > >Eratosthenes篩選法與尤拉篩選法

Eratosthenes篩選法與尤拉篩選法

Eratosthenes篩選法與尤拉篩選法 由於一個合數總是可以分解成若干個質數的乘積,那麼如果把質數的倍數都去掉,那麼剩下的就是質數了.Eratosthenes篩選法的思想特別簡單:對於不超過n的每個非負整數p,刪除2p,3p,4p,...,當處理完所有數之後,還沒有被刪除的就是素數.如果用vis[i]表示i已經被刪除,則篩選法的程式碼可以寫成:
void isprime(int n)///篩選1-n的素數
{
    memset(vis,0,sizeof(vis));
    for(int i = 2; i <= n; i++)
        for(int j = 2 * i; j <= n; j += i)
            vis[j] = 1;
}
儘管程式碼已經相當高效了,但仍然可以進行改進.首先,在"對於不超過n的每個非負數p"中,p可以限定為素數--只需在第二重迴圈前加一個判斷if(!vis[i])即可.另外,內層迴圈也不必從* 2開始--它已經在= 2時被篩選了.改進後代碼如下:
void isprime(int n)///篩選1-n的素數
{
    memset(vis,0,sizeof(vis));
    int m = sqrt(n + 0.5);
    for(int i = 2; i <= m; i++)
    {
        if(!vis[i])
        {
            for(int j = i * i; j <= n; j += i)
                vis[j] = 1;
        }
    }
}

Eratosthenes篩選法雖然效率高,但是Eratosthenes篩選法做了許多無用功,一個數會被篩到好幾次,最後的時間複雜度是O(nloglogn),對於普通素數演算法而言已經非常高效了,但尤拉篩選法的時間複雜度僅僅為O(n).

尤拉篩選法的思想就是不做無用功,原本Eratosthenes篩法的第一重迴圈是用來找素數,然後把素數的倍數標記,而尤拉篩法換了一個角度,第一位是找素數沒有問題,但是標記的時候用的是所有數.尤拉篩選法在資料小的時候不如Eratosthenes篩選法快,反而是資料變大以後,兩者差距變得越來越明顯,尤拉篩選法明顯快於Eratosthenes篩選法.尤拉篩選法程式碼如下:

const int Max = 100002;
int Prime[Max];
bool vis[Max];
void prepare()
{
    int num = 0;
    memset(vis,true,sizeof(vis));
    for(int i = 2; i <= Max; ++i)
    {
        if(vis[i])
            Prime[++num] = i;
        for(int j = 1; j <= num; ++j)
        {
            if (i * Prime[j] > Max)
                break;
            vis[i * Prime[j]] = false;
            if (i % Prime[j] == 0)
                break;
        }
    }
}


相關推薦

【演算法】3.Eratosthenes篩選篩選求素數

Eratosthenes篩法 1.原理 一個合數可以分成幾個素數的和,如果把素數(最初只知道2)的倍數全都去掉,剩下的就都是素數了 2.思路分析 去除0,1(既不是素數又不是合數) 找到佇列中最小的素數,刪除其倍數 3.程式碼實現(只給出了函

Eratosthenes篩選篩選

Eratosthenes篩選法與尤拉篩選法 由於一個合數總是可以分解成若干個質數的乘積,那麼如果把質數的倍數都去掉,那麼剩下的就是質數了.Eratosthenes篩選法的思想特別簡單:對於不超過n的

小於等於n的素數的個數(埃式篩選篩選

問題描述 給定數字n,求出小於等於n的素數的個數,假設n<=1000000 思路 找出數字n之前的所有素數,用陣列isprime[i]表示i是否是素數;用num[i]表示小於等於數字i的素數有多少。 那麼最重要的就是解決判斷一個數是否是素數 方法

函式求法求素數

尤拉函式:     尤拉函式定義:        對於正整數n,尤拉函式Euler(n)是1到n-1中與n互質的數的個數,特別的,Euler(1) = 1,若n為質數則有 Euler(n) = n - 1      尤拉函式的兩種求法:     1.由定義和常識可以知道對

埃氏篩的區別

Eratosthenes篩法(Sieve of Eratosthenes) 由於思想非常簡單,故只給出實現。 void eratosthenes_sieve(int n) { totPrimes = 0; memset(flag, 0, size

求素數個數(埃氏篩

求1——n的素數的個數,有以下三種方法: 普通的O()演算法: #include<iostream> #include<cstdio> #include<cmath> using namespace std; bool isprim

線性篩選素數(篩選

bool ok[maxn];//自然數表 int prime[maxn];//素數陣列 int tol;//素數長度 void make_prime() { tol = 0; for(int i

Prime Path-POJ3126-1篩選+BFS-好題

題意: 給你兩個四位數的質數m,n(m<=n),每次變化只能改變當前數的一個數字,並且過程中的數字全是四位數的質數,求最小的步數。 思路: 先尤拉篩選法求出素數,然後從m開始BFS,每次只改變一個

O(N)的素數篩選函式

首先,在談到素數篩選法時,先涉及幾個小知識點. 1.一個數是否為質數的判定.         質數,只有1和其本身才是其約數,所以我們判定一個數是否為質數,只需要判定2~(N - 1)中是否存在其約數即可,此種方法的時間複雜度為O(N),隨著N的增加,效率依然很慢。這裡有

定理、拓展定理及其應用(降冪

摘要   本文主要介紹了數論中的尤拉定理,進而介紹尤拉定理的拓展及應用,結合例題展示如何使用拓展尤拉定理實現降冪取模。   在數論中,尤拉定理,(也稱費馬-尤拉定理)是一個關於同餘的性質定理。瞭解尤拉定理之前先來看一下費馬小定理:     a是不能被質數p整除的正整數,則有a^(p

線性

合數指自然數中除了能被1和本身整除外,還能被其他數(0除外)整除的數 時間複雜度O(n) 每個合數只會被他的最小的質因子篩去。  #include<iostream> #include<cmath> #include<cstring> usi

【模板】(線性篩

1 int n; 2 int p[MAX_N], cnt; 3 bool b[MAX_N]; 4 5 void Euler() 6 { 7 b[0] = b[1] = 1; 8 for(register int i = 2; i <= n; ++i) 9

[模板]線性篩素數()

用途 $O(n)$處理出n以內所有素數 原理 使用 合數=最大因數(除1和本身外)*最小質因數 的原理來篩,每個數只會被篩一次 對於每個數i,令它是某數的最大因數,然後從小到大地找<=i的素數j,則i*j是合數 直到找到某個j使得$i\%j==0$,因為再往後的話,j'> i的某個因子,

【演算法模板】求素數

#include<iostream> using namespace std; const int MAXN=1000000+10; int n,cnt,prime[MAXN]; bool vis[MAXN]; void findprime(int n)

數論 之 篩總結(艾托拉斯特尼篩+

1.篩法: 2.埃拉託斯特尼篩法(素數/質數篩選法): 2.1 步驟:      給出要篩數值的範圍n,找出以內的素數。先用2去篩,即把2留下,把2的倍數剔除掉;再用下一個素數,也就是3篩

素數個數-

模擬的時候真沒想到這是一道這麼麻煩的題。。。 先來看題: 素數個數 題目描述 求1,2,\cdots,N1,2,⋯,N 中素數的個數。 輸入輸出格式 輸入格式: 1 個整數N。 輸出格式: 1 個整數,表示素數的個數。

『素數(Prime)判定和線性(The sieve of Euler)』

  <更新提示>      <第一次更新>      <正文>      素數(Prime)及判定      定義      素數又稱質數,一個大於1的自然數,除了1和它自身外,不能整除其他自然數的數叫做質數,否則稱為合數。      1既不是素數也不是合數。  

BZOJ 2818: 求gcd(x,y)==k(k為質數)

Description 給定整數N,求1<=x,y<=N且Gcd(x,y)為素數的 數對(x,y)有多少對. Input 一個整數N Output 如題 Sample Input 4 Sample Output 4 Hint

篩選+唯一分解(模板)

#include<bits/stdc++.h> #define MAXN 1000005 using namespace std; typedef long long ll; ll prime[MAXN]; ll vis[MAXN]; ll cnt; ll n;

Farey Sequence——(篩函式)

傳送門 A - Farey Sequence Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d &