본문 바로가기
👩🏻‍💻 Front-end/👾 Algorithm

백준 2231 - 분해합 (Python)

by su-no 2022. 5. 16.

문제

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

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

 

입력

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

 

출력

첫째 줄에 답을 출력한다. 생성자가 없는 경우에는 0을 출력한다.

 

코드

n = int(input())

i = 1
min = n-9*len(str(n))

for i in range(min, n+1):
    sum = i+(i//1000000 % 10)+(i//100000 % 10)+(i//10000 % 10) + \
        (i//1000 % 10)+(i//100 % 10)+(i//10 % 10)+(i % 10)
    if n == sum:
        print(i)
        break
    if n == i:
        print(0)
        break

 

풀이

1부터 수를 증가시키며 n까지 대입해보는 방법은, 시간초과로 실패!

경우의 수를 줄이기 위해 반복문의 최소값에 무엇이 들어갈지 생각해봐야 한다.

간단하게 생성자 111의 경우 분해합은 111+1+1+1이 되고, 999의 경우 999+9+9+9가 된다.

따라서 반복문의 최소값은 n-9*(자릿수)가 된다.

 

 

풀이2 - 문자열 사용

n = int(input())

result = 0
for i in range(1, n+1):
    a = list(map(int, str(i)))
    result = i+sum(a)
    if result == n:
        print(i)
        break
    if i == n:
        print(0)

다른 분들의 풀이를 참고했다.

간단하게 n을 문자열로 바꾸고, 문자열은 배열처럼 자릿수를 반환할 수 있으니..

list(map(int, str(n))를 사용하면 자릿수로 형성된 리스트를 얻을 수 있다.

예를 들어 n=198일 때 list는 ['1', '9', '8']이 된다.

이 리스트를 map 함수를 이용해 각각 int형으로 변환해주고, 동일하게 n+n의 각 자릿수 덧셈을 수행해주면 된다.

다만, 이 방법은 시간이 1.5s정도로 오래 걸렸다. 문자열을 처리하는 게 시간이 더 오래걸리는 것 같다.

위에서처럼 동일하게 반복문의 min 값을 지정해주려고 했는데, 답이 자꾸 틀렸다.

반례를 좀 더 찾아봐야겠다.