判断一个数是否为质数的方法

基本思路

其实很简单,不必用深搜广搜,也不必用贪心动规,单是枚举就能搞定!

是的,你没听错!枚举!

从小到大枚举,依次判断是否能整除n,只要有一个数可以整除n,就可以证明n是一个合数,若没有一个数可以整除n,就可以证明n为一个质数。

我们都知道,枚举最重要的就是要确定范围。

因为所有数都能被1整除,n mod n 等于 0,所以范围应该是2~n-1。

但是还要判断n是否为1,因为众所周知,1既不是质数,也不是合数。

代码如下: 

bool isPrime(int n) {
	if(n == 1) {	// 1不是质数
		return false;
	}
	// 枚举范围: 2~n-1
	for(int i = 2; i < n; ++i) {
		if(n % i == 0) {	// 判断n是否能被i整除
			return false;
		}
	}
	return true; 
}

由于在C++中,return返回后,函数会自动终止执行,所以我们不需要break之类的东西。

优化

枚举范围可以缩小到i * i <= n。

bool isPrime(int n) {
	if(n == 1) {	// 1不是质数
		return false;
	}
	// 枚举范围: 2~n-1
	for(int i = 2; i <= n / i; ++i) {    // 为防止越界,故i<=n/i
		if(n % i == 0) {	// 判断n是否能被i整除
			return false;
		}
	}
	return true; 
}

再优化

其实还有一种算法叫作埃氏筛,代码如下:

这种算法适合筛批量的素数。

时间复杂度O(nlogn)

void getPrimes(int n) {
    memset(prime, 1, sizeof prime);    // 排除1的情况
	for(int i = 2; i <= n; ++i) {
		if(!prime[i]) continue;
		for(int j = i << 1; j <= n; j += i) {
			prime[j] = 0;   // 将素数的倍数筛去
        }
    }
}
 
​

还不够快?

怎么办?

其实我们还可以使用欧拉筛法。

原理和埃氏筛法一样,但是多了一句话:

if(i % prime[j] == 0) break;

这样就可以达到O(n)的效果了!

总结

所以,我们要根据自己需要来选择合适的算法。

不能为了用而用。

不过强烈推荐O(n)的欧拉筛,

速度很快。

再见!

除了试除法,判断一个是否为素还有其他的方法,下面介绍几种常用的方法。 1. 质数筛选法 质数筛选法是一种较为常见的素判断方法,其思想是先将待判断列出一些小于等于它的质数,然后判断是否能被这些质数整除。具体实现可以采用埃式筛法或欧拉筛法等,时间复杂度均为 O(nloglogn)。 2. Fermat测试 Fermat测试是一种基于费马小定理的素测试方法,其原理是:如果 p 是素,且 a 是小于 p 的正整,则 a^(p-1) mod p = 1。因此,我们可以随机选取一些 a 值,进行计算,如果不等于 1,则 p 不是素。如果等于 1,则 p 可能是素,需要进行多次测试以提高准确性。 需要注意的是,Fermat测试对于一些合也可能返回为素,因此需要多次测试以提高准确性。 3. Miller-Rabin算法 Miller-Rabin算法是一种基于Fermat测试的素测试算法,其原理是:对于一个 n,有至少一半的 a 值,满足 a^(n-1) mod n != 1。因此,我们可以随机选取一些 a 值,进行计算,如果不等于 1,则 n 不是素。如果等于 1,则 n 可能是素,需要进行多次测试以提高准确性。 需要注意的是,Miller-Rabin算法的准确性与测试次有关,测试次越多,准确性越高。一般来说,10次左右的测试已经可以满足绝大多情况。时间复杂度为 O(klog^3n),其中 k 为测试次。 以上是常见的几种素判断方法,每种方法都有其优缺点,可以根据实际情况选择合适的方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值