素数的求法

  一般素数的求法有两种,一种是埃氏筛法,还有一种是线性筛(即欧拉筛法)。

埃氏筛法(时间复杂度O(nlognlogn))

  给出要筛数值的范围  n,找出  n以内的素数p1,p2,p3,......,pk。先用2去筛,即把2留下,把2的倍数剔除掉;再用下一个素数,也就是3筛,把3留下,把3的倍数剔除掉;接下去用下一个素数5筛,把5留下,把5的倍数剔除掉;不断重复下去......。

int m = sqrt (n + 0.5);
memset(vis,0,sizeof(vis));
for(int i=2;i<=m;i++)
    if( !vis[i] )
        for(int j=i*i;j<=n;j+=i)
            vis[j]=1;

  用一个数组来储存素数表

int m = sqrt (n + 0.5); // n + 0.5解决精度问题
memset(vis,0,sizeof(vis));
memset(prime,0,sizeof(prime));
int cnt=1,i;
for(i=2;i<=m;i++)
    if( !vis[i] ){
        prime[cnt++]=i;
        for(int j=i*i;j<=n;j+=i)
            vis[j]=1;
    }

for(;i<=n;++i){
    if(!vis[i]) prime[cnt++]=i;

欧拉筛法(O(n))

  埃氏筛法的问题在于他把每个合筛了不只一次,所以我们需要通过优化来使每个合数只需要一遍就能被筛出来,即为欧拉筛法

  

for( int i = 2 ; i <= n ; ++i ){
        if( IsPrime[ i ] )
            Pri[ PriN++ ]=i; //将这句话放在下面的循环前以保证PriN和Pri值的完整性
        for(int j=0;j<PriN;++j){
            if( i*Pri[ j ] > MaxN )
                break; //当过大了就跳出
            IsPrime[ i * Pri[ j ] ] = 0;
            //筛去素数
            if( i % Pri[ j ] == 0 ) break;
            //这里是关键,如果i是一个合数(这当然是允许的)而且i mod prime[j] = 0
            //那么跳出,因为i*prime[ (- over -)j ]一定已经被筛去了,被一个素因子比i小的数
        }
    }
原文地址:https://www.cnblogs.com/2020pengxiyue/p/9093524.html