강의로 돌아가기
이낙헌

이분탐색을 이용한 풀이(yellow의 약수를 찾는것 보다 효율적입니다.)

가장 효율적인건 근의 공식을 이용하는 것이지만, 그보다는 좀더 알고리즘적으로 효율적인 접근이 있어 공유해 드립니다.

좀 더 효율적인 풀이법은 이분 탐색을 이용하는 것입니다. 세로 길이를 x, 가로 길이를 y 라고 하였을때(x <= y),
둘레와 넓이를 생각하면 x + y = brown//2 + 2 이고 x * y = brown + yellow 라는 것을 알 수 있습니다.

여기서 x + y = brown//2 + 2 로 고정되기 때문에 x와 y를 적절히 잘 선택해서 그 곱이 brown + yellow가 되도록 하면 되는데, 이 때 x와 y의 차가 더 작을 수록 그 곱은 커진다는 성질을 이용하면 됩니다.

여기서 s = brown//2 + 2 라고 하면 x는 1 ~ s//2 의 범위를 가지게 되고, 이를 통해 y = s - x로 x * y의 값을 구할 수 있습니다.

우리가 구해야하는 곱을 m = brown + yellow이라 하면 x * y 가 m 보다 크면 x는 더 작아져야 하고(x와 y의 차가 더 커져야 그 곱이 작아지기 때문), 반대로 x * y가 m보다 작으면 x는 더 커져야 합니다.

따라서 1 ~ s//2 의 범위에서 x를 찾을때 x * y의 값을 보고 x가 더 커져야 하는지 작아져야 하는지 알수 있게 되는데, 이때 이분탐색으로 찾으면 효율적으로 찾을 수 있습니다.

이렇게 찾으면 O(log brown)이기 때문에 yellow의 약수를 찾는 O(root(yellow)) 보다 효율적입니다.(brown은 최대 5000, yellow는 최대 2000000)

작성중인 코드―solution.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# x * y = brown + yellow
# x + y = (brown + 4)//2

# x + y 에서 x, y를 정한다. 이때 x와 y의 차가 작을 수록 그 곱은 더 커진다.
# 이를 이용해서 이분 탐색으로 그 차의 크기를 조절해서 답을 구한다.

# x <= y 라고 하면, x는 1 ~ (x+y)//2 의 값을 가진다.
def solution(brown, yellow):
    m = brown + yellow
    s = (brown + 4) // 2

    # x가 가질 수 있는 최대값
    diff = (s // 2)

    # x가 가질 수 있는 최대값의 절반
    x = diff // 2
    y = s - x
    diff //= 2

    while x * y != m:
        if diff != 1:
            diff //= 2

        if x * y > m:
            x -= diff
            y += diff

        else:
            x += diff
            y -= diff

    return [y, x]
  • 성진

    감사합니다 :)

    성진―2023.08.04 14:41
  • 채이환

    👍

    채이환―2023.10.11 09:53
  • Austin

    인정! 탐색과정이 좀 더 프로그래밍답네요, 근데 log brown 임은 어떻게 계산되나요?

    Austin―2023.12.01 15:31
0 개의 답변
답변 쓰기
이 입력폼은 마크다운 문법을 지원합니다. 마크다운 가이드 를 참고하세요.