[数论] 质数

Posted zero_orez6

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[数论] 质数相关的知识,希望对你有一定的参考价值。

定义

在大于1的自然数中,若一个数的因数只有1和他本身,那么这个数被称为质数/素数,否则为合数。
注意,1既不是质数,也不是合数。

证明

那么如何证明一个正整数是不是质数呢(⊙o⊙)?

想必很多同学想到从2枚举到 n − 1 n-1 n1,若其中有 n n n的因数, n n n就是合数,否则为质数

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

这样的话复杂度较高,为 O ( n ) O(n) O(n)。大家可以仔细思考一下,

n = x ∗ y n=x*y n=xy的一个因数x小于 n \\sqrt{n} n ,那么 y y y 一定大于 n \\sqrt{n} n ,

所以我们可以对上面的代码进行修改。

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

筛法求质数

埃式筛

一般情况下,可以先用较为简单的方法将 [ 1 , n ] [1,n] [1,n]的所有质数求出,在调用时即可 O ( 1 ) O(1) O(1)复杂度求出。

那么如何将 [ 1 , n ] [1,n] [1,n]的质数快捷求出?可以直接遍历 [ 1 , n ] [1,n] [1,n]判断是否为质数,复杂度为 O ( n ∗ n ) O(n*\\sqrt n) O(nn )

但是再思考一下质数的性质,在后面的数中,有不少的数是之前质数的倍数,在判断出一个数是质数时,即可将它所有 < = n <=n <=n的倍数标记为非质数。

以上便是埃氏筛的思想,代码如下:

#include<bits/stdc++.h>
using namespace std;
bool f[100086];
bool pd(int x)
{
	for(int i=2;i<=sqrt(x);i++)
	{
		if(x%i==0) return 0;
	}
	return 1;
}
int main()
{
	memset(f,1,sizeof(f));
	int n,q;
	cin>>n>>q;
	for(int i=2;i<=n;i++)
	{
		if(pd(i)==1)
		{
			for(int j=2*i;j<=n;j+=i)
			{
				f[j]=0;
			}
		}
	}
	while(q--)
	{
		int x;
		cin>>x;
		if(f[x]==0) cout<<"NO"<<endl;
		else cout<<"YES"<<endl;
	}
	return 0;
 } 

线性筛

即使在优化后,埃式筛仍然会重复标记一些合数,例如对于合数 30 30 30,质数 2 , 3 , 5 2,3,5 2,3,5都会重复标记,所以我们应找出某种方法能够唯一的产生30。

线性筛因此产生,它通过“从大到小累计质因子”来标记每个合数,
设用数组v来记录每个数的最小质因子,按下列步骤来维护数组v
1.从 2   n 2~n 2 n循环每一个数 i i i
2.若 v [ i ] = i v[i]=i v[i]=i,则 i i i为质数,将它保存下来。
3.扫描不大于i的每个质数 p p p,令 v [ i ∗ p ] = p v[i*p]=p v[ip]=p,因为 p < = i p<=i p<=i,所以 p p p i ∗ p i*p ip的最小质因子。
每个合数只会被它的最小质因子筛一次,时间复杂度为 O ( n ) O(n) O(n)

int v[10086],prime[10086];
void primes(int n)
{
	memset(v,0,sizeof(v));
	int m=0;
	for(int i=2;i<=n;i++)
	{
		if(v[i]==0) 
		{
			v[i]=i;
			prime[++m]=i;
		}
		for(int j=1;j<=m;j++)
		{
			if(prime[j]>v[i]||prime[j]>n/i) brreak;
			v[i*prime[j]]=prime[j];
		}
	}
	for(int i=1;i<=m;i++)
	{
		cout<<prime[i]<<endl;
	}
}

以上是关于[数论] 质数的主要内容,如果未能解决你的问题,请参考以下文章

数论

信息学中的数论

[数论] 质数

数论二·Eular质数筛法

洛谷P2667 超级质数 [2017年6月计划 数论05]

数论小总结