判断素数与求素数表(埃式筛,欧拉筛)

判断x是否为素数

bool isPrime ( int n)
{
     if(n<2) return 0; 	//0和1不是质数
     int tmp =n/2; 	//判断到n/2
     for(int i= 2;i <=tmp; i++)
        if(n %i== 0)	 //如果n与某数相除为0,则不是质数
          return 0 ;
     return 1 ;		//都除不尽,是质数
}

现在复杂度为O(n),注意上面的tmp其实可以直接优化到sqrt(n),原因:

1.如果是质数,则暴力枚举范围没有影响

2.如果是合数,则必有一个质因数<=sqrt(n),反证法:如果所有质因数都>sqrt(n),则相乘必>n,矛盾

下面只需要修改tmp的范围

bool isPrime ( int n)
{
     if(n<2) return 0; 	//0和1不是质数
     int tmp =sqrt(n); 	//判断到n/2
     for(int i= 2;i <=tmp; i++)
        if(n %i== 0)	 //如果n与某数相除为0,则不是质数
          return 0 ;
     return 1 ;		//都除不尽,是质数
}

复杂度O(sqrt(n))

上面的只是判断一个数是不是质数,如果要求出素数表,则需要更快的方法。

埃式筛法:

相当于先去掉2的倍数,再去掉3的倍数,再去掉5的,7的,11的……以此类推。

bool IsPrime[Maxn];			//标记i是否为质数
int Prime[Maxn];			//保存求得的质数
int Get_Prime(int n){
    int cnt = 0;				//统计n以内的质数的个数
    memset(IsPrime,true,sizeof(IsPrime));	//所有数一开始都为质数
    for(int i=2; i<=n; i++){		//外层循环从2到n
        if(IsPrime[i]){			//状态为质数的数必定是新的质数
            Prime[cnt++] = i;			//将其保存下来,且质数个数加一
            for(int j=i+i; j<=n; j+=i)		//内层循环将质数i的倍数都置为合数
                IsPrime[j] = false;
        }
    }
    return cnt;				//返回n以内的质数的个数
}

最后是更快一点的筛法,线性筛,也叫欧拉筛法。

本质上相当于任何一个合数都会被它的最小质因数作为基准删掉一次,

每个合数必定只存在一次最小质数数删除操作,故线性筛时间复杂度为O(n)

int Get_prime(int n){
    int cnt = 0;
    memset(IsPrime,true,sizeof(IsPrime));
    for (int i = 2; i <= n; i++){
        if (IsPrime[i])
            prime[cnt++] = i;
        for (int j = 0; j < cnt; j++){		//遍历质数表
            if (i*prime[j] > n) break;		//如果超过最大范围,跳出
            IsPrime[i*prime[j]] = false;		//将以prime[j]]为最小质因数的合数筛掉
            if (i%prime[j] == 0) break;		//保证只筛到以prime[j]为最小质因数的数
        }
    }
return cnt;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值