반응형
문제 출처 : https://www.acmicpc.net/problem/2407
문제
nCm을 출력한다.
입력
n과 m이 주어진다. (5 ≤ n ≤ 100, 5 ≤ m ≤ 100, m ≤ n)
출력
nCm을 출력한다.
알고리즘 분류
풀이
파스칼 삼각형 : https://ko.wikipedia.org/wiki/%ED%8C%8C%EC%8A%A4%EC%B9%BC%EC%9D%98_%EC%82%BC%EA%B0%81%ED%98%95
조합+dp+문자열 문제이다.
우선 nCr은 n!/r!*(n-r)!로 구할 수 있지만, 문제에선 입력값이 n 100 r 100이므로 long long 범위를 초과한다.
이러한 경우 보통 string을 이용하는데 이 문제에서도 그렇다.
우선,
0C0= 1
1C0= 1, 1C0 = 1
2C0 = 1, 2C1 = 2, 2C2 = 1
3C0 = 1, 3C1 = 3, 3C2 = 3, 3C3 =1
4C0 = 1, 4C1 = 4, 4C2 = 6, 4C3 = 4, 4C4 =1
이다.
위의 결과를 보면 파스칼의 삼각형과 결과가 같다는 것을 알 수 있다.
파스칼 삼각형의 알고리즘의 점화식은
dp[n][r] = dp[n-1][r-1] + dp[n-1][r] 이고,
n과 r이 같거나, r이 0이라면 모두 1이다.
이렇게 0,0부터 n,r까지 조합의 수를 파스칼의 삼각형으로 구할 수 있는데, 이 숫자는 long long의 범위를 초과하므로, 문자열로 덧셈을 해주어야 한다.
문자열 덧셈은 두 문자열의 길이를 맞춰주고 구현하는 것이 편하다.
코드
#include <iostream>
#include <string>
using namespace std;
int n, m;
string combi[101][101];
string addNum(string a, string b) {
string result="";
if (a.length() > b.length()) {
while (a.length() != b.length()) {
b = '0' + b;
}
}
else {
while (a.length() != b.length()) {
a = '0' + a;
}
}
int sum = 0;
for (int i = a.length()-1; i >=0; i--) {
sum += a[i] - '0';
sum += b[i] - '0';
result = to_string(sum % 10) + result;
if (sum >= 10) {
sum = 1;
}
else {
sum = 0;
}
}
if (sum == 1) {
return '1' + result;
}
return result;
}
void makeCombi() {
combi[0][0] = "1";
combi[1][0] = combi[1][1] = "1";
for (int i = 2; i <= n; i++) {
for (int j = 0; j <= m; j++) {
if (i == j || j==0) {
combi[i][j] = "1";
}
else {
combi[i][j] = addNum(combi[i - 1][j - 1], combi[i - 1][j]);
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
makeCombi();
cout << combi[n][m];
return 0;
}
반응형
'알고리즘 문제 풀이 > 백준' 카테고리의 다른 글
백준 2167 2차원 배열의 합 c++ (누적 합) (0) | 2021.10.04 |
---|---|
백준 16947 서울 지하철 2호선 c++ (dfs/bfs) (2) | 2021.10.04 |
백준 9046 복호화 c++ (문자열) (0) | 2021.10.02 |
백준 11057 오르막 수 c++ (dp) (0) | 2021.10.02 |
백준 2615 오목 c++ (완전탐색) (0) | 2021.10.01 |
댓글