素数与素数筛

素数的定义

啊,耳熟能详。素数又称质数,一个大于 1 1 1的自然数,除了 1 1 1和它本身外,不能被其他自然数整除,换句话说就是该数除了 1 1 1和它本身以外不再有其他的因数;否则称为合数。啊! 1 1 1不是素数啊

素数的判断

啊,也耳熟能详了,暴力枚举一下除 1 1 1和本身的自然数是否会被整除。

bool is_prime(int x) {
	for(int i=2;i<x;i++)
		if(x%i==0) return 0;
	return 1;
}

啊,其实可以优化的,也耳熟能详(我真欠揍),我们只用从 2 2 2 x \sqrt x x 就可以了。

2 2 2 x \sqrt x x 的证明:

很容易发现这样一个事实:如果 a a a x x x的约数,那么 x a \frac{x}{a} ax也是 x x x的约数。
得证。
代码:

bool is_prime(int x) {
	for(int i=2;i<=sqrt(x);i++)
		if(x%i==0) return 0;
	return 1;
}

啊,其实还有更简单的判断方法: M i l l e r − R a b i n Miller-Rabin MillerRabin。耳熟能详个屁,自行学习吧。

素数筛法:

1. E r a t o s t h e n e s Eratosthenes Eratosthenes筛法

E r a t o s t h e n e s Eratosthenes Eratosthenes一长串不是人读的是一个人的名字:埃拉托斯特尼。啊,耳熟能详。 E r a t o s t h e n e s Eratosthenes Eratosthenes筛法的原理非常简单:一个素数的倍数一定不是素数。
代码:

void Eratosthenes(int n) {
	for(int i=2;i<=n;i++) {
		if(check[i]) continue;
		prime[++cnt]=i;
		for(int j=2;j<=n/2;j++)
			check[i*j]=1;
	}
	return ;
}

过程如下:

正在处理的数数组check的情况
22,3,4,5,6,7,8,9,10,11,12
32,3,4,5,6,7,8,9,10,11,12
52,3,4,5,6,7,8,9,10,11,12
72,3,4,5,6,7,8,9,10,11,12
112,3,4,5,6,7,8,9,10,11,12

可以发现, 2 2 2 3 3 3都会把 6 6 6标记为合数。实际上,小于x2 x x x的倍数在之前就会被标记,所以我们可以优化为:

void Eratosthenes(int n) {
	for(int i=2;i<=n;i++) {
		if(check[i]) continue;
		prime[++cnt]=i;
		for(int j=i;j<=n/i;j++)
			check[i*j]=1;
	}
	return ;
}

时间复杂度为 O ( n   l o g   l o g   n ) O(n \ log \ log \ n) O(n log log n),显而易见。

线性筛法

埃式筛法也会重复标记,一个数的素数约数越多,重复标记越多。
我就不具体讲了,推荐一篇博客
代码:

void yu(int n) {
	check[1]=1;
	for(int i=2;i<=n;i++) {
		if(!check[i]) prime[++cnt]=i;
		for(int j=1;j<=cnt && i*prime[j]<=n;j++) {
			check[i*prime[j]]=1;
			if(i%prime[j]==0) break;
		}
	}
	return ;
}

啊,简单。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值