【欧拉筛求素数】


普通求素数是对每一个数的因子进行枚举,进而判断它是否是素数,但会很慢。

进阶一点的是埃式筛法,埃式筛法的基本思想就是,当我们遍历到一个素数时,把所有该素数的倍数(自然是合数)都筛选出来。但是这样同样会有重复筛选的情况而浪费时间,比如2的倍数有6,而3的倍数同样会把6,再次筛选一遍。

于是便有了欧拉筛来求素数的方法。

int prime[MAXN];
bool vis[MAXN];
int cnt=0;
void Euler_prime(int n) {
	for(int i=2; i<=n; ++i) {
		if(!vis[i]) {
			prime[cnt++]=i;    //vis[i]置为true或不置true都可以
			vis[i]=true;
		}
		for(int j=0; j<cnt; ++j) {
			if(i*prime[j]>n)//判断是否越界
				break;
			vis[i*prime[j]]=true;//筛数
			if(i%prime[j]==0)//时间复杂度为O(n)的关键!
				break;
		}
	}
}

在欧拉筛里面最为关键的一步便是if(i%prime[j]==0),而其最本质的思想是用最小质因数来筛掉一个合数
首先可以知道的是一个正整数,如果它不是素数那么就一定会有素数因子。但是一个数的最小质因子肯定只有一个,那么就表明,我们一定可以用最小质因子来筛掉一个非素数。

证明:p j 一定是i的最小质因数。因为pj是质数且,如果 i 还有比pj更小的因子,由于p数组是有序的,所以会在更靠前的位置被枚举到。为了满足"于任意一个合数,它会且只会它的最小因数筛掉",所以小于等于pj的质数都可以被使用。而对于大于pj的质数,i里明显有着比pj更小的质数。

其次我们需要证明在一个合数被筛掉之前不会被当成素数纳入素数合集。这个合数k可以被表示为ipj,可以知道的是i和pj一定比k小,那么一定先别遍历到,那么就一定会被ipj筛掉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值