문제풀이/BitMasking

[PS] BOJ1740 거듭제곱 ( 비트마스킹 ) with JAVA

IT록흐 2024. 2. 18. 09:21
반응형

 

 

 

1740번: 거듭제곱

3의 제곱수를 생각하자. 3의 0제곱, 3의 1제곱, 3의 2제곱, ... 은 순서대로 1, 3, 9, 27, ... 이 된다. 이를 바탕으로, 한 개 이상의 서로 다른 3의 제곱수의 합으로 표현되는 수를 생각할 수 있다. 예를

www.acmicpc.net

 

 

◎ 문제풀이 

 

3의 거듭제곱의 합 중 N번째로 작은 수를 구하는 문제이다. 

 

비트마스킹을 처음 풀어본 사람이라면 발상이 어려운 문제이다. 대표적인 거듭제곱의 합은 이진수 표현식이다. 십진수를 이진수로 표현하면 2의 거듭제곱의 합으로 표현할 수 있다. 

 

10101 은 2의 0승, 2의2승, 2의 4승의 합이다. 

 

여기서 2를 3으로 바꾸어주면 3의 거듭제곱의 합으로 바꿀 수 있다. 

 

1 : 1 -> 1

2 : 10 -> 3

3 : 11 -> 3+1 = 4

4 : 100 -> 9 = 9

5 : 101 -> 9+1 = 10

 

N번째로 작은 수란 N을 이진수로 변환하고 1의 자리에 해당하는 3의 거듭제곱을 합해주면 된다. 여기서 시프트 연산을 사용하면 편리하다.  '>>' 연산으로 오른쪽으로 이진수를 하나씩 줄여나가며 1이 나올때마다 3의 거듭제곱을 합해주면 된다. 

 

이진수에 1을 & 비트연산을 해주고 1이 나오는 경우에만 3의 거듭제곱을 합해준다. 

 

10101  & 00001 = 00001 : 3을 더해준다.  ( 3 )

01010 & 00001 = 00000: 0이니 넘어간다. ( 3의 1승 )

00101 & 00001 = 00001 :  9를 더해준다. ( 3의 2승 )

00010 & 00001 = 00000 : 0이니 넘어간다. ( 3의 3승 )  

00001 & 00001 = 00001 :  81을 더해준다. ( 3의 4승 )

00000 & 00001 = 00000 :  0이니 넘어간다. 

 

결과는 3 + 9 + 81 = 93 이다.

 

◎코드

import java.io.*;
import java.util.*;

public class Main{
    
    public static void main(String[] args){
        
        Scanner sc = new Scanner(System.in);
        
        long n = Long.parseLong(sc.next());
        long threeNum = 1;
        long ans = 0;
        
        while(n > 0){
            // & 연산이 1인 경우
            if( (n&1) ==1){
                ans += threeNum;
            }
            
            threeNum *= 3; // 거듭제곱하기
            n = n>>1; // 오른쪽 시프트 연산
        }
        
        System.out.println(ans);
        
        
    }
}
반응형