Eular质数筛法

  任意一个正整数k,若k≥2,则k可以表示成若干个质数相乘的形式。

  Eratosthenes筛法中,在枚举k的每一个质因子时,我们都计算了一次k,从而造成了冗余。因此在改进算法中,只利用k的最小质因子去计算一次k。

  而在其基础上改进的Eular筛法,其伪代码为:

isPrime[] = true
primeList = []
primeCount = 0
For i = 2 .. N
    If isPrime[i] Then
        primeCount = primeCount + 1
        primeList[ primeCount ] = i
    End If 
    For j = 1 .. primeCount
        If (i * primeList[j] > N) Then
            Break
        End If
        isPrime[ i * primeList[j] ] = false
        If (i % primeList[j]) Then
            Break
        End If
    End If
End For

  与Eratosthenes筛法不同的是,对于外层枚举i,无论i是质数,还是是合数,我们都会用i的倍数去筛。但在枚举的时候,我们只枚举i的质数倍。比如2i,3i,5i,...,而不去枚举4i,6i...,原因我们后面会讲到。

  此外,在从小到大依次枚举质数p来计算i的倍数时,我们还需要检查i是否能够整除p。若i能够整除p,则停止枚举。

  Eular筛法可以保证每个合数只会被枚举到一次,时间复杂度为O(n)。当N越大时,其相对于Eratosthenes筛法的优势也就越明显。

下面是实现代码:

int numPrime(int n){
    bool isPrime[1000005];
    for(int i = 0; i< 1000005; i++){
        isPrime[i] = true;
    } 
    int PrimeList[100000];
    int Primecount = 0;
    for(int i = 2; i<= n; i++){
        if(isPrime[i]){
            Primecount++;
            PrimeList[Primecount] = i;
        }
        for(int j = 1; j<= Primecount; j++){
            if(i*PrimeList[j] > n) break;
            isPrime[i*PrimeList[j]] = false;
            if(i%PrimeList[j] == 0 ) break;
        }
    }
//    for(int i = 1; i<= Primecount; i++) cout << PrimeList[i] << endl;
    return Primecount;
}
转载请注明出处:http://www.cnblogs.com/ygdblogs
原文地址:https://www.cnblogs.com/ygdblogs/p/5378743.html