素数简介
素数(prime number)又称质数,有无限个。
素数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。
接下来介绍几种判断素数的方法:
问法1:给定一个数n,判断n是不是素数
一、暴力枚举
枚举2~n-1
分别当做除数,判断是否能整除,如果某个数能把n
整除,那么就说明n
不是素数,如果所有都不能整除,那么n
就是素数。
注:n=1或n=2时需要特判
详见代码:
bool work(int n)
{
if(n==1)return false;
if(n==2)return true;
for(int i=2;i<=n-1;i++)
{
if(n%i==0)return false;
}
return true;
}
然而这样会很慢......
二、优化过的暴力算法
由于n至少会有一个约数在sqrt(n)中,所以我们可以直接枚举从2~sqrt(n),这样便会快不少。
详见代码:
bool work(int n)
{
if(n==1)return false;
if(n==2)return true;
for(int i=2;i*i<=n;i++)//这里也可以写成i<=sqrt(n)
{
if(n%i==0)return false;
}
return true;
}
以上所说的算法只是用来判断单个素数的,但是若是要求1~n之间的素数该怎么办呢?
还是暴力?
不!
要用到一个名叫“筛法”的东东
三、埃氏筛法
由于我们知道,2的任何倍数都不可能是素数,3的任何倍数不可能是素数,5的任何倍数不可能是素数......
所以我们可以把素数的倍数全部筛掉。
详见代码:
/*
vis用来判断有没有被筛掉,
prime用来存储素数
cnt代表素数总数
*/
for(int i=2;i<=n;i++)
{
if(vis[i]==1)continue;
prime[++cnt]=i;
for(int j=1;j*i<=n;j++)//筛掉素数的所有倍数
{
vis[j*i]=1;
}
}
但是以12为例
12是2的倍数,被筛
12是3的倍数,被筛++
所以事实证明会有一些数被筛好多次
那要怎么做到每个数只筛一次的线性复杂度呢?
四、线性筛
线性筛,又称欧拉筛
欧拉筛法的基本思想 :在埃氏筛法的基础上,让每个合数只被它的最小质因子筛选一次,以达到不重复的目的。
/*
vis用来判断有没有被筛掉,
prime用来存储素数
cnt代表素数总数
*/
for(int i=2;i<=n;i++)
{
if(!vis[i])prime[++cnt]=i;
for(int j=1;j<=cnt&&i*prime[j]<=n;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
以上就是素数判断及筛法的总结,谢谢观看
参考文献资料:
https://www.baidu.com
https://blog.csdn.net/qq_39763472/article/details/82428602