C++ 欧拉筛法求素数
时间: 2024-09-24 16:15:18 浏览: 147
欧拉筛法是一种用于找出一定范围内所有质数的有效算法,它比简单的Sieve of Eratosthenes(埃拉托斯特尼筛法)更节省空间。在C++中,我们可以按以下步骤实现欧拉筛法:
1. **初始化数组**:创建一个大小为n+1的布尔数组isPrime,初始值都设为true。表示从2到n的所有数字都是潜在的质数。
2. **筛选过程**:从第一个质数2开始,遍历到√n,对每个质数p,将它的倍数标记为合数。但是,由于每次遇到质数,只需要更新那些大于或等于p^2的倍数,因为之前的倍数已经被较小的质数标记了。这一步可以利用位操作(如位移)提高效率。
```cpp
for (int p = 2; p * p <= n; ++p) {
if (isPrime[p]) { // 如果p是质数
for (int i = p * p; i <= n; i += p) {
isPrime[i] = false;
}
}
}
```
3. **生成素数序列**:最后,将isPrime数组中值为true的位置对应的索引即为素数。例如,isPrime[2]、isPrime[3]、isPrime[5]等。
相关问题
欧拉筛法求素数 c++
以下是使用欧拉筛法求素数的C++代码:
```c++
#include <iostream>
using namespace std;
const int MAXN = 1000000; // 筛数范围
int prime[MAXN + 5]; // 存储素数
bool isPrime[MAXN + 5]; // 标记是否为素数
int EulerSieve(int n) {
int cnt = 0; // 素数个数
for (int i = 2; i <= n; i++) {
if (!isPrime[i]) {
prime[cnt++] = i; // 将素数存入prime数组
}
for (int j = 0; j < cnt && i * prime[j] <= n; j++) {
isPrime[i * prime[j]] = true; // 标记合数
if (i % prime[j] == 0) { // 保证每个合数只被标记一次
break;
}
}
}
return cnt;
}
int main() {
int n;
cin >> n;
int cnt = EulerSieve(n);
for (int i = 0; i < cnt; i++) {
cout << prime[i] << " ";
}
return 0;
}
```
第1关:欧拉筛法求素数
### 欧拉筛法求素数的算法实现
欧拉筛法是一种高效的素数筛选方法,能够在 \(O(n)\) 的时间复杂度下找到指定范围内所有的素数。其核心思想是通过已知的素数逐步排除掉那些可以由较小素数乘积构成的合数。
以下是基于 C++ 实现的一个完整的欧拉筛法代码示例:
```cpp
#include <iostream>
#include <vector>
using namespace std;
const int MAXN = 1000000; // 定义最大范围
int prime[MAXN], is_prime[MAXN], cnt = 0; // prime用于存储素数,is_prime用于标记素数(0为素数,1为合数),cnt记录素数个数
void euler_sieve(int n) {
for (int i = 2; i <= n; i++) {
if (!is_prime[i]) { // 如果当前数未被标记为合数,则它是素数
prime[cnt++] = i; // 将该素数存入prime数组
}
for (int j = 0; j < cnt && i * prime[j] <= n; j++) {
is_prime[i * prime[j]] = 1; // 标记i*prime[j]为合数
if (i % prime[j] == 0) break; // 当前i能够被prime[j]整除时退出循环
}
}
}
int main() {
int n;
cout << "请输入一个正整数N:" << endl;
cin >> n;
euler_sieve(n);
cout << "N内的所有素数及个数如下:" << endl;
for (int i = 0; i < cnt; i++) {
cout << prime[i] << endl;
}
cout << "共有" << cnt << "个素数" << endl;
return 0;
}
```
#### 关键点解析
1. **初始化**
使用 `is_prime` 数组来标记某个数字是否为素数,初始状态下假设所有大于等于2的数字均为素数[^2]。
2. **外层循环**
遍历从2到n的所有数字,如果某数字未被标记为合数,则将其视为素数并保存至 `prime` 数组中[^2]。
3. **内层循环**
对于每一个新发现的素数,利用它去标记它的倍数为合数。为了避免重复标记某些数字,当满足条件 `i % prime[j] == 0` 时立即跳出循环[^2]。
4. **效率优化**
每个合数只会被其最小质因数对应的素数标记一次,因此整个过程的时间复杂度降低到了线性级别 $ O(n) $。
---
###
阅读全文
相关推荐
















