baekjoon/DP
백준 16565번 : N포커 [자바]
Meluu_
2025. 7. 1. 09:47
🧫 문제 분석
✔️ 출처
📖 문제

포함 배제 원리에 대해 배우게 되었다.
말그대로 여러 집합을 합칠때 중복을 빼는 것이다.
짝수 집합일 경우 빼주고
홀수 집합일 경우 더한다.
세 집합 A,B,CA, B, C 면:


→ 더하고 빼고 반복.
벤다이어그램으로 봤을때
2번째 짝수번째 빼기를 보면
3번 빼서 AnBnC가 없어진다
따라서 세 집합의 교집합을 더한다.
최종적으로 중복ㅇ벗는 하나의 영역만 계산된다.
|B| + |C| + |D|
이경우 BnC가 2개
AnB 2개
AnC 2개
때문에 1개씩 빼줌
하지만 이러면 AnBnC가 사라짐
AnBnC 더함
최종적으로 중복없는 합 집합 생성
🔅 문제 풀이
import java.io.*;
import java.sql.SQLOutput;
import java.util.*;
public class Main {
static final long MOD = 10_007;
// 계산은 long
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
// 4카드 이하면 이길 수 없음
if (n < 4) {
System.out.println(0);
return;
}
int[][] dp = new int[53][53];
// dp로 조합의 개수 미리 구해놓기
dp[0][0] = 1;
for (int i = 1; i < 53; i++) {
dp[i][1] = i;
dp[i][0] = dp[i][i] = 1;
for (int j = 2; j < i; j++) {
dp[i][j] = (int) ((dp[i - 1][j] + dp[i - 1][j - 1]) % MOD);
}
}
long ans = 0;
int max = n / 4; // 가능한 최대 포카드 쌍 개수
for (int i = 1; i <= max; i++) {
// i쌍의 포카드를 뽑는 경우의 수
long pickFourCard = dp[13][i]; // C(13, i)
long rest = dp[52 - 4*i][n - 4*i]; // C(52 - 4*i, N - 4*i)
long cnt = (pickFourCard * rest) % MOD;
// 뽑은 포카드의 쌍의 수가 홀수일때는 더하고, 짝수일떄는 뺀다.
if (i % 2 == 1) {
ans = (ans + cnt) % MOD;
} else {
ans = (ans - cnt + MOD) % MOD;
}
}
System.out.println(ans);
}
}
❗ 오답노트 / 필요한 지식
- 어렵다..