소수 구하기의 핵심이론
대표적인 판별법으로는 에라토스테네스의 체를 들 수 있다.
에라토스테네스의 체란?
- 구하고자 하는 소수의 범위만큼 1차원 배열을 생성한다.
- 2부터 시작하고 현재 숫자가 지워지지 않을 때는 현재 선택된 숫자의 배수에 해당하는 수를 배열에서 끝까지 탐색하면서 지운다. 이때 처음으로 선택된 숫자는 지우지 않는다.
- 배열의 끝까지 2를 반복한 후 배열에서 남아 있는 모든 수를 출력한다.
에라토스테네스의 체를 사용할 때 시간 복잡도는?
일반적으로 에라토스테네스의 체를 구현하려면 이중 for문을 이용하므로 시간 복잡도가 O(N²) 라고 판단 할 수 있다.
하지만 실제 시간 복잡도는 최적화의 정도에 따라 다르지만, 일반적으로 O(Nlog(logN))이다.
그 이유는 배수를 삭제하는 연산으로 실제 구현에서 바깥쪽 for문을 생략하는 경우가 빈번하게 발생하기 때문이다.
예제 1
https://www.acmicpc.net/problem/1929
1929번: 소수 구하기
첫째 줄에 자연수 M과 N이 빈 칸을 사이에 두고 주어진다. (1 ≤ M ≤ N ≤ 1,000,000) M이상 N이하의 소수가 하나 이상 있는 입력만 주어진다.
www.acmicpc.net
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
int[] A = new int[n+1];
for (int i = 2; i <= n; i++) {
A[i] = i;
}
for (int i = 2; i <= Math.sqrt(n); i++) {
if(A[i] == 0) {
continue;
}
for (int j = i+i; j <= n; j = j+i) {
A[j] = 0;
}
}
for (int i = m; i<=n; i++) {
if(A[i] != 0) {
System.out.println(A[i]);
}
}
}
}
예제 2
https://www.acmicpc.net/problem/1456
1456번: 거의 소수
어떤 수가 소수의 N제곱(N ≥ 2) 꼴일 때, 그 수를 거의 소수라고 한다. 두 정수 A와 B가 주어지면, A보다 크거나 같고, B보다 작거나 같은 거의 소수가 몇 개인지 출력한다.
www.acmicpc.net
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long min = sc.nextLong();
long max = sc.nextLong();
long[] A = new long[10000001];
for (int i = 2; i < A.length; i++) {
A[i] = i;
}
for (int i = 2; i <= Math.sqrt(A.length); i++) {
if(A[i] == 0) {
continue;
}
for (int j = i+i; j < A.length; j = j+i) {
A[j] = 0;
}
}
int count = 0;
for (int i = 2; i < 10000001; i++) {
if (A[i] != 0) {
long temp = A[i];
while((double)A[i] <= (double)max/(double) temp) {
if ((double)A[i] >= (double)min/(double) temp) {
count++;
}
temp = temp * A[i];
}
}
}
System.out.println(count);
}
}
예제 3
https://www.acmicpc.net/problem/1747
1747번: 소수&팰린드롬
어떤 수와 그 수의 숫자 순서를 뒤집은 수가 일치하는 수를 팰린드롬이라 부른다. 예를 들어 79,197과 324,423 등이 팰린드롬 수이다. 어떤 수 N (1 ≤ N ≤ 1,000,000)이 주어졌을 때, N보다 크거나 같고,
www.acmicpc.net
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] A = new int[10000001];
for (int i = 2; i < A.length; i++) {
A[i] = i;
}
for (int i = 2; i <= Math.sqrt(A.length); i++) {
if (A[i] == 0) {
continue;
}
for (int j = i+i; j < A.length; j = j+i) {
A[j] = 0;
}
}
int i = n;
while (true) {
if (A[i] != 0) {
int result = A[i];
if(isPalindrome(result)) {
System.out.println(result);
break;
}
}
i++;
}
}
private static boolean isPalindrome(int result) {
char temp[] = String.valueOf(result).toCharArray();
int s = 0;
int e = temp.length - 1;
while (s < e) {
if (temp[s] != temp[e]) {
return false;
}
s++;
e--;
}
return true;
}
}
예제 4
https://acmicpc.net/problem/1016
1016번: 제곱 ㄴㄴ 수
어떤 정수 X가 1보다 큰 제곱수로 나누어 떨어지지 않을 때, 그 수를 제곱ㄴㄴ수라고 한다. 제곱수는 정수의 제곱이다. min과 max가 주어지면, min보다 크거나 같고, max보다 작거나 같은 제곱ㄴㄴ수
www.acmicpc.net
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long min = sc.nextLong();
long max = sc.nextLong();
boolean[] check = new boolean[(int) (max - min + 1)];
//2의 제곱수인 4부터 max보다 작거나 같은 값까지 반복하기
for (long i = 2; i*i <= max; i++) {
long pow = i*i;
long start_index = min/pow;
if (min % pow != 0) {
start_index++; //나머지가 있으면 1을 더해야 min보다 큰 제곱수에서 시작됨.
}
for (long j = start_index; pow * j <= max; j++) {
check[(int) ((j * pow) - min)] = true;
}
}
int count = 0;
for (int i = 0; i <= max - min; i++) {
if(!check[i]) {
count++;
}
}
System.out.println(count);
}
}
'🤷♂️Algorithm' 카테고리의 다른 글
[트리] 트리 알아보기 (0) | 2024.05.06 |
---|---|
[정수론] 유클리드 호제법 (0) | 2024.04.11 |
[백준 11047] 카드 정렬하기 (그리디) (0) | 2024.03.30 |
[백준 2343] 기타레슨 (이진 탐색) (0) | 2024.03.27 |
[백준 1377] 버블 소트 (버블 정렬) (0) | 2024.03.05 |
소수 구하기의 핵심이론
대표적인 판별법으로는 에라토스테네스의 체를 들 수 있다.
에라토스테네스의 체란?
- 구하고자 하는 소수의 범위만큼 1차원 배열을 생성한다.
- 2부터 시작하고 현재 숫자가 지워지지 않을 때는 현재 선택된 숫자의 배수에 해당하는 수를 배열에서 끝까지 탐색하면서 지운다. 이때 처음으로 선택된 숫자는 지우지 않는다.
- 배열의 끝까지 2를 반복한 후 배열에서 남아 있는 모든 수를 출력한다.
에라토스테네스의 체를 사용할 때 시간 복잡도는?
일반적으로 에라토스테네스의 체를 구현하려면 이중 for문을 이용하므로 시간 복잡도가 O(N²) 라고 판단 할 수 있다.
하지만 실제 시간 복잡도는 최적화의 정도에 따라 다르지만, 일반적으로 O(Nlog(logN))이다.
그 이유는 배수를 삭제하는 연산으로 실제 구현에서 바깥쪽 for문을 생략하는 경우가 빈번하게 발생하기 때문이다.
예제 1
https://www.acmicpc.net/problem/1929
1929번: 소수 구하기
첫째 줄에 자연수 M과 N이 빈 칸을 사이에 두고 주어진다. (1 ≤ M ≤ N ≤ 1,000,000) M이상 N이하의 소수가 하나 이상 있는 입력만 주어진다.
www.acmicpc.net
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
int[] A = new int[n+1];
for (int i = 2; i <= n; i++) {
A[i] = i;
}
for (int i = 2; i <= Math.sqrt(n); i++) {
if(A[i] == 0) {
continue;
}
for (int j = i+i; j <= n; j = j+i) {
A[j] = 0;
}
}
for (int i = m; i<=n; i++) {
if(A[i] != 0) {
System.out.println(A[i]);
}
}
}
}
예제 2
https://www.acmicpc.net/problem/1456
1456번: 거의 소수
어떤 수가 소수의 N제곱(N ≥ 2) 꼴일 때, 그 수를 거의 소수라고 한다. 두 정수 A와 B가 주어지면, A보다 크거나 같고, B보다 작거나 같은 거의 소수가 몇 개인지 출력한다.
www.acmicpc.net
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long min = sc.nextLong();
long max = sc.nextLong();
long[] A = new long[10000001];
for (int i = 2; i < A.length; i++) {
A[i] = i;
}
for (int i = 2; i <= Math.sqrt(A.length); i++) {
if(A[i] == 0) {
continue;
}
for (int j = i+i; j < A.length; j = j+i) {
A[j] = 0;
}
}
int count = 0;
for (int i = 2; i < 10000001; i++) {
if (A[i] != 0) {
long temp = A[i];
while((double)A[i] <= (double)max/(double) temp) {
if ((double)A[i] >= (double)min/(double) temp) {
count++;
}
temp = temp * A[i];
}
}
}
System.out.println(count);
}
}
예제 3
https://www.acmicpc.net/problem/1747
1747번: 소수&팰린드롬
어떤 수와 그 수의 숫자 순서를 뒤집은 수가 일치하는 수를 팰린드롬이라 부른다. 예를 들어 79,197과 324,423 등이 팰린드롬 수이다. 어떤 수 N (1 ≤ N ≤ 1,000,000)이 주어졌을 때, N보다 크거나 같고,
www.acmicpc.net
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] A = new int[10000001];
for (int i = 2; i < A.length; i++) {
A[i] = i;
}
for (int i = 2; i <= Math.sqrt(A.length); i++) {
if (A[i] == 0) {
continue;
}
for (int j = i+i; j < A.length; j = j+i) {
A[j] = 0;
}
}
int i = n;
while (true) {
if (A[i] != 0) {
int result = A[i];
if(isPalindrome(result)) {
System.out.println(result);
break;
}
}
i++;
}
}
private static boolean isPalindrome(int result) {
char temp[] = String.valueOf(result).toCharArray();
int s = 0;
int e = temp.length - 1;
while (s < e) {
if (temp[s] != temp[e]) {
return false;
}
s++;
e--;
}
return true;
}
}
예제 4
https://acmicpc.net/problem/1016
1016번: 제곱 ㄴㄴ 수
어떤 정수 X가 1보다 큰 제곱수로 나누어 떨어지지 않을 때, 그 수를 제곱ㄴㄴ수라고 한다. 제곱수는 정수의 제곱이다. min과 max가 주어지면, min보다 크거나 같고, max보다 작거나 같은 제곱ㄴㄴ수
www.acmicpc.net
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long min = sc.nextLong();
long max = sc.nextLong();
boolean[] check = new boolean[(int) (max - min + 1)];
//2의 제곱수인 4부터 max보다 작거나 같은 값까지 반복하기
for (long i = 2; i*i <= max; i++) {
long pow = i*i;
long start_index = min/pow;
if (min % pow != 0) {
start_index++; //나머지가 있으면 1을 더해야 min보다 큰 제곱수에서 시작됨.
}
for (long j = start_index; pow * j <= max; j++) {
check[(int) ((j * pow) - min)] = true;
}
}
int count = 0;
for (int i = 0; i <= max - min; i++) {
if(!check[i]) {
count++;
}
}
System.out.println(count);
}
}
'🤷♂️Algorithm' 카테고리의 다른 글
[트리] 트리 알아보기 (0) | 2024.05.06 |
---|---|
[정수론] 유클리드 호제법 (0) | 2024.04.11 |
[백준 11047] 카드 정렬하기 (그리디) (0) | 2024.03.30 |
[백준 2343] 기타레슨 (이진 탐색) (0) | 2024.03.27 |
[백준 1377] 버블 소트 (버블 정렬) (0) | 2024.03.05 |