[BaekJoon] 2004번 - 조합 0의 개수 [Java][C++]
[BaekJoon] 2004번 - 조합 0의 개수 [Java][C++]
1. 문제 풀이
주어진 이항계수에서 끝자리 0의 개수를 세는 문제로 조합을 팩토리얼로 바꾸어 찾으면 해결할 수 있다.
이항계수는 아래와 같이 팩토리얼간 나눗셈으로 바꿀 수 있다.
끝자리에 0이 있다는 것은 위 식에서 분자와 분모에 소인수로 있는 2와 5의 개수를 각각 세주면 알 수 있다. 팩토리얼은 1부터 해당 수까지 전부 곱한 수이므로 $x!$ 에서 소인수로 존재하는 2의 개수는 $x$ 보다 작거나 같은 2의 배수들은 1개, 4의 배수들은 2개, 8의 배수들은 3개, 이런식으로 가지고 있다. 5 역시 마찬가지이며 몫과 나머지 연산을 통해서 2의 개수와 5의 개수를 전부 세줄 수 있다. 분자의 2의 개수와 5의 개수에서 분모의 2의 개수와 5의 개수를 빼줬을 때, 둘의 최솟값으로 10을 만들 수 있고 이것이 끝자리 0의 개수가 된다.
2. 코드
1. 풀이 [Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
int cnt2 = find(n, 2) - find(m, 2) - find(n - m, 2);
int cnt5 = find(n, 5) - find(m, 5) - find(n - m, 5);
System.out.println(Math.min(cnt2, cnt5));
}
static int find(int x, int div) {
int cnt = 0;
long tmp = div;
while (x >= tmp) {
cnt += (int) (x / tmp);
tmp *= div;
}
return cnt;
}
}
2. 풀이 [C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <bits/stdc++.h>
using namespace std;
long long find(int x, int div) {
long long cnt = 0;
long long tmp = div;
while (x >= tmp) {
cnt += x / tmp;
tmp *= div;
}
return cnt;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n, m;
cin >> n >> m;
int cnt2 = find(n, 2) - find(m, 2) - find(n - m, 2);
int cnt5 = find(n, 5) - find(m, 5) - find(n - m, 5);
cout << min(cnt2, cnt5);
}
This post is licensed under CC BY 4.0 by the author.