N = int(input())
K = int(input())
ST,EN = 1,K
while ST<=EN:
    mid = (ST+EN)//2
    cnt = 0
    for i in range(1,N+1):
        cnt += min(mid//i,N)

    if cnt < K:
        ST = mid + 1
    else:
        EN = mid -1

print(ST)

코드는 간단하지만, 어려웠던 문제였다.

 

자세한 설명은 다른 사람 블로그를 참조하길 바란다.

 

몇몇 케이스를 해보면 알지만 K번째의 수는 절대 K를 넘을 수가 없다.

 

이점을 이용해 1,K로 이분탐색을 한다.

 

각 행을 i라고 하면, 각 행은 i의 배수이다. 

 

즉 N = 5라고 하면 총 5행이 있고, 우리가 찾고자 하는 T = 12 라고 하면

 

1행에서 12보다 작거나 같은 값은 1,2,3,4,5          T//1 = 12

2행에서 12보다 작거나 같은 값은 2,4,6,8,10        T//2 = 6

3행에서 12보다 작거나 같은 값은 3,6,9,12,          T//3 = 4

4행에서 12보다 작거나 같은 값은 4,8,12,            T//4 = 3

5행에서 12보다 작거나 같은 값은 5,10               T//5 = 2

 

위와 같이 보면 우리가 찾고자 하는 값보다 작은 값의 개수는 각 행의 값을 나눈 몫 만큼이다. 그리고 각 행의 열의 개수는 N이므로, N과 비교해서 최소값으로 한다.

 

이분 탐색을 반복하면서 특정 값보다 작거나 같은 값의 개수가 K개가 될때까지 반복해준다. 또한 ST == END가 될때까지 반복해준다. 왜냐하면 K가 되는 값이 여러개가 될수 있으므로, 특정해줘야한다.

K개 에서 그냥 빠져 나올 경우 

N=52, K=276

에서 답이 잘못 나온다.

'알고리즘 > 백준' 카테고리의 다른 글

[BOJ/백준] 2252 줄 세우기  (0) 2021.03.12
[BOJ/백준] 11066 파일 합치기  (0) 2021.03.12
[BOJ/백준] 5052 전화번호 목록  (0) 2021.03.11
[BOJ/백준] 1963 소수 경로  (0) 2021.03.11
[BOJ/백준] 1504 특정한 최단 경로  (0) 2021.03.11

+ Recent posts