2004번: 조합 0의 개수

문제:

${n \choose m}$의 끝자리 0의 개수를 출력하는 프로그램을 작성하시오.

입력:

첫째 줄에 정수 n, m (0≤m≤n≤2,000,000,000, n≠0)이 들어온다.

풀이:

⚠️ 이 문제를 풀 때 주의 해야 될 점은 개수를 확인할 때 쓰는 two_multiple, five_multiple값이 long long이어야 되는 것이다. 그 이유는 2,000,000을 안넘는 n과 m은 int형인 것이 상관 없는데 two_multiple, five_multiple은 n과 m이 2,000,000과 같은 큰 수 인 경우에는 2, 5를 곱하였을 때 값이 int형이 담을 수 없는 값만큼 커지기 때문에 long long으로 설정해야 overflow가 발생하지 않는다.

아래에서 모든 자료형을 long long으로 선언한 이유는 어짜피 int값과 long long값을 연산을 하게 되면 int값이 자동으로 long long으로 변환 되기 때문에 몇개만 int형으로 선언하는게 의미가 없기 때문이다.

코드:

#include <iostream>

using namespace std;

int main(){
	long long n, m, num_two = 0, num_five = 0, two_multiple=2, five_multiple = 5;
	//입력 
	cin >> n >> m;
	//---------5의 개수--------------
	//n에 있는 5의 개수 더해주기
	while(n/five_multiple){
		num_five+=n/five_multiple;
		five_multiple*=5;
	}
	//5의 배수 초기화
	five_multiple = 5;
	//m에 있는 5의 개수 빼주기
	while(m/five_multiple){
		num_five-=m/five_multiple;
		five_multiple*=5;
	}
	//5의 배수 초기화
	five_multiple = 5;
	//n-m에 있는 5의 개수 빼주기
	while((n-m)/five_multiple){
		num_five-=(n-m)/five_multiple;
		five_multiple*=5;
	}
	//---------2의 개수--------------
	//n에 있는 5의 개수 더해주기
	while(n/two_multiple){
		num_two+=n/two_multiple;
		two_multiple*=2;
	}
	//2의 배수 초기화
	two_multiple = 2;
	//m에 있는 2의 개수 빼주기
	while(m/two_multiple){
		num_two-=m/two_multiple;
		two_multiple*=2;
	}
	//2의 배수 초기화
	two_multiple = 2;
	//n-m에 있는 2의 개수 빼주기
	while((n-m)/two_multiple){
		num_two-=(n-m)/two_multiple;
		two_multiple*=2;
	}
	//두개의 값중 최솟값 출력
	cout << min(num_two, num_five); 
}