May 23 2008
자기복제수 문제
프로그래밍 갤러리에서 다시 자기복제수 떡밥이 돌길래 덥썩 물고 구현해 봤다.
(참고로 자기복제수란, N을 제곱했을 때 맨 뒷자리에 N이 다시 나타나는 수를 말한다. 예를 들어, 76은 자기복제수이다. 76 * 76 = 57′76′ 이기 때문이다.)
프갤의 떡밥은 자기복제수를 계속 찾아나가면서 몇이 나왔을 때 사양이 어떻게 되고 몇 ms 가 걸렸는지인데, 난 그냥 회사에서 잠깐 짬 내서 하는 것이니까 구글링하다 찾은 문제의 스펙대로만 풀었다. 그래서 큰 수의 처리도 없고(N의 제곱이 INT_MAX보다 작아야 함) 처리 속도도 크게 신경 안썼다. 감으로 바로 떠오른 알고리즘을 통해 풀어 보았다.
package practice; import java.util.Scanner; /** * '자기복제수' 체크<br /> * <br /> * 자기복제수 : 어떤 자연수 N 을 제곱했을 때, 그 제곱수의 맨 뒷자리에 원래의 수 N이 다시 나타나는 경우<br /> * 그 수 N을 자기복제수라고 한다.<br /> * <br /> * 입력<br /> * 입력은 표준입력(standard input)을 통해 받아들인다. <br /> * 입력의 첫 줄에는 테스트 케이스의 개수 T (1 ≤ T ≤ 20)가 주어진다. <br /> * 각 테스트 케이스는 한 줄로 이루어져 있으며 자연수 N (1 ≤ N ≤ 1000) 이 주어진다.<br /> * <br /> * 출력<br /> * 출력은 표준출력(standard output)을 통하여 출력한다. <br /> * 각 테스트 케이스에 대해, 주어진 자연수가 자기복제수이면 YES를 아니면 NO를 출력한다.<br /> */ public class PracticeSelfCloning { public static final int MAX_INPUT_NUM = 1000; public static final int MIN_INPUT_NUM = 1; public static final int MAX_INPUT_COUNT = 20; public static final int MIN_INPUT_COUNT = 1; private int inputCount = 0; private int[] inputDataList = null; public PracticeSelfCloning() { inputCount = 0; inputDataList = null; } public boolean inputData( ) { Scanner scan = new Scanner(System.in); inputCount = scan.nextInt(); if( inputCount > MAX_INPUT_NUM || inputCount < MIN_INPUT_COUNT ) { System.err.println("테스트 케이스의 갯수가 " + MIN_INPUT_COUNT + "<=T<=" + MAX_INPUT_COUNT + " 을 만족하지 않습니다."); return false; } inputDataList = new int[inputCount]; for( int i = 0 ; i < inputCount ; i++ ) { inputDataList[i] = scan.nextInt(); if( inputDataList[i] > MAX_INPUT_NUM || inputDataList[i] < MIN_INPUT_NUM ) { System.err.println("테스트 케이스가 " + MIN_INPUT_NUM + "<=N<=" + MAX_INPUT_NUM + " 을 만족하지 않습니다."); return false; } } scan.close(); return true; } public void printCheckSelfCloning() { for ( int i = 0 ; i < inputCount ; i++ ) { if( checkSelfCloning( inputDataList[i] ) ) System.out.println("YES"); else System.out.println("NO"); } } private boolean checkSelfCloning(int value) { int squareVal = value * value; int valueOri = value; /* * 알고리즘 : 원래의 수를 N이라 하고 N의 자릿수를 c라 하면, * N^2를 10^c로 나눈 나머지가 N이 되어야 자기복제 수이다. */ int modVal = 10; int valueCipher = 1; while( value / 10 > 0 ) { valueCipher++; value = value / 10; modVal = modVal * 10; } int mod = squareVal % modVal; if( mod == valueOri ) return true; return false; } public static void main(String[] args) { // TODO Auto-generated method stub if( !checkCondition() ) return; PracticeSelfCloning selfCloning = new PracticeSelfCloning(); selfCloning.inputData(); selfCloning.printCheckSelfCloning(); } public static boolean checkCondition() { // MAX_INPUT_NUM * MAX_INPUT_NUM 이 int 의 한계를 넘어설 경우를 체크 if( Integer.MAX_VALUE / MAX_INPUT_NUM < MAX_INPUT_NUM ) { System.err.println("MAX_INPUT_NUM 의 값을 낮추거나 BigInteger를 사용해야 합니다."); return false; } // MAX_INPUT_COUNT 는 체크할 필요 없음 -> 컴파일 시에 오버플로우 체크 return true; } } |
아마도 많은 최적화 방법이 있지 않을까 생각한다.
