素数的判定五法

1.基本方法

输出\(n\)以内的所有质数,遍历\([1,n]\)的所有数,每个数\(p\)都不能被\([2,p]\)整除,则为质数

2.初步优化

针对任意数\(N\),如果有一个数\(p(p \le \sqrt{N})\)\(N\)的因子,则一定有\(u=\frac{N}{p}(u\geq \sqrt{N})\)也是它的因子,如果不存在\(p\)这样的因子,那么\(N\)就是质数

3.素数筛

时间复杂度:\(O(n)\)

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int pri[1005];
int n;
int main(){
	scanf("%d",&n); 
	for(int i=2;i<=n;i++){
		pri[i]=1;
	}
	for(int i=2;i<=sqrt(n)+1;i++){
		if(pri[i]){
			for(int j=2;j<=n/i;j++){
				pri[i*j]=0;
			}
		}
		
	}
	for(int i=2;i<=n;i++){
		if(pri[i]) printf("%d\n",i);
	}
	return 0;
}

4

埃氏筛法

该算法时间复杂度为:\(O(nloglogn)\)
\(n = 10^6\) 时 , 复杂度约为 \(7.7\times 10^5\),优于\(O(n)\)

//求100以内素数 
#include<iostream>
#include<cstring>
#include<string>
 
using namespace std;
bool vis[101];//标记是否为素数 
int prime[101];//储存素数 
 
int main()
{
	int n,m,j,k,i,T,t=0;
	memset(vis,true,sizeof(vis));//初始化,都默认为素数 
	for (i=2;i<100;i++)
	{
		if (vis[i]==true)//如果是素数 
		{
			prime[t++] = i;//把素数i储存进去 
			
			for (j=i+i;j<100;j+=i)//枚举素数i的倍数,然后标记为非素数 
			vis[j] = false;//标记为非素数 
		}
		
	}	
	for (i=0;i<t;i++)
	cout<<prime[i]<<endl;//打印答案 
	
	return 0;
}

5

质数还有一个特点,就是它总是等于 \(6x-1\) 或者 \(6x+1\),其中 x 是大于等于1的自然数。
如何论证这个结论呢,其实不难。首先 \(6x\) 肯定不是质数,因为它能被 \(6\) 整除;其次\(6x+2\) 肯定也不是质数,因为它还能被\(2\)整除;依次类推,\(6x+3\) 肯定能被 \(3\) 整除;\(6x+4\) 肯定能被\(2\) 整除。那么,就只有 \(6x+1\)\(6x+5\) (即等同于\(6x-1\)) 可能是质数了。所以循环的步长可以设为 \(6\),然后每次只判断 \(6\)两侧的数即可。

#include <cmath>
bool isPrime(int num) {
    if (num <= 3) {
        return num > 1;
    }
    // 不在6的倍数两侧的一定不是质数
    if (num % 6 != 1 && num % 6 != 5) {
        return false;
    }
    int sqrta = sqrt(num);
    for (int i = 5; i <= sqrta; i += 6) {
        if (num % i == 0 || num % (i + 2) == 0) {
            return false;
        }
    }
    return true;
}
posted @ 2019-12-05 22:00  刘子闻  阅读(668)  评论(0编辑  收藏  举报