ภาพรวม
Sieve of Eratosthenes (ถังเอราโทสเธนีส) เป็นอัลกอริทึมที่มีประสิทธิภาพสูงสุดสำหรับการหาจำนวนเฉพาะทั้งหมดที่น้อยกว่า n เมื่อ n < 10 ล้าน ประมาณ ความซับซ้อนด้านเวลา O(n log log n) เร็วกว่าการตรวจสอบแต่ละตัว O(n√n) มาก
หลักการทำงาน
- สร้าง Boolean Array
isPrime[0...n]เริ่มต้นทั้งหมด = true - ตั้ง
isPrime[0] = isPrime[1] = false - วน i = 2 ถึง √n:
- ถ้า
isPrime[i]ยังเป็น true → i เป็นจำนวนเฉพาะ - ทำเครื่องหมาย
falseให้ทุก Multiple ของ i (เริ่มจาก i×i)
- ถ้า
- ค่าที่เหลือเป็น true = จำนวนเฉพาะ
โค้ดตัวอย่าง (Optimized)
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
void sieveOfEratosthenes(int n) {
vector<bool> isPrime(n + 1, true);
isPrime[0] = isPrime[1] = false;
int limit = static_cast<int>(sqrt(n));
for (int i = 2; i <= limit; i++) {
if (isPrime[i]) {
// เริ่มจาก i*i เพราะตัวกู่อาจถูกทำเครื่องหมายแล้ว
for (int j = i * i; j <= n; j += i) {
isPrime[j] = false;
}
}
}
cout << "Prime numbers up to " << n << ": ";
for (int i = 2; i <= n; i++) {
if (isPrime[i]) cout << i << " ";
}
cout << "\n";
}
int main() {
int n;
cout << "Enter upper limit: ";
cin >> n;
sieveOfEratosthenes(n);
return 0;
}
ผลลัพธ์ตัวอย่าง
Enter upper limit: 15
Prime numbers up to 15: 2 3 5 7 11 13
การเพิ่มประสิทธิภาพ (Optimizations)
1. Bit-Packed Sieve (ลด Memory 8x)
// ใช้ vector<unsigned char> หรือ bitset แทน vector<bool>
// vector<bool> เป็น specialization ที่บีบอัดเป็น 1 bit แล้ว
// แต่ Manual Bit-Packing เร็วกว่าสำหรับ Cache
vector<uint8_t> sieve((n >> 3) + 1, 0xFF); // 1 bit ต่อจำนวน
2. Wheel Factorization (ข้าม Even Numbers)
// เก็บเฉพาะ Odd Numbers: index i แทนเลข 2*i+1
// ลด Memory และ Operations เหลือครึ่ง
int size = (n - 1) / 2;
vector<bool> isPrime(size, true);
for (int i = 1; i * (2*i + 2) <= n; i++) { // i=1 → 3
if (isPrime[i]) {
int p = 2*i + 1;
for (int j = (p*p - 1)/2; j < size; j += p) {
isPrime[j] = false;
}
}
}
3. Segmented Sieve (สำหรับ n ใหญ่มาก > 10^9)
- แบ่งช่วง [0, n] เป็น Segments ขนาด √n
- หา Primes ≤ √n ด้วย Sieve ปกติ
- ประมวลผลแต่ละ Segment แยกกัน
- Memory O(√n) แทน O(n)
การเปรียบเทียบประสิทธิภาพ
| อัลกอริทึม | Time Complexity | Space | เหมาะสำหรับ |
|---|---|---|---|
| Trial Division | O(n√n) | O(1) | n < 10^4, ตรวจสอบตัวเดียว |
| Sieve of Eratosthenes | O(n log log n) | O(n) | n < 10^8, หาทั้งช่วง |
| Optimized Sieve (Bit + Wheel) | O(n log log n) | O(n/16) | n < 10^9, High Performance |
| Segmented Sieve | O(n log log n) | O(√n) | n > 10^9, Memory Limited |
| Miller-Rabin (Probabilistic) | O(k log³ n) | O(1) | Single Large Number Test |
ข้อสังเกต
- โค้ดต้นฉบับใช้
<bits/stdc++.h>(GCC Extension) → เปลี่ยนเป็น Standard Headers memsetบนvector<bool>ไม่ได้ → ใช้ Constructor หรือfill- Loop Condition:
i*i <= nป้องกัน Overflow ดีกว่าi <= sqrt(n) - สำหรับ Production ใช้ Library เช่น
primesieve(Fastest Known)