에라토스테네스의 체란?
하나의 수가 소수인지 판정하는 것은 \(O(\sqrt N)\)이면 됩니다. 하지만 \(1\)부터 \(N\)
까지의 모든 소수가 필요하다면, 각 수를 따로 판정하면 \(O(N \sqrt N)\)으로 느립니다.
에라토스테네스의 체(Sieve of Eratosthenes) 는 이 문제를 거의 \(O(N)\)에 가깝게
푸는 고전 알고리즘입니다. 핵심 발상은 단순합니다 — 소수를 찾기보다, 합성수를
지운다.
1. 동작 원리
\(2\)부터 시작해, 어떤 수가 아직 지워지지 않았다면 그것은 소수입니다. 그 소수의
배수들을 전부 지웁니다. 다음 안 지워진 수로 넘어가 반복합니다.
2 3 4 5 6 7 8 9 10 11 12 ...
2의 배수 지움: 4 6 8 10 12 지움
3의 배수 지움: 9 12(이미) 지움
5의 배수 지움: 10(이미) ...
남은 것: 2 3 5 7 11 ... → 소수!
"한 수가 소수냐"를 묻는 대신 "소수의 배수를 일괄 제거"하는 것이 핵심 전환입니다.
2. 왜 빠른가: 복잡도
배수를 지우는 총 횟수는
$$ \frac{N}{2} + \frac{N}{3} + \frac{N}{5} + \cdots = N \sum_{p \le N} \frac{1}{p} $$
이 조화급수(소수에 대한)는 \(\ln \ln N\)으로 수렴해, 전체 복잡도가
\(O(N \log \log N)\)입니다. \(\log \log N\)은 사실상 작은 상수에 가까워, 실용적으로
거의 선형입니다. \(N = 10^7\)까지도 순식간에 처리됩니다.
3. 핵심 최적화 두 가지
체를 짤 때 두 가지 최적화를 반드시 기억하세요.
- \(\sqrt N\)까지만 거르기: \(i > \sqrt N\)인 소수의 배수는 이미 더 작은 소인수에
의해 지워졌습니다. 그래서 바깥 반복은 \(i \le \sqrt N\)까지만. - \(i \times i\)부터 지우기: \(i\)의 배수 중 \(2i, 3i, \dots, (i{-}1)i\)는 더 작은
소수가 이미 지웠습니다. 그래서 \(i^2\)부터 시작합니다.
이 두 가지를 빠뜨려도 답은 맞지만, 넣으면 눈에 띄게 빨라집니다.
4. 체가 주는 부가 정보
체는 소수 목록만 주지 않습니다. 살짝 바꾸면 더 많은 걸 얻습니다.
| 변형 | 얻는 것 |
|---|---|
| 지울 때 표시 대신 최소 소인수 기록 | \(O(\log N)\) 소인수분해 |
| 약수 개수/합 누적 | 모든 수의 약수 정보 |
| 선형 체(linear sieve) | 진짜 \(O(N)\) + 곱셈적 함수 |
특히 빠른 소인수분해가 강력합니다. 각 수의 가장 작은 소인수를 미리 체로
구해 두면, 어떤 수든 \(O(\log N)\)에 소인수분해할 수 있습니다.
5. 언제 쓰나
- 여러 수의 소수 여부를 반복해서 물어볼 때.
- 어떤 범위의 소수를 모두 나열해야 할 때.
- 많은 수를 빠르게 소인수분해해야 할 때.
반대로 수 하나만 판정한다면 \(O(\sqrt N)\) 시도 나눗셈이 더 간단합니다.
정리
체는 "소수를 찾는다"가 아니라 "합성수를 지운다"는 발상의 전환입니다.
\(O(N \log \log N)\)에 범위 내 모든 소수를 얻고, 약간 변형하면 빠른 소인수분해까지
공짜로 따라옵니다.