素数与素数表基本概念
素数又称为质数,是指除了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 <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;
}
这里需要注意的几点:
- 1不是素数
- 素数表长至少要比n大1
- 在Find+Prime()函数中要特别留意i < maxn不能写成i <= maxn
- main函数中要记得调用Find_Prime(),不然不会出现结果