[PS] BOJ 10275 / 골드 러시

[PS] BOJ 10275 / 골드 러시
문제 링크: https://www.acmicpc.net/problem/10725
Thumbnail: Photo by Jingming Pan (Unsplash)

이진수로 생각해보면 금방 풀 수 있었는데, 직관적으로 풀이가 떠오르지 않았어서 정리해봅니다.

풀이

문제의 번역에 살짝 오역이 있어, 마법을 사용한 횟수를 출력한다고 생각하면 됩니다.

기본적으로는, $A$ 또는 $B$ 둘 중에 아무거나 기준으로 잡고 금을 쪼개가며 해당 수를 0으로 만들때까지 빼주면 됩니다.

전체 코드

input = open(0).readline
for _ in range(int(input())):
    N, A, B = map(int, input().split())
    if A % 2 == 1: # 홀수 단위로 자르려면 무조건 1까지 나눠야 한다.
        print(N)
    else:
        magic_cnt = -1
        total_gold = 1 << N # 2^N
        while A > 0:
            if A >= total_gold:
                A -= total_gold
            total_gold >>= 1
            magic_cnt += 1
        print(magic_cnt)

solution.py

이진수로 풀어보자

간단히 생각해보면, 마법의 발동마다 금의 무게를 절반으로 나누는 것은 해당 수를 이진수로 변환하는 것으로 생각할 수 있습니다.

두 수 $A$, $B$를 이진수로 변환한 뒤, 각각의 이진수 표기에서 가장 오른쪽(가장 낮은 자리)에 1이 나타나는 수를 찾아 필요한 마법의 횟수를 계산할 수 있다.

input = open(0).readline
for _ in range(int(input())):
    N, A, B = map(int, input().split())
    if A % 2 == 1: # 홀수 단위로 자르려면 무조건 1까지 나눠야 한다.
        print(N)
    else:
        a_n = 1
        b_n = 1
        a_cnt = 0
        b_cnt = 0
        # A의 이진수 표기에서 가장 낮은 1의 자리를 찾는다.
        while a_n & A == 0:
            a_cnt += 1
            a_n <<= 1
        # B의 이진수 표기에서 가장 낮은 1의 자리를 찾는다.
        while b_n & B == 0:
            b_cnt += 1
            b_n <<= 1
        # 둘 중 더 낮은 자리를 기준으로 마법을 사용한다.
        print(N - min(a_cnt, b_cnt))