数学筛法--很全--在noip中的运用--Sabrina--Sabrinadol

1.求素数用到的方法
(1)普通枚举 枚举到sqrt(n)就好
(2)朴素筛法
通过对每个数有无非平凡因子来判断
朴素筛法 nlogn ,这个时间复杂度的计算有些复杂
如下
n/2+n/3+n/4+…+n/n;
n(1/2+1/3+1/4+…+1/n)
后面那一坨大致就约等于 ln(n) (学过数竞应该知道)

int a[maxn],b[maxn],n;
int cnt=0;
//筛出 2 到 n 中的所有素数 


void naive_sieve(int n){
	for(int i=2;i<=n;i++)
	{
		if(!a[i]) b[cnt++]=i;
		for(int j=2*i;j<=n;j+=i)//从i+i往后筛所有的倍数
		a[j]=1;
	}
}

(3)埃式筛法
通过素因子来筛

int a[maxn],b[maxn],n;
int cnt=0;
//优化, nloglogn ,这里的计算跟上个差不多,埃式筛法 
void naive_sieve(int n){
	for(int i=2;i<=n;i++)
	{
		if(!a[i]) 
		{
			b[cnt++]=i;
			for(int j=2*i;j<=n;j+=i)//将此循环体拿到if依据里面
			//意思就是,在遍历筛的时候遇到的如果是合数就不用筛了,优化
			a[j]=1;
		} 
	}
}

(4)线性筛(欧拉筛)


void oula_sieve(int n)
{
	int cnt=0;
	for(int i=2;i<=n;i++)
	{
		if(!a[i]) b[cnt++]=a[i];
		for(int j=0;b[j]*i<=n;j++)
		{
			a[b[j]*i]=1;
//			保证b[j]是i*b[j]1的最小素因子 
			if(i%b[j]==0) break;
		}
	}
} 

大家可能对以上三种方法及其优化思路还有疑问,下面加深讲解
1.基本思想其实都是先筛掉有非平凡因数的合数筛掉,再进行存储
2.举下面 一个栗子
比如说我们要筛 12这个数
(1)朴素筛 : 除1外每个数都要去把12筛一遍
也就是我们扫到这些数都要去把12筛 : 2 3 4 6
(2)埃氏筛 : 除1外每个质因数都要去把12筛一遍
也就是我们扫到这些数都要去把12筛 : 2 3

(3)欧拉筛 :
可能有人不太懂
1–j代表的是下标
2–b[]存储找到的素数
代码中的第二重(if依据巧妙避开求重)可以让标记只让当前找到的素因数往后标记
3–还是举12的例子
12的最小质因数会将12筛出
也就是只有:2

4–总结欧拉筛:

每次用已筛出来的质数去筛更大的数,
每个合数只被它最小的质因子筛掉,
试想,如果26筛了12之后还没break,
而是用3
6筛掉18,那么18还会被29筛一次,就重复了
而根本原因就是6有2这个因子,
而3
6筛掉的数一定也有2这个因子,
3*6这个数应该被2这个因子筛掉,而不是3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值