埃氏筛+欧拉筛+区间筛

埃氏筛  O(nloglogn)

       埃氏筛的意义很简单,每次我对现在遍历到的素数进行枚举,对它的所有的在区间内的倍数进行枚举,这些枚举的数字都是合数,当我们把所有的区间内素数的倍数枚举完时,把他们都做上标记,未被标记的就是素数.这样还可以保证下次枚举的必定是素数,因为合数已经被标记了.

void getp()
{
	int cnt=0;
	vis[1]=1;
	for(int i=2;i<=n;i++)//枚举
		if(vis[i]==0)//判断是否为素数
			for(int j=2;j*i<=n;j++)//枚举倍数
				vis[i*j]=1;
	return ;
}
/*
vis标记为1的就不是素数,注意埃氏筛拓展之后就是区间筛
*/

但是埃氏筛有个缺点,我们每次进行素数倍数的枚举,会产生的重复的枚举,比如一个数字是某几个素数的倍数,就会重复枚举几次.如果我们能够消除重复的枚举,在这个前提之下,就创造出了欧拉筛.

欧拉筛  O(N)

        欧拉筛的含义就是优化的埃氏筛.每次我们判断某个数是否为素数,再去枚举,只不过它的欧典在于每个数只会去枚举一次.当当前的数和遍历的质因数整除时,就需要注意了,这个数已经枚举过了,直接break即可.

void getp()
{
	int cnt=0;
	for(int i=2;i<=n;i++)
	{
		if(vis[i]==0)
			p[++cnt]=i;
		for(int j=1;j<=cnt&&p[j]*i<=n;j++)
		{
			vis[i*p[j]]=1;
			if(i%p[j]==0)
				break;
		}
	}
	return ;
}

区间筛   时间复杂度类似于埃氏筛

区间筛是一种变种的埃氏筛,是对于某个数值大,但是区间长度仍在计算范围内的区间进行区间内素数问题求解的算法.我们首先要枚举2到\sqrt{R}的质数.然后用这些质数去枚举在区间[L,R]间的倍数,这些枚举的倍数就是合数,直接打上标记,区间内未被标记的就是素数.

void segment_sieve(int a,int b)
{
    for(int i=0;i<1e6+5;i++)
     isprime[i]=lowisprime[i]=true;
        for(int i=2;i*i<b;i++)
        {
            if(lowisprime[i])
             {
                for(int j=2*i;j*j<b;j+=i)
                     lowisprime[j]=false;
                for(long long j=(a/i)*i;j<b;j+=i)
                     if(j>=a&&j<b)
                         isprime[j-a]=false;
            }
        }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值