素数与素数筛

文章目录

      • 素数的定义
      • 素数的判断
        • 从2到 x \sqrt x x 的证明:
      • 素数筛法:
        • 1.Eratosthenes 筛法
      • 线性筛法

素数的定义

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

素数的判断

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

bool is_prime(int x) {
	for(int i=2;i

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

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

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

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

啊,其实还有更简单的判断方法:Miller-Rabin。耳熟能详个屁,自行学习吧。

素数筛法:

1.Eratosthenes 筛法

这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的情况
2 2,3,4,5,6,7,8,9,10,11,12
3 2,3,4,5,6,7,8,9,10,11,12
5 2,3,4,5,6,7,8,9,10,11,12
7 2,3,4,5,6,7,8,9,10,11,12
11 2,3,4,5,6,7,8,9,10,11,12

可以发现,2和3都会把6标记为合数。实际上,小于x2的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 ;
}

啊,简单。

你可能感兴趣的:(数论)