Review the sieve method-small optimization

Elbow Sieve

Time complexity: O (nloglogn)

First, for a composite number n, there must be a prime factor less than or equal to the radical n .

A composite number refers to a number that can be divisible by other numbers (except 0) in addition to being integers greater than 1 and itself.

It is easy to understand: Take 4 as an example, a*b=4, it can be easily known from the inequality,
Insert picture description here
so it is easy to get: For a composite number n, there must be a prime factor less than or equal to the radical n.

So it can be pruned

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100
int a[MAXN];//a[i]= 0 表示i是质数,利用全局变量为0,免得写初始化。。。

int main()
{
    
    
    for(int i=2;i*i<=MAXN;i++)//筛选的质因数i
   	 	for(int j=i*i;j<=MAXN;j+=i)
  			if(!a[j])a[j]=1;
//对于一个合数j来说,必然存在一个小于等于根号j的质因数,所以已经被前面的i筛过一次了
//这里就不需要j=i*2开始筛了,直接从i*i开始筛即可
    for(int i=2;i<=MAXN;i++)//输出
        if(!a[i])cout<<i<<" ";
    return 0;
}

Generally, the Ehrlich sieve method is enough to write the questions, and the Ehrlich sieve cannot pass the problems, and most of the Euler sieve cannot be passed. There is no need to write so long. . . (Algorithm Xiaocaiji's feelings)


Euler Sieve

I feel that the problem is similar to the Ehrlich sieve method. . . The difference is not big ( O(n) ), unless the amount of data is extremely large, the Eschweiz sieve method is mainly written quickly.

/*
欧拉(线性)筛法
思想:在埃式筛法上进行了优化,去除掉无用功(没有被重复的删),但由于欧拉筛法的特判有取模运算,小范围效率可能不如埃式筛法
*/
//关键点:每个合数只被他最小的质因数筛去
//时间复杂度O(n)
/*
如果i%prime[j]==0,那么i就可以看成prime[i]乘以一个数(记为n);
因为我们存的prime是从小到大存的,所以prime[j+1]>prime[j];
那么i*prime[j+1]就可以看成prime[j]*n*prime[j+1];
那么i*prime[j+1]的最小质因子是prime[j]。
加上if(i%prime[j]==0) break后
我们就可以保证每一个数只被它的最小质因子给筛去,
那么每一个数只会被筛一次,那么时间复杂度为O(n)。
举个例子,6=2*3;当i=2时i%2=0,跳出循环,那它就不会被质因子3给筛去;
当i=3时,6就被质因子2给筛去了。
*/
#include<bits/stdc++.h>
using namespace std;
#define N 200

int a[N],primes[N],n,cnt;
/*
分为三步:
1.将质数加入质数表
2.筛选的时候,将数乘与质数表里面的每一个数,从而筛去合数
3.关键点在于如果被最小的数筛到了就break
*/
void sieve()
{
    
    
    memset(a,1,sizeof(a));
    for(int i=2;i<=n;i++){
    
    
        if(a[i])primes[cnt++]=i;
        for(int j=0;j<cnt&&primes[j]*i<=n;j++){
    
    
            a[primes[j]*i]=0;
            if(i%primes[j]==0)break;
        }
    }
}

void out()
{
    
    
    for(int i=0;i<cnt;i++)
        cout<<primes[i]<<"\t";
    cout<<"\n\n";
    for(int i=2;i<=n;i++)
        if(a[i])cout<<i<<"\t";
}

int main()
{
    
    
    cin>>n;
    sieve();
    out();
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43615816/article/details/114852689