위 문제를 풀다가 사소하지만 주의점 하나를 발견하여 기록해보려한다.
import java.io.*;
import java.util.Scanner;
import java.util.function.DoubleToLongFunction;
public class K번째_수 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int N = Integer.parseInt(br.readLine());
int k = Integer.parseInt(br.readLine());
long left = 0;
long right = Math.min(N*N, (long)Math.pow(10,9));
long mid = 0;
while(left+1<right){
mid = (left + right)/2;
long count = 0;
for(long i = 1; i<=N; i++){
count += Math.min(mid / i, N);
}
if(count<k){
left = mid;
}else right = mid;
}
bw.write(right+"");
bw.flush();
}
}
위 코드는 논리적으로 맞았지만 오답이었다.
입력을 보면 N은 10^5이하의 값이고, k는 최대 10^9이기 때문에 나는 조심하려고 N과 M을 제외하고는 모두 long
으로 선언했다. 어차피 N과 M은 int
의 범위 내이기 때문이다.
그런데 왜 틀렸을까?
바로 아래 코드 때문이다.
long right = Math.min(N*N, (long)Math.pow(10,9));
여기서 right를 long
으로 선언한 것은 잘했지만 Math.min
의 N*N
에서 문제가 발생한다.
N이 int
이므로 N*N
도 int
로 인식하는 것이다. 따라서 오버플로우가 발생할 수 있다.
결국 해결하려면 N도 long
으로 선언해야하는 것이다.
아래가 정답 코드이다.
import java.io.*;
import java.util.Scanner;
import java.util.function.DoubleToLongFunction;
public class K번째_수 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
long N = Long.parseLong(br.readLine());
int k = Integer.parseInt(br.readLine());
long left = 0;
long right = Math.min(N*N, (long)Math.pow(10,9));
long mid = 0;
while(left+1<right){
mid = (left + right)/2;
long count = 0;
for(long i = 1; i<=N; i++){
count += Math.min(mid / i, N);
}
if(count<k){
left = mid;
}else right = mid;
}
bw.write(right+"");
bw.flush();
}
}
Math.min()
과Math.max()
안에서 변수를 사용하여 계산하는 값은 그 변수의 자료형을 따름에 주의하자.