에라토스테네스의 체
수 하나에 대하여 소수 인지 판정할 때는 밀러-라빈 소수판별법 같은 빠른 소수판별법을 사용하면 되지만 1부터 N 사이 같은 특정구간의 모든 소수가 필요한 경우도 존재합니다.
그럴때는 1부터 N까지 리스트를 쫙 깔아두고 그 리스트를 가지고 소수 리스트를 생성하게 됩니다.
예를 들어서 1부터 100 사이의 모든 소수를 원한다고 가정해보겠습니다.
$1$ |
$2$ |
$3$ |
$4$ |
$5$ |
$6$ |
$7$ |
$8$ |
$9$ |
$10$ |
$11$ |
$12$ |
$13$ |
$14$ |
$15$ |
$16$ |
$17$ |
$18$ |
$19$ |
$20$ |
$21$ |
$22$ |
$23$ |
$24$ |
$25$ |
$26$ |
$27$ |
$28$ |
$29$ |
$30$ |
$31$ |
$32$ |
$33$ |
$34$ |
$35$ |
$36$ |
$37$ |
$38$ |
$39$ |
$40$ |
$41$ |
$42$ |
$43$ |
$44$ |
$45$ |
$46$ |
$47$ |
$48$ |
$49$ |
$50$ |
$51$ |
$52$ |
$53$ |
$54$ |
$55$ |
$56$ |
$57$ |
$58$ |
$59$ |
$60$ |
$61$ |
$62$ |
$63$ |
$64$ |
$65$ |
$66$ |
$67$ |
$68$ |
$69$ |
$70$ |
$71$ |
$72$ |
$73$ |
$74$ |
$75$ |
$76$ |
$77$ |
$78$ |
$79$ |
$80$ |
$81$ |
$82$ |
$83$ |
$84$ |
$85$ |
$86$ |
$87$ |
$88$ |
$89$ |
$90$ |
$91$ |
$92$ |
$93$ |
$94$ |
$95$ |
$96$ |
$97$ |
$98$ |
$99$ |
$100$ |
1은 우선 소수가 아니니까 걸러줍니다.
$1$ |
$2$ |
$3$ |
$4$ |
$5$ |
$6$ |
$7$ |
$8$ |
$9$ |
$10$ |
$11$ |
$12$ |
$13$ |
$14$ |
$15$ |
$16$ |
$17$ |
$18$ |
$19$ |
$20$ |
$21$ |
$22$ |
$23$ |
$24$ |
$25$ |
$26$ |
$27$ |
$28$ |
$29$ |
$30$ |
$31$ |
$32$ |
$33$ |
$34$ |
$35$ |
$36$ |
$37$ |
$38$ |
$39$ |
$40$ |
$41$ |
$42$ |
$43$ |
$44$ |
$45$ |
$46$ |
$47$ |
$48$ |
$49$ |
$50$ |
$51$ |
$52$ |
$53$ |
$54$ |
$55$ |
$56$ |
$57$ |
$58$ |
$59$ |
$60$ |
$61$ |
$62$ |
$63$ |
$64$ |
$65$ |
$66$ |
$67$ |
$68$ |
$69$ |
$70$ |
$71$ |
$72$ |
$73$ |
$74$ |
$75$ |
$76$ |
$77$ |
$78$ |
$79$ |
$80$ |
$81$ |
$82$ |
$83$ |
$84$ |
$85$ |
$86$ |
$87$ |
$88$ |
$89$ |
$90$ |
$91$ |
$92$ |
$93$ |
$94$ |
$95$ |
$96$ |
$97$ |
$98$ |
$99$ |
$100$ |
짝수(즉, "$2$"의 배수)도 걸러줍니다.
단, $2$ 그 자체는 소수이므로 거르지 않습니다.
$1$ |
$2$ |
$3$ |
$4$ |
$5$ |
$6$ |
$7$ |
$8$ |
$9$ |
$10$ |
$11$ |
$12$ |
$13$ |
$14$ |
$15$ |
$16$ |
$17$ |
$18$ |
$19$ |
$20$ |
$21$ |
$22$ |
$23$ |
$24$ |
$25$ |
$26$ |
$27$ |
$28$ |
$29$ |
$30$ |
$31$ |
$32$ |
$33$ |
$34$ |
$35$ |
$36$ |
$37$ |
$38$ |
$39$ |
$40$ |
$41$ |
$42$ |
$43$ |
$44$ |
$45$ |
$46$ |
$47$ |
$48$ |
$49$ |
$50$ |
$51$ |
$52$ |
$53$ |
$54$ |
$55$ |
$56$ |
$57$ |
$58$ |
$59$ |
$60$ |
$61$ |
$62$ |
$63$ |
$64$ |
$65$ |
$66$ |
$67$ |
$68$ |
$69$ |
$70$ |
$71$ |
$72$ |
$73$ |
$74$ |
$75$ |
$76$ |
$77$ |
$78$ |
$79$ |
$80$ |
$81$ |
$82$ |
$83$ |
$84$ |
$85$ |
$86$ |
$87$ |
$88$ |
$89$ |
$90$ |
$91$ |
$92$ |
$93$ |
$94$ |
$95$ |
$96$ |
$97$ |
$98$ |
$99$ |
$100$ |
$3$의 배수도 걸러줍니다.
단, $3$ 그 자체는 소수이므로 거르지 않습니다.
$1$ |
$2$ |
$3$ |
$4$ |
$5$ |
$6$ |
$7$ |
$8$ |
$9$ |
$10$ |
$11$ |
$12$ |
$13$ |
$14$ |
$15$ |
$16$ |
$17$ |
$18$ |
$19$ |
$20$ |
$21$ |
$22$ |
$23$ |
$24$ |
$25$ |
$26$ |
$27$ |
$28$ |
$29$ |
$30$ |
$31$ |
$32$ |
$33$ |
$34$ |
$35$ |
$36$ |
$37$ |
$38$ |
$39$ |
$40$ |
$41$ |
$42$ |
$43$ |
$44$ |
$45$ |
$46$ |
$47$ |
$48$ |
$49$ |
$50$ |
$51$ |
$52$ |
$53$ |
$54$ |
$55$ |
$56$ |
$57$ |
$58$ |
$59$ |
$60$ |
$61$ |
$62$ |
$63$ |
$64$ |
$65$ |
$66$ |
$67$ |
$68$ |
$69$ |
$70$ |
$71$ |
$72$ |
$73$ |
$74$ |
$75$ |
$76$ |
$77$ |
$78$ |
$79$ |
$80$ |
$81$ |
$82$ |
$83$ |
$84$ |
$85$ |
$86$ |
$87$ |
$88$ |
$89$ |
$90$ |
$91$ |
$92$ |
$93$ |
$94$ |
$95$ |
$96$ |
$97$ |
$98$ |
$99$ |
$100$ |
$4$의 배수는 거를 필요가 없습니다.
$4$ 자체가 $2$의 배수라서 이미 걸러지고, $4$의 배수들도 $2$의 배수이기때문에 이미 걸러진지 오래입니다.
앞으로 $k$가 이미 걸러진 수라면, $k$의 배수도 이미 걸러져있을테니 무시해주도록 합니다.
$5$는 아직 걸러지지 않았으므로 $5$의 배수도 걸러줍니다.
단, $5$ 그 자체는 소수이므로 거르지 않습니다.
$1$ |
$2$ |
$3$ |
$4$ |
$5$ |
$6$ |
$7$ |
$8$ |
$9$ |
$10$ |
$11$ |
$12$ |
$13$ |
$14$ |
$15$ |
$16$ |
$17$ |
$18$ |
$19$ |
$20$ |
$21$ |
$22$ |
$23$ |
$24$ |
$25$ |
$26$ |
$27$ |
$28$ |
$29$ |
$30$ |
$31$ |
$32$ |
$33$ |
$34$ |
$35$ |
$36$ |
$37$ |
$38$ |
$39$ |
$40$ |
$41$ |
$42$ |
$43$ |
$44$ |
$45$ |
$46$ |
$47$ |
$48$ |
$49$ |
$50$ |
$51$ |
$52$ |
$53$ |
$54$ |
$55$ |
$56$ |
$57$ |
$58$ |
$59$ |
$60$ |
$61$ |
$62$ |
$63$ |
$64$ |
$65$ |
$66$ |
$67$ |
$68$ |
$69$ |
$70$ |
$71$ |
$72$ |
$73$ |
$74$ |
$75$ |
$76$ |
$77$ |
$78$ |
$79$ |
$80$ |
$81$ |
$82$ |
$83$ |
$84$ |
$85$ |
$86$ |
$87$ |
$88$ |
$89$ |
$90$ |
$91$ |
$92$ |
$93$ |
$94$ |
$95$ |
$96$ |
$97$ |
$98$ |
$99$ |
$100$ |
이미 걸러진 $6$의 경우 무시해줍니다.
$7$이 아닌 $7$의 배수를 걸러줍니다.
$1$ |
$2$ |
$3$ |
$4$ |
$5$ |
$6$ |
$7$ |
$8$ |
$9$ |
$10$ |
$11$ |
$12$ |
$13$ |
$14$ |
$15$ |
$16$ |
$17$ |
$18$ |
$19$ |
$20$ |
$21$ |
$22$ |
$23$ |
$24$ |
$25$ |
$26$ |
$27$ |
$28$ |
$29$ |
$30$ |
$31$ |
$32$ |
$33$ |
$34$ |
$35$ |
$36$ |
$37$ |
$38$ |
$39$ |
$40$ |
$41$ |
$42$ |
$43$ |
$44$ |
$45$ |
$46$ |
$47$ |
$48$ |
$49$ |
$50$ |
$51$ |
$52$ |
$53$ |
$54$ |
$55$ |
$56$ |
$57$ |
$58$ |
$59$ |
$60$ |
$61$ |
$62$ |
$63$ |
$64$ |
$65$ |
$66$ |
$67$ |
$68$ |
$69$ |
$70$ |
$71$ |
$72$ |
$73$ |
$74$ |
$75$ |
$76$ |
$77$ |
$78$ |
$79$ |
$80$ |
$81$ |
$82$ |
$83$ |
$84$ |
$85$ |
$86$ |
$87$ |
$88$ |
$89$ |
$90$ |
$91$ |
$92$ |
$93$ |
$94$ |
$95$ |
$96$ |
$97$ |
$98$ |
$99$ |
$100$ |
빨간색이 좀 너저분 해보이니 아예 빨간색으로 칠한 부분을 삭제해주도록 하겠습니다.
$1$ |
$2$ |
$3$ |
$\times$ |
$5$ |
$\times$ |
$7$ |
$\times$ |
$\times$ |
$\times$ |
$11$ |
$\times$ |
$13$ |
$\times$ |
$\times$ |
$\times$ |
$17$ |
$\times$ |
$19$ |
$\times$ |
$\times$ |
$\times$ |
$23$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$29$ |
$\times$ |
$31$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$37$ |
$\times$ |
$\times$ |
$\times$ |
$41$ |
$\times$ |
$43$ |
$\times$ |
$\times$ |
$\times$ |
$47$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$53$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$59$ |
$\times$ |
$61$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$67$ |
$\times$ |
$\times$ |
$\times$ |
$71$ |
$\times$ |
$73$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$79$ |
$\times$ |
$\times$ |
$\times$ |
$83$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$89$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$97$ |
$\times$ |
$\times$ |
$\times$ |
$8$은 이미 없어진지 오래입니다.
$9$와 $10$도 이미 없어졌습니다.
$11$의 배수를 걸러주려 했더니 이미 표에 $11$의 배수가 없습니다.
$13$의 배수도 없습니다...왜일까요?
$11$의 배수를 걸러준다는 것은 $11 \times 2$, $11 \times 3$, $11 \times 4$, ...를 걸러준다는 것인데
바꿔서 생각해보면 $2 \times 11$, $3 \times 11$, $4 \times 11$, ...이므로, $10 \times 11$까지는 이미 걸러진 것입니다.
$11 \times 11$부터 걸러야 하는데, $100$까지의 범위에서 거르기로 하였으므로 이미 끝난 셈입니다.
$N$까지의 범위에서 거르기로 했으면, $k \leq \sqrt{N}$인 $k$의 배수까지만 걸러주면 된다는 사실을 알았습니다.
소거는 이걸로 끝났고, 나머지 모두를 소수로 판정해줍니다.
$1$ |
$2$ |
$3$ |
$\times$ |
$5$ |
$\times$ |
$7$ |
$\times$ |
$\times$ |
$\times$ |
$11$ |
$\times$ |
$13$ |
$\times$ |
$\times$ |
$\times$ |
$17$ |
$\times$ |
$19$ |
$\times$ |
$\times$ |
$\times$ |
$23$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$29$ |
$\times$ |
$31$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$37$ |
$\times$ |
$\times$ |
$\times$ |
$41$ |
$\times$ |
$43$ |
$\times$ |
$\times$ |
$\times$ |
$47$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$53$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$59$ |
$\times$ |
$61$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$67$ |
$\times$ |
$\times$ |
$\times$ |
$71$ |
$\times$ |
$73$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$79$ |
$\times$ |
$\times$ |
$\times$ |
$83$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$89$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$\times$ |
$97$ |
$\times$ |
$\times$ |
$\times$ |
앞에서 이야기 한 주제들을 가지고 이제 코드로 만들어봅시다.
1. 1은 소수가 아니다.
2. 2가 아닌 짝수(2의 배수)는 소수가 아니다.
3. 차례차례 걸러지지 않은 수의 배수를 거른다.
4. $k$의 배수를 거를 때는 $k \times k$부터 걸러도 된다.
5. $k$의 배수를 거를 때 $k$가 소수가 아니라면 이미 걸러져 있으니 필요가 없다.
위키백과에 굉장히 잘 짜여진 코드 가 있으니 이를 기반으로 만들어주도록 합니다.
어지간하면 이정도 코드로도 충분히 체를 사용할 수 있습니다.
물론 최적화의 여지는 있습니다.
아예 return 부분에서 짝수 부분을 없는거처럼 그냥 계산한 다음에, 맨 앞에 2만 붙여주면 됩니다.
1, 2를 넣었을 때 결과로 2가 나와버리는 약간의 미스가 있지만, 굳이 에라토스테네스의 체에 2를 넣진 않을거라고 생각됩니다.
i * i부터 판단해줘도 되므로 구간도 바꿔주도록 합니다.
return 부분에서 아에 sieve 짝수 부분이 어떻게 되든 상관하지도 않으므로 애초에 i가 짝수일 때는 계산 하지 않아도 됩니다.
i가 홀수일 때만 검사하고, i * i(홀수)부터 검사를 시작하므로 2i만큼 거리를 두고 걸러주면 홀수만 건드릴 수 있습니다.
여기서 더욱 최적화 하면 Linear-sieve (선형 체) 로 진화하는 과정도 존재합니다.
"에라토스테네스의 체"의 시간복잡도는 어떻게 될까요?
1부터 n까지 $2$의 배수는 대략 $\frac{n}{2}$번 있고, $3$의 배수는 $\frac{n}{3}$번, $\frac{n}{5}$번, $\frac{n}{7}$번, $\frac{n}{11}$번, ...
$\sqrt{n}$ 이하의 모든 소수 $p$에 대하여 $\frac{n}{p}$의 값을 다 더한 $\sum\limits_{p \in \mathbb{P}, p \leq \sqrt{n}} \frac{n}{p}$의 값이 시간복잡도일텐데, 메르텐스의 제 2 정리 에 따라 $\sum\limits_{p \in \mathbb{P}, p \leq n} \frac{1}{p} \sim \ln{\ln n}$이므로, $\sum\limits_{p \in \mathbb{P}, p \leq \sqrt{n}} \frac{n}{p} = n \times \sum\limits_{p \in \mathbb{P}, p \leq \sqrt{n}} \frac{1}{p} \sim n \ln{\ln \sqrt{n}} \sim n \ln{\ln n}$에서, 시간복잡도는 $O(n \ln{\ln n})$이라는 다소 충격적인 복잡도로 나오게 됩니다. 이때, $O(f(n))$은 란다우 표기법 이고, $\ln n$은 자연로그함수 입니다.
$n = 10^9$일 때도 $\ln{\ln n} = 3.03125...$ 정도이고, $n = 2^{64}$일 때도 $\ln{\ln n} = 3.79237...$ 정도이므로, 거의 $O(n)$으로 생각해도 좋습니다. (어차피 10억개짜리 리스트를 만들면 메모리 초과가 날 것입니다.)