SueBeen Park

SueBeen Park

Developer. NewBie

© 2021

Dark Mode

SCPC 1회 예선: 균일수

문제

자연수를 표시하기 위한 표기법으로는 10을 기저로 하는 10진법을 가장 많이 사용한다. 하지만, 그 이외에도 어떤 자연수이든지 기저로 하여 표현하는 것이 가능하다. 예를 들어 10을 기저로 하는 10진법에서 238로 표현되는 수가, 2를 기저로 하는 2진법에서는 11101110으로 표현된다. 그리고, 같은 수를 23진법으로 표현하면 10, 8로 표현될 것이다. (23진법에서는 각 자리수는 10진수로 표현하고 자리수 사이를 콤마로 구분하였다. 기저가 10 이상인 경우에만 이렇게 콤마로 구분하는 방법을 쓴다.)

자연수 N 이 기저 b 에 대한 b 진법으로 표현했을 때 모든 자리수의 값이 같게 되는 경우 N 을 b 에 대해서 “균일수”라고 부른다. 예를 들어, 10진수 36은 기저 17에 대해서 2,2로 표현되므로, 10진수 36은 17에 대해서 균일수가 되고, 10진수 36은 또한 기저 8에 대해서도 균일수가 된다. 그 이유는 10진수 36의 8진수 표현이 44이기 때문이다. 자연수 N 이 하나 이상의 기저에 대해 균일수가 된다면, 그 기저들 중 가장 작은 값을 구하려고 한다. 극단적인 경우, 만약 b>N 이라면 N 은 b 진법으로 한자리 수가 되는데, 이 때도 균일수가 되는 것으로 간주한다. 자연수 N 이 주어졌을 때, N 이 b 에 대해서 균일수가 되는 최소의 양의 정수 b 를 구하는 프로그램을 작성하시오. 단, b 는 2 이상이어야 한다.

입력

입력 파일에는 여러 테스트 케이스가 포함될 수 있다. 파일의 첫 번째 줄에 테스트 케이스 개수를 나타내는 자연수 T 가 주어지고, 이후 차례로 T개의 테스트 케이스가 주어진다. ( 1≤T≤100 ) 두 번째 줄부터 주어지는 각각의 테스트 케이스는 자연수 N 으로 주어진다. ( 1≤N≤109 )

출력

각 테스트 케이스의 답을 순서대로 표준출력으로 출력하여야 하며, 각 테스트 케이스마다 첫 줄에 “Case #T”를 출력하여야 한다. 이때 T는 테스트 케이스의 번호이다. 그 다음 줄에는 N 이 b 에 대해서 균일수가 되는 최소 양수 b 를 출력한다. 단, b 는 2이상이다.

import java.util.Scanner;

class Solution {
	static int Answer;
	
	static int solve(int n) {

		int ans = n+1;
		int q,r; 	//몫과 나머지
		
		for(int i=2; i*i<n; i++) {
			r = n%i;
			q = n;
			boolean flag = true;
			
			while(q>0) {
				if(q%i != r) {
					flag = false;
					break;
				}
				q /= i;
			}
			if(flag) {
				ans = i;
				break;
			}
		}
		if(ans == n+1) {
			for (int i=1; i*i<n; i++) {
                if (n%i != 0) continue;
                int num = n/i-1;
                if (num > i) {
                    ans = num;
                }
            }
		}
		return ans;
	}

	public static void main(String args[]) throws Exception	{
		
		Scanner sc = new Scanner(System.in);

		int T = sc.nextInt();
		for(int test_case = 0; test_case < T; test_case++) {
			
			int N = sc.nextInt();
			Answer = solve(N);
			
			System.out.println("Case #"+(test_case+1));
			System.out.println(Answer);
		}
	}
}

코드 설명

시간 초과를 피하기 위해서 생각해보니 큰수는 대부분 16, 16 같이 두자리로 균일수가 만들어지는 것을 알 수 있었다.

그래서 우선 작은 범위인 N의 제곱근범위까지 for문을 돌리고 균일수가 되는 수를 발견하지 못했다면 무조건 두자리의 균일수가 나오므로 균일수가 만들어지는 num, num 이 수로 for문을 돌려서 나누어 떨어진다면 N = num * 1 + num * ans 이므로 답을 구할 수 있다.

문제출처 : codeground