Algorithm/Algorithm
[Algorithm] 에라토스테네스의 체
도리닥닥
2021. 12. 27. 17:00
728x90
1. 개요
- 고대 그리스의 수학자 에라토스테네스가 만들어 낸 소수(primary number)를 찾는 방법이다. 마치 체를 치듯 수를 걸러낸다고 하여 '에라토스테네스의 체'라고 부른다고 함.
- 임의의 자연수 n에 대하여 그 이하의 소수를 찾는 가장 간단하고 빠른 방법.
2. 방법
1. 2부터 소수를 구하고자 하는 구간의 모든 수를 나열 한다.
2. 2는 소수이므로 오른쪽에 2를 쓴다.
3. 자기 자신을 제외한 2의 배수를 모두 지운다.
4. 남아있는 수 가운데 3은 소수이므로 오른쪽에 3을 쓴다.
5. 자기 자신을 제외한 3의 배수를 모두 지운다.
......
위 과정을 반복하면 구간의 모든 소수가 남는다.
3. 구현
- C++
void Eratos(int n)
{
/* 만일 n이 1보다 작거나 같으면 함수 종료 */
if (n <= 1) return;
/* 2부터 n까지 n-1개를 저장할 수 있는 배열 할당
배열 참조 번호와 소수와 일치하도록 배열의 크기는
n+1 길이만큼 할당(인덱스 번호 0과 1은 사용하지 않음) */
bool* PrimeArray = new bool[n + 1];
/* 배열초기화: 처음엔 모두 소수로 보고 true값을 줌 */
for (int i = 2; i <= n; i++)
PrimeArray[i] = true;
/* 에라토스테네스의 체에 맞게 소수를 구함
만일, PrimeArray[i]가 true이면 i 이후의 i 배수는 약수로 i를
가지고 있는 것이 되므로 i 이후의 i 배수에 대해 false값을 준다.
PrimeArray[i]가 false이면 i는 이미 소수가 아니므로 i의 배수 역시
소수가 아니게 된다. 그러므로 검사할 필요도 없다.
또한 i*k (k < i) 까지는 이미 검사되었으므로 j시작 값은 i*2에서 i*i로 개선할 수 있다.
*/
for (int i = 2; i * i <= n; i++)
{
if (PrimeArray[i])
for (int j = i * i; j <= n; j += i)
PrimeArray[j] = false;
}
// 이후의 작업 ...
}
4. 응용 문제
https://www.acmicpc.net/problem/1929
1929번: 소수 구하기
첫째 줄에 자연수 M과 N이 빈 칸을 사이에 두고 주어진다. (1 ≤ M ≤ N ≤ 1,000,000) M이상 N이하의 소수가 하나 이상 있는 입력만 주어진다.
www.acmicpc.net
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n,m;
cin >> n >> m;
vector<int> v(m+1);
v[1] = 1; // 1은 소수가 아니므로 체크.
for(int i = 2; i <= m; i++) {
for(int j = 2 * i; j <= m; j = j+i) { // i를 곱해줌으로서 자기자신은 체크하지 않음.
v[j] = 1; // 체크된 수들은 소수가 아님.
}
}
for(int i = n; i <= m; i++) {
if(v[i] == 0) cout << i << '\n';
}
}
출처 : 위키백과, 백준