Notice
Recent Posts
Link
정화 코딩
[C++] 복권 (백준 1359번) 본문
https://www.acmicpc.net/problem/1359
#include <iostream>
#include <vector>
using namespace std;
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
long long f[11];
f[0] = 1;
for (int i = 1; i < 11; i++) f[i] = f[i - 1] * i;
int n, m, k;
cin >> n >> m >> k;
cout.precision(10);
int ans = 0;
for (int i = k; i <= m; i++) {
int tmp1 = f[m] / (f[i] * f[m - i]);
int tmp2 = f[n - m] / (f[m - i] * f[n - 2 * m + i]);
ans += tmp1 * tmp2;
}
cout << (double) ans * f[m] * f[n - m] / f[n] << '\n';
}
수식은 아래와 같다.
시그마 안에 있는 식을 정리하면 아래와 같다.
그런데 아래와 같이 구현하면 WA를 받게 된다.
for (int i = k; i < m + 1; i++) {
ans += (double) (f[m] * f[n - m]) / (f[i] * f[m - i] * f[m - i] * f[n - 2 * m + i]);
}
답을 이렇게 계산하면 8 7 1 를 입력했을 때 1.022907992 가 출력되어, 확률이 1이 넘는 기이한 현상을 볼 수 있다.
이렇게 이상하게 계산되는 이유를 몰라서 한참을 헤맸는데, 생각해보니 C(n-m, m-i)에서 (n-m)이 (m-i)보다 작은 경우가 생길 수 있다. 8 7 1 이 이 경우 중 하나이다. 그래서 이 때 예외 처리를 해주어야 한다.
하지만 예외 처리를 따로 하지 않아도 해결할 수 있다.
for (int i = k; i <= m; i++) {
int tmp1 = f[m] / (f[i] * f[m - i]);
int tmp2 = f[n - m] / (f[m - i] * f[n - 2 * m + i]);
ans += tmp1 * tmp2;
}
위와 같이 구현을 하면 된다. 하나의 조합 계산의 결과는 int이므로 각각을 계산하여 int로 저장한 후, 곱해서 ans에 더해주는 방식이다. 이렇게 하게 되면 (n-m)이 (m-i)보다 작은 경우에 자동으로 tmp2가 0이 되어 따로 예외 처리를 해줄 필요가 없는 것이다. (AC)
'PS' 카테고리의 다른 글
[C++] 가장 긴 바이토닉 부분 수열 (백준 11054번) (0) | 2025.03.09 |
---|---|
[C++] GLCCDM (백준 32649번) (0) | 2025.03.08 |
[ICPC Sinchon] 25W 알고리즘 캠프 초급 강의 9회차 과제 에디토리얼 (0) | 2025.03.07 |
[ICPC Sinchon] 25W 알고리즘 캠프 초급 강의 8회차 과제 에디토리얼 (0) | 2025.03.07 |
[ICPC Sinchon] 25W 알고리즘 캠프 초급 강의 7회차 과제 에디토리얼 (0) | 2025.03.07 |
Comments