코딩테스트/자바 문제풀이

[수학] 백준 21275 폰 호석만

승요나라 2024. 8. 16. 21:03

21275번: 폰 호석만

https://www.acmicpc.net/problem/21275

 

# 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    static String xA, xB, x, max; // xA와 xB는 입력받은 문자열, x는 결과 값, max는 최대 값
    static long a, b; // a와 b는 진법을 나타냄
    static int count; // 가능한 해의 개수
    static int[] arr; // 각 문자의 값(0~9, a~z)을 저장하는 배열

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] s = br.readLine().split(" ");
        xA = s[0]; // 첫 번째 수
        xB = s[1]; // 두 번째 수

        // x의 최대 값은 2^63 (long 타입이 저장할 수 있는 범위 내의 값)
        max = String.valueOf(Math.pow(2, 63));

        // arr 배열에 1~36진법에 해당하는 숫자 저장
        arr = new int[200]; // 아스키코드에 맞춰 배열 크기 설정
        for (int i = 0; i < 9; i++) {
            // '1'~'9' 문자를 숫자 1~9로 저장
            // arr[49~57] == 1~9
            arr[i + '1'] = i + 1;
        }
        for (int i = 0; i < 26; i++) {
            // 'a'~'z' 문자를 숫자 10~35로 저장
            // arr[97~122] == a~z == 10~35
            arr['a' + i] = i + 10;
        }

        solve();

        if (count == 0) {
            System.out.println("Impossible"); // 불가능한 경우
        } else if (count == 1) {
            String toInteger = x.substring(0, x.length() - 2); // 결과에서 소수점 제거
            System.out.println(toInteger + " " + a + " " + b); // 결과와 진법 출력
        } else {
            System.out.println("Multiple"); // 가능한 경우가 여러 개인 경우
        }
    }

    public static void solve() {
        // i(=xA), j(=xB) 를 1~36 진법으로 순차적으로 체크
        for (int i = 1; i <= 36; i++) {
            for (int j = 1; j <= 36; j++) {
                // A ≠ B 이므로 i와 j가 같으면 연산 패스
                if (i == j) {
                    continue;
                }

                // 두 진법에서 유효한 값인지 체크하고 값이 같은지 확인
                if (check(i, xA) && check(j, xB)) {
                    if (find(i, xA).equals(find(j, xB))) {
                        // 결과 값이 최대 값(2^63)을 넘으면 패스
                        if (find(i, xA).compareTo(max) >= 1) {
                            continue;
                        }

                        // 가능한 경우의 수를 증가시키고 결과 저장
                        count++;
                        x = find(i, xA);
                        a = i;
                        b = j;
                    }
                }
            }
        }
    }

    // 주어진 진법에서 문자열을 숫자로 변환
    public static String find(int a, String s) {
        int temp = 0;
        double result = 0;

        // 문자열을 뒤에서부터 한 자리씩 계산
        for (int i = s.length()-1; i >= 0; i--) {
            int t = arr[s.charAt(i)]; // 각 문자의 값을 가져옴
            result += Math.pow(a, temp) * t; // 해당 진법에 맞게 계산
            temp++;
        }

        // 결과를 문자열로 반환
        return String.valueOf(result);
    }

    // 주어진 진법에서 사용할 수 있는 문자인지 체크
    public static boolean check(int a, String s) {
        // 문자열의 각 문자가 해당 진법에서 유효한지 확인
        for (int i = 0; i < s.length(); i++) {
            // 만약 진법보다 큰 문자가 있으면 false 반환
            if(a <= arr[s.charAt(i)]) {
                return false;
            }
        }
        return true;
    }
}
  • 자잘하게 챙겨야 하는 것이 많은 문제였다.
  • 주의할 것은 체크하고 있는 진법보다 입력 받은 값이 크다면 모두 패스하고 find()를 실행하지 않아야 한다.

 

풀이는 아래 블로그를 참고했다.

 

백준 21275 [자바] java 폰 허석만

문제 링크: https://www.acmicpc.net/problem/21275 21275번: 폰 호석만 만약 문제의 조건에 맞는 X, A, B가 유일하게 존재한다면, X를 십진법으로 표현한 수와 A와 B를 공백으로 나누어 출력하라. 만약 만족하는

dingdingmin-back-end-developer.tistory.com