Idealim
article thumbnail

/* 본 게시물은 참고자료를 토대로 작성되었습니다. */

/* 본 글은 개인적으로 공부한 내용을 정리한 글이므로 오류가 있을 수 있습니다. */

참고 자료

[백준] 2231번 - 분해합 : https://www.acmicpc.net/problem/2231


문제

어떤 자연수 N이 있을 때, 그 자연수 N의 분해합은 N과 N을 이루는 각 자리수의 합을 의미한다. 어떤 자연수 M의 분해합이 N인 경우, M을 N의 생성자라 한다. 예를 들어, 245의 분해합은 256(=245+2+4+5)이 된다. 따라서 245는 256의 생성자가 된다. 물론, 어떤 자연수의 경우에는 생성자가 없을 수도 있다. 반대로, 생성자가 여러 개인 자연수도 있을 수 있다.

자연수 N이 주어졌을 때, N의 가장 작은 생성자를 구해내는 프로그램을 작성하시오.

 

입력

첫째 줄에 자연수 N(1 ≤ N ≤ 1,000,000)이 주어진다.


1. MySolution (1754ms)

import kotlin.math.pow

fun main() {
    val N = readLine()!!
    val digitN = N.map{ it.toString().toInt() }
    var ans = 1000000

    fun digitToNum(tmpDigit:ArrayList<Int>, firstDigit: Int): Int{
        if (digitN.size == 1) return firstDigit
        
        val tmp = ArrayList<Int>(tmpDigit.size)
        for (i in tmpDigit.indices){
            tmp.add(tmpDigit[i] * (10.0.pow(tmpDigit.size-i-1)).toInt())
        }
        return tmp.sum() + (firstDigit * (10.0.pow(tmpDigit.size))).toInt()
    }

    fun calcM(depth: Int, tmpDigit: ArrayList<Int>, firstDigit: Int){
        if (depth == digitN.size - 1){
            val digitSum = tmpDigit.sum() + firstDigit // M의 각자리 숫자 합
            val m = digitToNum(tmpDigit, firstDigit) // M
            val n = m + digitSum
            if (n == N.toInt()) {
                if (ans > m) ans = m
            }
            return
        }
        for (i in 0..9){
            tmpDigit.add(i)
            calcM(depth + 1, tmpDigit, firstDigit)
            tmpDigit.remove(i)
        }
    }

    // digitN 의 개수 -> 자리수
    // 가장 높은 자리수
    for (i in 0..digitN[0]){
        calcM(0, ArrayList<Int>(digitN.size), i)
    }
    if (ans == 1000000) print(0) else print (ans)
}

2. BestSolution

fun sol(){
    val num = readLine()!!.toInt()
    for (i in 1..num) { // (1)
        var sum = i
        var check = i
        while (check > 0) { // 각 자리수 더함
            sum += check % 10
            check /= 10
        }
        if (sum == num) { // 생성자 찾은 경우
            println(i)
            return
        }
    }
    println(0)
}

위(1) 부분을 아래와 같이 바꿀 시 탐색 횟수를 더 줄일 수 있다. 

fun bestSol(){
    val numStr = readLine()!!
    val num = numStr.toInt()
    for (i in (num - (numStr.length * 9))..num) {
        var sum = i
        var check = i
        while (check > 0) {
            sum += check % 10
            check /= 10
        }
        if (sum == num) {
            println(i)
            return
        }
    }
    println(0)
}

*수학적 원리는 다음 을 참고하길 바란다.

반응형
profile

Idealim

@Idealim

읽어주셔서 감사합니다. 잘못된 내용이 있으면 언제든 댓글로 피드백 부탁드립니다.