-
[백준] 2004번: 조합 0의 개수코딩(Coding)/백준 문제풀이 2021. 1. 11. 10:56728x90
링크: www.acmicpc.net/problem/2004
2004번: 조합 0의 개수
첫째 줄에 정수 $n$, $m$ ($0 \le m \le n \le 2,000,000,000$, $n \ne 0$)이 들어온다.
www.acmicpc.net
조합 0의 개수
문제
nCm의 끝자리 0의 개수를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 정수 n, m (0≤m≤n≤2,000,000,000, n≠0)이 들어온다.
출력
첫째 줄에 nCm의 끝자리 0의 개수를 출력한다.
문제접근
이번 문제는 수학문제이면서 약간의 논리가 필요한거 같다. 우선 조합 nCr의 일반식을 입력해보면
nCr = n!/((n-r)! * r!)이다.
처음에 나는 위 공식을 이용해서 값을 구한다음 뒤에서 부터 0의 개수를 세는 방식으로 문제를 접근했다.
그러나 역시 다른 뜻이 있었다는 걸 보여주듯이 시간 초과가 나타났다.
더보기import sys def facto(n): if n == 0 or n == 1: return 1 else: result = 1 for i in range(1,n+1): result *= i return result def comb(n, m): return int(facto(n)/(facto(n-m) * facto(m))) def calc(n, m): data = comb(n,m) data = reversed(str(data)) count = 0 for i in data: if(i == '0'): count += 1 else: break; return count def main(): n, m = sys.stdin.readline().split() n = int(n); m = int(m) print(calc(n,m)) if __name__ == "__main__": main()
숫자가 20억까지면 int형의 거의 끝 숫자까지 사용한다는 것인데, 당연히 시간초과가 날 것을 간과했다... ㅍ_ㅍ;;;
따라서 단순히 공식으로 풀어내는 것이 아니라 다른 방법을 통해 문제를 푸는 것인데, 자연수에서 "1000"은 10이 3번 곱해진 것이다. 또 "4300"은 43에 10이 2번 곱해진 것이다. 따라서 입력으로 주어진 수(nCm)의 10의 개수를 세면 뒤에 존재하는 0의 개수를 얻을 수 있다.
그러나 nCm은 수가 커지면 시간초과가 나온다. 따라서 nCm의 공식에서 분자와 분모를 나누어서 10의개수를 세고 분자의 10의 개수에서 분모의 10개수를 빼면(뺀다고 표현했지만 사실 약분을 하는 것이다.) nCm의 10의 개수를 얻을 수 있다.
여기서 10은 2와 5로 나뉜다. 따라서 입력으로 주어진 수의 분자와 분모 2와 5의 개수를 세어서 빼준 후(약분), 2와 5 개수의 최소값을 통해 0의 개수를 얻을 수 있다는 결론이 나온다.
코드
""" 백준 알고리즘 2004번: 조합 0의 개수 https://www.acmicpc.net/problem/2004 nCr = n!/((n-r)! * r!) 아 시간초과... 0의 개수는 10이 생겨날때마다 늘어난다. 10 = 2 * 5로만들어짐 따라서 분자 n의 5의 개수에서 m, n-m의 5의 개수를 빼고(약분 하는 거임) 분자 n의 2의 개수에서 m, n-m의 2의 개수를 뺀다(약분) 2는 100개 있는데 5가 1개있으면 10은 1개 만들어 지므로 둘중에 제일 작은 수를 구하면 그게 답 """ import sys def count2(n): count = 0 while n != 0: n = n//2 count += n return count def count5(n): count = 0 while n != 0: n = n//5 count += n return count def calc(n, m): cnt2 = count2(n) - (count2(m) + count2(n - m)) cnt5 = count5(n) - (count5(m) + count5(n-m)) return min(cnt2, cnt5) def main(): n, m = sys.stdin.readline().split() n = int(n); m = int(m) print(calc(n,m)) if __name__ == "__main__": main()
728x90'코딩(Coding) > 백준 문제풀이' 카테고리의 다른 글
[백준] 10870번: 피보나치 수 5 (0) 2021.01.12 [백준] 1912번: 연속합 (0) 2021.01.12 [백준] 11053번: 가장 긴 증가하는 부분 수열 (0) 2021.01.08 [백준] 1297번: TV 크기 (0) 2021.01.06 [백준] 2417번: 정수 제곱근 (0) 2021.01.05