根据给定文件的信息,本文将深入探讨五种不同的方法来快速筛选出10亿以内的素数和非素数,并对这些方法进行分析与比较。 ### 快速筛选素数 #### 方法一:朴素筛选法(Eratosthenes筛) 此方法是最直观的筛选素数的方法之一,通过遍历每个数并标记其倍数来实现筛选。 **核心思想**: 1. **初始化**:创建一个布尔数组`flag`,将其所有元素设为`false`。 2. **筛选过程**: - 遍历2到`MAXN`之间的每一个数。 - 如果当前数未被标记,则它是素数,记录下来,并将该素数的所有倍数标记为非素数。 3. **结束条件**:当遍历到`MAXN`时,筛选完成。 这种方法简单易懂,但效率较低,尤其是对于较大的数值范围。 #### 方法二:优化的朴素筛选法 在方法一的基础上进行了优化,只考虑奇数,从而减少了一半的计算量。 **核心思想**: 1. **初始化**:同方法一,创建一个布尔数组`flag`。 2. **筛选过程**: - 从3开始遍历,每次增加2,直到`MAXN`。 - 如果当前数未被标记,则它是素数,记录下来,并将该素数的所有奇数倍数标记为非素数。 3. **结束条件**:同方法一。 通过跳过偶数(除了2),可以显著提高筛选速度。 #### 方法三:试除法 该方法使用试除的方式判断一个数是否为素数。 **核心思想**: 1. **初始化**:同方法一,创建一个布尔数组`flag`。 2. **筛选过程**: - 对于每个数`i`,从3开始,每次增加2,判断是否有因子。 - 如果存在因子,则不是素数;否则是素数。 3. **结束条件**:同方法一。 这种方法虽然直观,但由于对每个数都需要执行除法运算,因此效率不高。 #### 方法四:线性筛法 这种方法在筛选过程中尽可能避免重复标记,从而提高了效率。 **核心思想**: 1. **初始化**:同方法一,创建一个布尔数组`flag`。 2. **筛选过程**: - 遍历2到`MAXN`之间的每一个数。 - 如果当前数未被标记,则它是素数,记录下来。 - 使用已知的素数来标记非素数,一旦遇到当前数是已知素数的倍数时,就停止标记。 3. **结束条件**:同方法一。 这种方法通过减少重复工作来提升效率,尤其是在处理大范围数据时效果显著。 #### 方法五:位操作筛选法 利用位操作来节省内存空间,进一步提高效率。 **核心思想**: 1. **初始化**:创建一个整型数组`bit`,每个整数表示32个数的状态。 2. **筛选过程**: - 遍历2到`MAXN`之间的每一个数。 - 如果当前数对应的位没有被标记,则它是素数,记录下来,并标记其倍数。 3. **结束条件**:同方法一。 通过位操作减少了所需的存储空间,对于大范围数据特别有用。 ### 总结 以上五种方法分别代表了筛选素数的不同策略,从简单到复杂,每种方法都有其适用场景。朴素筛选法适用于小规模的数据集,而线性筛法和位操作筛选法则更适合处理大规模数据。实际应用中,可以根据具体需求选择合适的方法。
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
#include<memory.h>
#include<time.h>
const int MAXN = 10000000;
bool flag[MAXN];
int prime[664600], num; //10^7
//int prime[5761500], num; //10^8
int bit[MAXN / 32];
// 利用对每个素数的倍数必定不是素数来筛选
void GetPrime_1()
{
int i, j;
num = 0;
memset(flag, false, sizeof(flag));
for (i = 2; i < MAXN; ++i)
{
if (!flag[i])
{
prime[num++] = i;
for (j = i; j < MAXN; j += i)
flag[j] = true;
}
}
- 粉丝: 1w+
- 资源: 1
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助