게시물은 엄청 오랜만에 올리는 것 같은데..ㅎㅎ
백준 풀면서 에러가 어떤 에러인지 잘 읽어보라는 교훈을 얻게 되어서 오랜만에 게시글을 쓰게 되었다.
일단 거의 소수 문제부터 설명해보겠다
문제 링크
1456번: 거의 소수
어떤 수가 소수의 N제곱(N ≥ 2) 꼴일 때, 그 수를 거의 소수라고 한다. 두 정수 A와 B가 주어지면, A보다 크거나 같고, B보다 작거나 같은 거의 소수가 몇 개인지 출력한다.
www.acmicpc.net
문제
어떤 수가 소수의 N제곱(N ≥ 2) 꼴일 때, 그 수를 거의 소수라고 한다.
두 정수 A와 B가 주어지면, A보다 크거나 같고, B보다 작거나 같은 거의 소수가 몇 개인지 출력한다.
입력
첫째 줄에 왼쪽 범위 A와 오른쪽 범위 B가 공백 한 칸을 사이에 두고 주어진다.
출력
첫째 줄에 총 몇 개가 있는지 출력한다.
제한
1 ≤ A ≤ B ≤ 1014
일단 여기서 어떤 수가 소수의 N제곱(N>=2) 꼴일 때 그걸 거의 소수라고 하는데 A보다 크거나 같고, B보다 작거나 같은 거의 소수가 몇 개인지 출력하라는 문제이다.
여기서 중요한 점 2개는 일단 첫번째로 A와 B의 범위가 10^14 보다 작거나 같을 수 있기 때문에 long형을 사용해야하며,
그 어떤 수의 제곱 꼴을 찾을 때 소수들 중에서 제곱 세제곱 네제곱꼴 등을 저장할 때 그것과 B를 비교하게 되면 ,,
즉, N^k 와 B를 비교하게 되면 LONG 형 범위를 초과할 수도 있기 때문에
그 둘의 비교 대신에 N과 B/(N^(k-1)) 을 비교하는 걸로 바꿔서 계산하는 게 중요한 점인 것 같다..
사실 소수 구하는 건 에라토스테네스의 체 구하면서 구하면 되고 그것들의 제곱한 수, 세제곱, 네제곱 계속 해가면서
그 B보다 작은 수 코드로 잘 비교하면 되는거라 코드 자체는 어렵지는 않았던 것 같은데
계속 런타임 에러가 났다..
다음부터 꼭 에러가 나면 ()안에 왜 오류가 떴는지 읽어보길...
처음에는 런타임 오류라는 글자만 보고 왜 그러지? 아 소수 구할 때 모든 범위 안 구해도 되고 그 제곱근까지만 구해보면 되는데(에라토스테네스의 체) 그 부분 때문에 오류가 났나? 고민을 또 하다가
계속 오류 나길래 포기할까 했는데 엄청 어이없는 실수였음
long A = Long.parseLong(st.nextToken());
long 형을 받으려면 Long.parseLong으로 받아야 하는데...
계속 long A = Integer.parseInt(st.nextToken()); 이렇게 받으려고 하니까 오류가 나지 바보야
근데 심지어 런타임 에러(NumberFormat) 이렇게 자세하게 왜 오류가 났는지도 알려줬는데 이것도 안보고 내 코드만 보고 왜 오류나는지 탐색하고 있으니까 바보지
나중에 런타임 에러 날 때는 왜 오류나는지 꼭 확인하고 보라는 뜻에서 이렇게 게시글까지 작성하게 되었다.ㅎㅎ
코드
/*240324 P1456 거의 소수*/
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
/*범위 넘어가는 거 조심..!!*/
/*LONG 범위 넘어갈까봐 일부러 N^k 승이랑 B 비교 대신 */
/*N이랑 B/(N^(k-1)) 비교하는 걸로 바꿨음*/
/*어렵긴한데 이 문제에서 제곱근 이상이려면 이미 소수가 아니라고 걸러진 수들이니까 그 이후로 진행할 필요가 없었음*/
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
/*멍청이 long이라고 했으면서 integer로 받아서 계속 오류나는거였네*/
long A = Long.parseLong(st.nextToken());
long B = Long.parseLong(st.nextToken());
long[] array = new long[10000001]; // 10^14 승이길래 그거 제곱근 10^7까지반복 //왜냐면 그게 최대니까
for(int i = 2; i<array.length; i++) {
array[i] = i;
}
for (int i = 2; i <=Math.sqrt(array.length); i++) { // 설마.... 여기 부분 때문에 런타임 나는건가..?
if(array[i] == 0) {
continue;
}
for(int j = i+i; j<array.length; j = j+i) {
array[j] = 0;
}
}
int count = 0;
for(int i = 2; i < 10000001; i++) {
if (array[i] != 0) {
long t = array[i];
while((double)array[i] <= (double)B/(double)t) {
if((double)array[i] >= (double)A/(double)t) {
count++;
}
t = t * array[i];
}
}
}
System.out.println(count);
}
}
'공부기록 > 알고리즘' 카테고리의 다른 글
[알고리즘] 8-9일차 (0) | 2024.02.23 |
---|---|
[알고리즘] 7-8일차 (0) | 2024.02.22 |
[알고리즘] 6일차 (0) | 2024.02.20 |
[알고리즘] 5일차_그래프 (0) | 2024.02.19 |
[알고리즘] 4일차 (0) | 2024.02.16 |