【算法-简单数学问题】- 素数表的获取(简单方法和埃式筛法)

素数与素数表基本概念

素数又称为质数,是指除了1和本身之外,不能被其他数整除的一类数。注意: 1既不是素数,也不是合数。

直接对于一定范围内的素数进行判定求取素数表,采用直接简单遍历的方式,这样的时间复杂度为O(n),那么如果使用加快的方法可以这样分析:
如果在2 ~ n-1中存在n的约数,那么不妨设这个约数为k,那么由k*(n/k) ==n可知,n/k也是n的一个约数,并且k与n/k必然一个小于sqrt(n),而另一个大于sqrt(n),通过这样的思路就可以降低算法的复杂度。

示例代码:

bool isPrime(int n) {
    if(n <= 1) return false; // 特判
    int sqr = (int)sqrt(1.0 * n);  //求得根号n
    for(int i = 2; i < sqr; i++) {  // 遍历2~根号n
        if(n % i == 0) return false; // n是i的倍数,则n不是素数
    }
    return true; // n是素数
}

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

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

素数表的获取

用以上的方法实现素数表的获取,时间复杂度为O(n*根号n)
如果出现大范围素数表需要求解,以上解法将力不从心,所以可以使用各种“筛法”,其中“埃式筛法”是最简单的一种。

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

求正整数M~N之间的所有素数:

算法代码:

#include 
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;
}

这里需要注意的几点:

  • 1不是素数
  • 素数表长至少要比n大1
  • 在Find+Prime()函数中要特别留意i < maxn不能写成i <= maxn
  • main函数中要记得调用Find_Prime(),不然不会出现结果

你可能感兴趣的:(C/C++,算法和数据结构)