알고리즘의 킹갓제너럴엠퍼러마제스티충무공알고리즘마스터 현우가 교수로 취임하였다!
그러나 학생들에게 크나큰 기대를 품고 첫 수업에 들어갔던 현우는 아무도 외판원 순회 문제(Traveling Salesman Problem, TSP)를 풀지 못하는 것을 보고 낙심하였다.
그 와중에 학생 남규는 TSP를 완전탐색으로 풀려고 하였고, 현우는 그걸 보고 경악을 금치 못한다. 왜냐면 TSP를 완전탐색으로 풀려면 O(N!)의 시간이 소모되는데, 이는 경악을 금치 못할 시간이기 때문이다.
그러나 남규는 O(N!)이 왜 큰지도 잘 모른다. 그래서 현우는 더더욱 경악을 금치 못하고, N!이 얼마나 큰지 대략적으로나마 알려주기 위해, 자연수 N이 주어지면 N!의 오른쪽 끝에 있는 0의 개수를 알려주기로 하였다.
그러나 현우는 경악을 금치 못하여 지금 코딩을 할 수 없는 상황이다. 여러분이 현우를 대신하여 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어지고, 이어서 T개의 줄에 정수 N이 주어진다(1 <= N <= 1000000000).
출력
각 줄마다 N!의 오른쪽 끝에 있는 0의 개수를 출력한다.
예제 입력 1 복사
6
3
60
100
1024
23456
8735373
예제 출력 1 복사
0
14
24
253
5861
2183837
복습
이 문제에서는 팩토리얼을 했을 때 나오는 0의 갯수를 구하라고 나와있다.
그러니까 5!을 하면 120이 나오니까 0이 한 개 인 것이다.
당연히 처음에는 모르니까 하나씩 적어보는게 편하다.
6! 은 720, 7! 은 5040(오른쪽 0갯수만 셈) 8!은 40320....
자세히 살펴보면 2와 5의 제곱의 짝의 갯수에 의해서 0의 갯수가 정해지는 것을 알 수 있다.
그럼 당연히 소인수 분해를 하면 2의 갯수는 5의 갯수보다 많기 때문에,
결국 5의 제곱의 갯수만 구하면 되는 쉬운 형태로 결론이 난다.
팩토리얼의 0의 개수는 5가 곱해진 개수로 구할 수 있다.
그래서 n에 5를 나눈 몫을 더해준다.
여기에서 n에 5의 제곱수들로 나눈 몫도 더해주어야 한다.
0의 개수를 구하려면 숫자에 10이 곱해진 횟수를 구해줘야한다.
예 ) 100 = 10**2
10을 소인수 분해 하면 2*5이다.
즉, 숫자를 소인수 분해하여 (2*5) 가 몇개 있는지 구하면된다.
5가 2보다 크기 때문에 5가 몇개 들어있는지 구하면된다.
풀이
수의 범위가 (1 <= N <= 십억) 이므로 팩토리얼을 직접 구할 수는 없다.
끝에 0이 몇 개인지 구하는 것은 인수로 10을 몇 개 포함하고 있는지 구하는 것과 같다.
예를 들어 900은 9 x 10 x 10 이므로 끝에 0이 2개이다.
하지만 팩토리얼을 직접 구할 수는 없기 때문에 소인수분해를 이용해야 한다.
10은 5와 2를 인수로 가진다. 따라서 N! 을 구하려면 몇개의 (5 x 2)가 들어있는지 구하면 된다.
정리하면 다음과 같다.
- 어떤 수의 끝에 0이 있다는 건 10 x N 과 같다.
- 10을 만들 수 있는 수는 5와 2뿐이다.
예를 들어 50! 의 끝에 0이 몇개인지 구하려고 한다.
방법은 두가지다
- 50! 에서 2의 배수의 개수를 구하거나
- 5의 배수의 개수를 구하거나
둘 중에 5가 더 크므로 5를 사용하는 것이 더 편리하다.
위에서 5의 배수를 정리하면 다음과 같다.
(5x1), (5x2), (5x3), (5x4), (5x5)
(5x6), (5x7), (5x8), (5x9), (5x10)
마지막의 (5x10) 은 (5x5x2) 와 같다.
위에서 알 수 있는 것은 다음과 같다.
50! 을 소인수분해하면 5로 12번 나눌 수 있다.
따라서 뒤에 0이 12개 붙는다.
위의 계산을 편하게 하려면 5의 배수를 구하고 5x5의 배수를 구하고 5x5x5 ... 를 구하고 그 총합을 합치면 된다. 아래는 그것을 구현한 코드이다.
import sys
sys.stdin = open("2_4_20220811_백준_3474_교수가된현우.txt", "r")
T = int(sys.stdin.readline())
for i in range(T) :
num = int(sys.stdin.readline())
count = 0
i = 5
# 5가 몇개가 들어가는지 구해준다.
while i <= num :
count += num // i #5의 배수의 합을 구한다.
i *= 5
print(count)
#0의 개수를 구하려면 숫자에 10이 곱해진 횟수를 구해줘야한다.
#예 ) 100 = 10**2
# 10을 소인수 분해 하면 2*5이다.
# 즉, 숫자를 소인수 분해하여 (2*5) 가 몇개 있는지 구하면된다.
# 5가 2보다 크기 때문에 5가 몇개 들어있는지 구하면된다.
# def factorial(n) :
# if n == 1 :
# return 1
# return n * factorial(n-1)
# n = int(input())
# for i in range(n) :
# num = int(input())
# facNum = str(factorial(num))
# zeroCount = 0
# for i in range(len(facNum)-1, 0, -1) :
# if facNum[i] == '0' :
# zeroCount += 1
# else :
# break
# print(zeroCount)
#자연수 N이 주어지면 N!의 오른쪽 끝에 있는 0의 개수
#N!를 구해라
'코테풀이 > 구현' 카테고리의 다른 글
[백준 | 실버2 | 파이썬] 지구온난화(구현, 맵, 4방향) (0) | 2022.08.22 |
---|---|
[백준 | 실버2] 19583 : 싸이버개강총회(구현) (0) | 2022.08.17 |
[백준 | 실버5] 4659번 : 비밀번호 발음하기(구현, 시뮬레이션) (0) | 2022.08.10 |
[백준 | 실버5] 10709번 : 기상캐스터(구현, 시뮬레이션) (0) | 2022.08.10 |
[백준 | 실버5] 2828 : 사과 담기 게임(매우 복습 필요) (0) | 2022.08.10 |