求素数及素数表的获取

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

最小的质数是2。

1.素数的判断

由于一些题目中素数的判断只是其中的一部分,所以如果这个时候的时间复杂度为O(n)实际上有点大了,所以我们需要更加快速的判定方法。注意到如果在2~n-1中存在n的约数,不妨设为k,即n%k == 0,那么由k * (n/k) ==n可知,n/k也是n的一个约数,且k与n/k中一定满足其中一个小于sqrt(n)另一个大于sqrt(n),其中sqrt(n)为根号n。

所以,我们只需要判定n能否被2,3,……sqrt(n)中的一个整除,即可判定n是否为素数,其算法的时间复杂度为O(sqrt(n)).

代码如下:

bool isPrime(int n){
	if(n <= 1) return false;
	int aqr = (int)sqrt(1.0*n);
	for(int i = 2; i <= sqr; i++)
	{
		if(n % i == 0) return false;
	}
	return true;
}

上述代码中,sqrt的作用是为一个浮点数开根号,需要添加math.h头文件。

由于sqrt的参数要求是浮点数,因此在n前面需要乘上1.0使其变成浮点型。


2.素数表的获取

用以上的方法实现素数的判断后,时间复杂度为O(sqrt(n) ),现在要把这些素数都加到素数表中就很容易了,直接采用枚举的方法即可,而枚举部分的复杂度为O(n),所以总复杂度为O(n*sqrt(n))。这个复杂度对n不超过十的五次方的大小是没有问题的,考试时大部分涉及素数表的题目都不会超过这个范围,代码如下:

const int maxn = 101;  
int prime[maxn], pNum = 0;
bool p[maxn] = {0};
void Find_Prime() {
	for(int i = 1; i < maxn; i++)
	{
		if(isPrime(i) == true){
			prime[pNum++] = i;
			p[i] = true;
		}
	}
}

上面算法在n到十的五次方以内都是可以承受的,如果出现大范围素数表需要求解,以上解法将力不从心,所以可以使用各种“筛法”,其中“埃式筛法”是最简单的一种。

其实“埃式筛法”就是如果我发现了某一个数是一个素数,那么这个数的所有倍数,都不是素数了,就把这些倍数全部筛掉了。

A[i] = i;
for(int k = 2; k < maxn; k++)
{
	if(A[k]!= -1)
		for(j = 2; j*k<n; j++)
			A[j*k] = -1;
}


下面为一个具体的例子:

给定两个数,求两个数之前的所有素数。

#include <stdio.h>
const int maxn = 1000001;
int prime[maxn], num = 0;
bool p[maxn] = {0};
void Find_Prime (int n) {
    for(int i = 2; i < maxn; i++) {
        if(p[i] == false) {
            prime[num++] = i;
            // 只需要n个素数,因此超时即可结束
            if(num >= n) break;
            for(int j = i + i; j < maxn; j +=i) {
                p[j] = true;// 都不是素数
            }
        }
    }
}

int main() {
    int m, n, count = 0;
    scanf("%d%d", &m, &n);
    Find_Prime(n);
    // 输出从第m个素数至第n个素数
    for(int i = m; i <= n; i++) {
        // 下标从0开始
        printf("%d",prime[i - 1]);
        count++;
        if(count % 10 != 0 && i < n) printf(" ");
        else printf("\n");
    }
    return 0;
}







  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值