[백준] 2164번 카드 2 - Python

윤민우·2023년 2월 17일

알고리즘 - 백준

목록 보기
4/4

문제

N장의 카드가 있다. 각각의 카드는 차례로 1부터 N까지의 번호가 붙어 있으며, 1번 카드가 제일 위에, N번 카드가 제일 아래인 상태로 순서대로 카드가 놓여 있다.

이제 다음과 같은 동작을 카드가 한 장 남을 때까지 반복하게 된다. 우선, 제일 위에 있는 카드를 바닥에 버린다. 그 다음, 제일 위에 있는 카드를 제일 아래에 있는 카드 밑으로 옮긴다.

예를 들어 N=4인 경우를 생각해 보자. 카드는 제일 위에서부터 1234 의 순서로 놓여있다. 1을 버리면 234가 남는다. 여기서 2를 제일 아래로 옮기면 342가 된다. 3을 버리면 42가 되고, 4를 밑으로 옮기면 24가 된다. 마지막으로 2를 버리고 나면, 남는 카드는 4가 된다.

N이 주어졌을 때, 제일 마지막에 남게 되는 카드를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 정수 N(1 ≤ N ≤ 500,000)이 주어진다.

출력

첫째 줄에 남게 되는 카드의 번호를 출력한다.

예제 입력 1

6

예제 출력 1

4

답안지

오답 1 (시간 초과)

문제에서 진행되는 방식을 그대로 따라한 방법으로 시간 초과가 뜨면서 만들어진 오답이다.
Queue를 생각하면서 만든 코드로, 처음에 1~TestCase에 해당하는 숫자를 queue에 모두 넣고, 그 다음에 마지막 1개가 남을 때까지, 1개를 없애고 처음걸 꺼내서 뒤에 넣고 반복을 돌리는 구조라고 보면된다.

TestCase = int(input())
queue = [i for i in range(1, TestCase + 1)]

while len(queue) != 1:
    queue.pop(0)
    if len(queue) == 1:
        continue
    queue.append(queue.pop(0))
else:
    print(queue[0])

아이디어

위에서 시간 초과가 뜨는 것을 확인하고 그렇다면 규칙을 찾아야겠다는 생각에 위의 코드를 변형시켜 1 ~ 50까지 돌려본 결과 규칙을 찾을 수 있었다.

1 -> 1 | 3 -> 2 | 5 -> 2 | 9 -> 2
2 -> 2 | 4 -> 4 | 6 -> 4 | 10 -> 4
                | 7 -> 6 | 11 -> 6
                | 8 -> 8 | 12 -> 8
                         | 13 -> 10
                         | 14 -> 12
                         | 15 -> 14
                         | 16 -> 16

위와 같이 2의 제곱수 마다 2씩 증가하는 규칙을 찾을 수 있다. 그렇다면 TestCase의 숫자보다 작은 2의 제곱수를 구할 수 있는 방법을 찾아야 하는데, 거기에도 여러가지 방법이 있다.

정답 1

2의 제곱수를 1에서부터 차근차근 구하는 방법

case = int(input())
PowerOfTwo = 1
while case >= PowerOfTwo * 2:
    PowerOfTwo *= 2
    # print(PowerOfTwo)
answer = (case - PowerOfTwo) * 2
if answer == 0:
    print(PowerOfTwo)
else:
    print(answer)

정답 2

log를 사용하여 구하는 방법

import math

case = int(input())
PowerOfTwo = 2**int(math.log(case, 2))
answer = (case - PowerOfTwo) * 2
if answer == 0:
    print(PowerOfTwo)
else:
    print(answer)

정답 3

bitwise 기법을 사용하는 방법

bitwise operation을 비트 연산이라고 한다 ^^
python에서는 <<를 통해서 왼쪽으로 비트를 한 칸씩 옮기고, >>를 통해서 오른쪽으로 비트를 옮기는 등의 bitwise operation이 있다!

case = int(input())
PowerOfTwo = 1
while case >= PowerOfTwo << 1:
    PowerOfTwo <<= 2
answer = (case - PowerOfTwo) * 2
if answer == 0:
    print(PowerOfTwo)
else:
    print(answer)

0개의 댓글