Algorithm/BOJ
백준 1094 막대기 (비트 개수 세기)
삼쓰 웅쓰
2021. 6. 3. 15:31
728x90
출처: https://www.acmicpc.net/problem/1094
분류: 비트마스킹
접근방식
주어진 문제의 조건을 맹목적으로 따라서 풀 수도 있지만,
조건을 해보면 결국은 주어진 x를 몇 개의 2의 배수를 사용해 만들 수 있느냐 하는 문제입니다.
다시 생각해보면 "x를 이진수로 만들었을 때 1이 몇 개냐" 라는 말과 같은 말이라는 걸 알 수 있습니다 :)
따라서 이진수에서 1이 몇 개인지 세는 방법을 알아보겠습니다.
2로 나누기
우선 비트 연산을 하지 않는다면 주어진 수를 x로 나눠가면서 셀 수가 있겠네요.
중학생(?)때 배우는 10진수를 2진수로 바꿀 때 나눠가면서 나머지를 세는 바로 그 방식입니다.
while x > 0 {
bitCount += x % 2
x /= 2
}
>> 1
2로 나누는 걸 비트연산으로 하려면 오른쪽으로 쉬프트 1 해주면 되겠네요
그 전에 마지막 비트가 켜져있는지 1과 &연산을 통해 확인합니다.
while x > 0 {
bitCount += x & 1
x >>= 1
}
x & (x-1 )
어떤 수와 그보다 1작은 수를 &연산 하면 마지막 비트를 꺼줄 수 있습니다.
이건 직접 해보면 금방 이해가 가실텐데요,
예를 들어,
4는 이진수로 100 이고 3은 이진수로 011이 됩니다.
4의 마지막 비트를 0으로 바꿔주고 싶네요, 1은 하나뿐이니 연산 결과가 0이 되면 되겠죠?
4와 3을 &연산하면 0이 됩니다.
10는 이진수로 1010이고 9는 1001 입니다.
10의 마지막 비트를 꺼주면 2자리 비트가 꺼지고 결과는 1000이 되어야겠네요.
10과 9를 &연산하면 결과는 1000이 됩니다 :)
while x > 0 {
x &= (x-1)
bitCount += 1
}
해결방법
var x = Int(readLine()!)!
var bitCount = 0
while x > 0 {
// 맨 마지막 비트가 꺼짐
x &= (x-1)
bitCount += 1
}
print(bitCount)
배운점
비트 연산으로 참 많은 걸 할 수 있다.
신비로운 세계 :(