https://www.acmicpc.net/problem/2057
2057번: 팩토리얼 분해
음 아닌 정수 N이 주어졌을 때, 이 수를 서로 다른 정수 M(M ≥ 1)개의 팩토리얼의 합으로 나타낼 수 있는지 알아내는 프로그램을 작성하시오. 예를 들어 2=0!+1!로 나타낼 수 있지만, 5는 이와 같은
www.acmicpc.net
22/09/15
같은 그룹원에게 추천받아서 풀었던 그리디 문제인데, (그리디인 줄 모르고 풀었었다) 접근방법을 틀리게 할 때가 많았던 문제이다.
역시 그리디는 그리디인줄 모르고 풀어야 그 진정한 어려움을 알 수 있다고 했던가, 정말 힘들었다.
이후에 브루트 포스로 풀 수 있다는 것을 깨닫고, 조금 허탈함을 느끼긴 했다.
문제 접근 방식:
맨 처음에 접근 할 때 잘 모르겠어서 그룹원의 힌트를 보고 접근했다.
그 그룹원 분은 1!부터 n! 까지의 합이 n+1! 보다 작다는 점을 힌트로 주었다.
힌트를 얻고 문제 접근 방식을 다음과 같이 하였다.
N에서 0!, 1!, 2!... 을 차근차근 빼다가 음수가 나오면 실패, 0이 나오면 성공이겠구나,라고 생각을 잘못했었다.
아래는 내가 위의 접근 방식과 같이 작성한 잘못된 파이썬 코드이다. 더보기를 누르면 확인할 수 있다.
# 2057번 팩토리얼 분해
# 수학, 그리디
'''
접근 방법:
앞에 있는 팩토리얼들을 모두 더해도 그 다음 팩토리얼 숫자가 나오지 않기 때문에
그냥 N에서 0!, 1!, ... 차근차근 빼다가 음수가 나오면 실패,
0이 나오면 성공
'''
from math import factorial
N = int(input())
k = 0
while True:
if N == 0:
print('YES')
break
elif N < 0:
print('NO')
break
N -= factorial(k)
k += 1
근데 알고보니, 1! + 2! + 8! 과 같은 반례들이 있다는 것을 보고 이 접근 방식은 틀렸다는 사실을 알게 되었다.
이 반례를 통해 그렇다면, N이 주어질때, N보다 작거나 같은 최대의 k! 을 빼도록 하자,라고 생각했다.
결론만 이야기 하자면, 접근 방법 자체는 맞았으나, 한 가지 빼먹고 구현한 것이 있어서 틀렸습니다를 많이 받았다.
바로 0!과 1! 의 유무, 그리고 k! 을 이미 사용했더라면, 체크를 해줌으로써 다시 못 빼도록 하는 것이었다.
0! 과 1! 은 두 개가 같기 때문에 N보다 작거나 같은 최대의 k! 을 뺄 때 자칫 잘못하면 여러 번 빼거나 한 번만 빼도록 코드가 구현될 수 있다.
이런 부분들 때문에 많이 틀렸고, 결국 최종적으로 맞은 코드는 다음과 같다.
아래는 내가 위의 접근 방식과 같이 작성한 파이썬 코드이다. 더보기를 누르면 확인할 수 있다.
# 2057번 팩토리얼 분해
# 수학, 그리디
'''
접근 방법:
앞에 있는 팩토리얼들을 모두 더해도 그 다음 팩토리얼 숫자가 나오지 않기 때문에
그냥 N에서 N이랑 가까운 팩토리얼을 차근차근 빼다가 음수가 나오면 실패,
0이 나오면 성공
'''
from math import factorial
N = int(input())
check = [0 for _ in range(21)]
check[20] = 1
k = 19
fac = factorial(19)
if N != 0:
while True:
while True:
k = check.index(1) - 1
fac = factorial(k)
check[k] = 1
if N >= fac:
break
N -= fac
if check[0] == 1 or N == 0:
break
if N == 0:
print('YES')
else:
print('NO')
else:
print('NO')
'알고리즘 > 백준 문제 풀이' 카테고리의 다른 글
[Python] 18155번 Issuing Plates (0) | 2022.09.29 |
---|---|
[Python] 1308번 D-Day (0) | 2022.09.29 |
[Python] 4948번 베르트랑 공준 (0) | 2022.09.29 |
[Python] 5637번 가장 긴 단어 (0) | 2022.09.28 |
[Python] 16113번 시그널 (0) | 2022.09.28 |