๋ฐ˜์‘ํ˜•
Notice
Recent Posts
Recent Comments
Link
ยซ   2025/04   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
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 29 30
Archives
Today
Total
04-03 16:54
๊ด€๋ฆฌ ๋ฉ”๋‰ด

ImJay

[BOJ/Java] 12422. ์ฐฝ๋ฌธ ๊นจ๊ธฐ (Large) ๋ณธ๋ฌธ

์•Œ๊ณ ๋ฆฌ์ฆ˜/BOJ - Java

[BOJ/Java] 12422. ์ฐฝ๋ฌธ ๊นจ๊ธฐ (Large)

ImJay 2025. 3. 14. 15:42
๋ฐ˜์‘ํ˜•

๐Ÿ“Œ [BOJ/Java] 12422. ์ฐฝ๋ฌธ ๊นจ๊ธฐ (Large)

๐Ÿ”— ๋ฌธ์ œ ๋งํฌ


๐Ÿ“– ๋ฌธ์ œ ํ•ด์„

๋ณธ ๋ฌธ์ œ๋Š” K๊ฐœ์˜ ์ฐฝ๋ฌธ์œผ๋กœ ๋‘˜๋Ÿฌ์‹ธ์ธ ๋ฐฉ์—์„œ ์ง„ํ–‰๋˜๋Š” ์ƒํ™ฉ์„ ๋ชจ๋ธ๋งํ•œ๋‹ค. ์ฐฝ๋ฌธ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋Œ ํ•œ ๊ฐœ์— ๊นจ์ง€๋‚˜, H๊ฐœ์˜ ์ฐฝ๋ฌธ์€ ๊ฐ•ํ™”๋˜์–ด ์žˆ์–ด ์ฒซ ๋ฒˆ์งธ ๋Œ์€ ๊ฒฌ๋””๊ณ  ๋‘ ๋ฒˆ์งธ ๋Œ์— ๊นจ์ง„๋‹ค. ๋ชจ์ž„ ์ „์— M๋ช…์˜ ์ผ๊พผ์ด ๊ฐ๊ฐ ๋ฌด์ž‘์œ„๋กœ ํ•œ ์ฐฝ๋ฌธ์„ ์„ ํƒํ•˜์—ฌ ์ถ”๊ฐ€ ๊ฐ•ํ™” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ฉฐ, ํ•œ ๋ฒˆ ๊ฐ•ํ™”ํ•  ๋•Œ๋งˆ๋‹ค ํ•ด๋‹น ์ฐฝ๋ฌธ์€ ๋Œ์„ ํ•œ ๋ฒˆ ๋” ๋ฒ„ํ‹ธ ์ˆ˜ ์žˆ๋‹ค. ๋ชจ์ž„ ๋‹น์ผ์—๋Š” N๋ช…์˜ ์•…๋‹น์ด ๊ฐ์ž ํ•œ ๊ฐœ์˜ ์ฐฝ๋ฌธ์„ ์„ ํƒํ•˜์—ฌ ๋Œ์„ ๋˜์ง€๋ฉฐ, ์ด๋ฏธ ๊นจ์ง„ ์ฐฝ๋ฌธ์— ๋Œ์ด ๋˜์ ธ์ง€๋ฉด ๋Œ์€ ๊ทธ๋Œ€๋กœ ํ†ต๊ณผํ•œ๋‹ค.

๋ฌธ์ œ์˜ ๋ชฉํ‘œ๋Š” ๋ชจ์ž„ ํ›„์— ์ตœ์†Œ ํ•œ ๊ฐœ ์ด์ƒ์˜ ์ฐฝ๋ฌธ์ด ๊นจ์งˆ ํ™•๋ฅ ์„ ๊ตฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค.


๐Ÿ› ๏ธ ํ’€์ด ๊ณผ์ •

๋ณธ ๋ฌธ์ œ๋Š” ๊ฐ ์ฐฝ๋ฌธ์˜ ๋‚ด๊ตฌ์„ฑ์„ ๊ฐ•ํ™”์™€ ๋Œ ๋˜์ง€๊ธฐ์˜ ๊ฒฐ๊ณผ๋กœ ๋ชจ๋ธ๋งํ•˜์—ฌ, ์ „์ฒด ๋ฐฉ์ด ์•ˆ์ „ํ•œ ์ƒํƒœ(์ฆ‰, ํ•œ ๊ฐœ์˜ ์ฐฝ๋ฌธ๋„ ๊นจ์ง€์ง€ ์•Š์€ ์ƒํƒœ)๊ฐ€ ๋  ํ™•๋ฅ ์„ ๊ณ„์‚ฐํ•œ ํ›„, 1์—์„œ ํ•ด๋‹น ํ™•๋ฅ ์„ ๋นผ์–ด ์ฐฝ๋ฌธ์ด ๊นจ์งˆ ํ™•๋ฅ ์„ ๊ตฌํ•˜๋Š” ๋ฌธ์ œ์ด๋‹ค. ๋ฌธ์ œ ํ•ด๊ฒฐ ๊ณผ์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ง„ํ–‰๋œ๋‹ค.

  • ์ฐฝ๋ฌธ ๊ทธ๋ฃน ๋ถ„๋ฆฌ:
    K๊ฐœ์˜ ์ฐฝ๋ฌธ ์ค‘ H๊ฐœ๋Š” ์ฒ˜์Œ๋ถ€ํ„ฐ ๊ฐ•ํ™”๋œ ์ฐฝ๋ฌธ(๊ทธ๋ฃน A)์œผ๋กœ ๊ธฐ๋ณธ ๋‚ด๊ตฌ์„ฑ์ด 2์ด๋ฉฐ, ๋‚˜๋จธ์ง€ K − H๊ฐœ๋Š” ๊ธฐ๋ณธ ์ฐฝ๋ฌธ(๊ทธ๋ฃน B)์œผ๋กœ ๊ธฐ๋ณธ ๋‚ด๊ตฌ์„ฑ์ด 1์ด๋‹ค.
  • ๋™์  ๊ณ„ํš๋ฒ•(DP)์„ ํ†ตํ•œ ๊ฒฝ์šฐ์˜ ์ˆ˜ ๊ณ„์‚ฐ:
    ๊ฐ ์ฐฝ๋ฌธ์— ๋Œ€ํ•ด ์ถ”๊ฐ€ ๊ฐ•ํ™” ํšŸ์ˆ˜(dr)์™€ ๋Œ์— ๋งž์€ ํšŸ์ˆ˜(ds)์˜ ์กฐํ•ฉ์œผ๋กœ ๊ธฐ์—ฌ๋„๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค. ๊ฐ ์ฐฝ๋ฌธ์€ ๋‹ค์Œ์˜ ์•ˆ์ „ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•ด์•ผ ํ•œ๋‹ค.
    - ๊ทธ๋ฃน A(๊ฐ•ํ™” ์ฐฝ๋ฌธ): ds ≤ dr + 1
    - ๊ทธ๋ฃน B(๊ธฐ๋ณธ ์ฐฝ๋ฌธ): ds ≤ dr
    ๊ฐ ์ฐฝ๋ฌธ์— ๋Œ€ํ•ด 1/(dr! × ds!)์˜ ๊ฐ€์ค‘์น˜๋ฅผ ๋ถ€์—ฌํ•˜๋Š” ์ƒ์„ฑํ•จ์ˆ˜๋ฅผ ๊ณ ๋ คํ•˜๋ฉฐ, ์ „์ฒด ์ฐฝ๋ฌธ์— ๋Œ€ํ•œ ๊ฒฝ์šฐ์˜ ์ˆ˜๋Š” ๋‘ ๊ทธ๋ฃน์˜ DP ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์„ฑ(convolution)ํ•˜์—ฌ ๊ตฌํ•œ๋‹ค.
  • ์ตœ์ข… ํ™•๋ฅ  ๊ณ„์‚ฐ:
    ๋ชจ์ž„์—์„œ ์ด MํšŒ์˜ ๊ฐ•ํ™”์™€ NํšŒ์˜ ๋Œ ๋˜์ง€๊ธฐ๊ฐ€ ์ด๋ฃจ์–ด์งˆ ๋•Œ, ์•ˆ์ „ํ•œ ์ƒํƒœ์˜ ํ™•๋ฅ  P_safe๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๊ณ„์‚ฐ๋œ๋‹ค.

    P_safe = (M! × N! / K^(M+N)) × S_total

    ์—ฌ๊ธฐ์„œ S_total์€ ์ „์ฒด generating function์—์„œ x^M·y^N ํ•ญ์˜ ๊ณ„์ˆ˜์ด๋‹ค. ์ตœ์ข…์ ์œผ๋กœ ์ฐฝ๋ฌธ์ด ๊นจ์งˆ ํ™•๋ฅ ์€ 1 − P_safe๋กœ ๊ตฌํ•œ๋‹ค.

๐Ÿ’ป ์ฝ”๋“œ ๊ตฌํ˜„ (Java)

import java.io.*;
import java.util.*;

public class Main {
    // M๊ณผ N์˜ ์ตœ๋Œ€๊ฐ’์ด 100์ž„์„ ๊ณ ๋ คํ•˜์—ฌ MAX๋ฅผ 110์œผ๋กœ ์„ค์ •ํ•œ๋‹ค.
    static final int MAX = 110;
    
    public static void main(String[] args) throws Exception {
        // ๋น ๋ฅธ ์ž…์ถœ๋ ฅ์„ ์œ„ํ•˜์—ฌ BufferedReader์™€ PrintWriter๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(System.out);
        
        int T = Integer.parseInt(br.readLine().trim());
        
        // 0๋ถ€ํ„ฐ MAX-1๊นŒ์ง€์˜ ํŒฉํ† ๋ฆฌ์–ผ๊ณผ ๋กœ๊ทธ ํŒฉํ† ๋ฆฌ์–ผ์„ ๋ฏธ๋ฆฌ ๊ณ„์‚ฐํ•œ๋‹ค.
        double[] fact = new double[MAX];
        double[] logFact = new double[MAX];
        fact[0] = 1.0;
        logFact[0] = 0.0;
        for (int i = 1; i < MAX; i++) {
            fact[i] = fact[i - 1] * i;
            logFact[i] = logFact[i - 1] + Math.log(i);
        }
        // 0๋ถ€ํ„ฐ MAX-1๊นŒ์ง€์˜ 1/n! ๊ฐ’์„ ๋ฏธ๋ฆฌ ๊ณ„์‚ฐํ•œ๋‹ค.
        double[] invFact = new double[MAX];
        for (int i = 0; i < MAX; i++) {
            invFact[i] = 1.0 / fact[i];
        }
        
        // ๊ฐ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค.
        for (int t = 1; t <= T; t++) {
            String line = br.readLine();
            String[] parts = line.trim().split("\\s+");
            int K = Integer.parseInt(parts[0]); // ์ฐฝ๋ฌธ์˜ ์ด ๊ฐœ์ˆ˜์ด๋‹ค.
            int N = Integer.parseInt(parts[1]); // ๋Œ์„ ๋˜์ง€๋Š” ์•…๋‹น์˜ ์ˆ˜์ด๋‹ค.
            int M = Integer.parseInt(parts[2]); // ๊ฐ•ํ™”ํ•˜๋Š” ์ผ๊พผ์˜ ์ˆ˜์ด๋‹ค.
            int H = Integer.parseInt(parts[3]); // ์ฒ˜์Œ๋ถ€ํ„ฐ ๊ฐ•ํ™”๋œ ์ฐฝ๋ฌธ์˜ ๊ฐœ์ˆ˜์ด๋‹ค.
            
            // ๊ทธ๋ฃน A๋Š” ๊ฐ•ํ™”๋œ ์ฐฝ๋ฌธ, ๊ทธ๋ฃน B๋Š” ๊ธฐ๋ณธ ์ฐฝ๋ฌธ์ด๋‹ค.
            int countA = H;
            int countB = K - H;
            
            // ๊ทธ๋ฃน A์— ๋Œ€ํ•œ DP ํ…Œ์ด๋ธ”์„ ๊ตฌ์„ฑํ•œ๋‹ค.
            // dpA[r][s]๋Š” ๊ทธ๋ฃน A์˜ ์ฐฝ๋ฌธ์— ๋Œ€ํ•ด ์ด rํšŒ์˜ ์ถ”๊ฐ€ ๊ฐ•ํ™”์™€ sํšŒ์˜ ๋Œ ๋˜์ง€๊ธฐ๊ฐ€ ์ด๋ฃจ์–ด์กŒ์„ ๋•Œ์˜ ๊ธฐ์—ฌ๋„ ํ•ฉ์ด๋‹ค.
            // ๊ทธ๋ฃน A์˜ ์•ˆ์ „ ์กฐ๊ฑด์€ ds ≤ r + 1์ด๋‹ค.
            double[][] dpA = new double[M + 1][N + 1];
            dpA[0][0] = 1.0;
            for (int i = 0; i < countA; i++) {
                double[][] newdp = new double[M + 1][N + 1];
                // ํ˜„์žฌ๊นŒ์ง€์˜ ๊ฐ•ํ™” ํšŸ์ˆ˜(r0)์™€ ๋Œ ๋˜์ง„ ํšŸ์ˆ˜(s0)์— ๋Œ€ํ•˜์—ฌ ์ˆœํšŒํ•œ๋‹ค.
                for (int r0 = 0; r0 <= M; r0++) {
                    for (int s0 = 0; s0 <= N; s0++) {
                        double cur = dpA[r0][s0];
                        if (cur == 0.0) continue;
                        int remR = M - r0; // ๋‚จ์€ ๊ฐ•ํ™” ํšŸ์ˆ˜์ด๋‹ค.
                        int remS = N - s0; // ๋‚จ์€ ๋Œ ๋˜์ง€๊ธฐ ํšŸ์ˆ˜์ด๋‹ค.
                        // ์ƒˆ ์ฐฝ๋ฌธ์— ๋Œ€ํ•ด ๊ฐ€๋Šฅํ•œ (dr, ds) ์กฐํ•ฉ์„ ์‹œ๋„ํ•œ๋‹ค.
                        // ๋‹จ, ์•ˆ์ „ ์กฐ๊ฑด์€ ds ≤ dr + 1์ด๋‹ค.
                        for (int dr = 0; dr <= remR; dr++) {
                            int maxDs = Math.min(remS, dr + 1);
                            for (int ds = 0; ds <= maxDs; ds++) {
                                // ํ•œ ์ฐฝ๋ฌธ์—์„œ์˜ ๊ธฐ์—ฌ๋„๋Š” 1/(dr! × ds!)์ด๋‹ค.
                                double add = invFact[dr] * invFact[ds];
                                newdp[r0 + dr][s0 + ds] += cur * add;
                            }
                        }
                    }
                }
                dpA = newdp;
            }
            
            // ๊ทธ๋ฃน B์— ๋Œ€ํ•œ DP ํ…Œ์ด๋ธ”์„ ๊ตฌ์„ฑํ•œ๋‹ค.
            // dpB[r][s]๋Š” ๊ทธ๋ฃน B์˜ ์ฐฝ๋ฌธ์— ๋Œ€ํ•ด ์ด rํšŒ์˜ ์ถ”๊ฐ€ ๊ฐ•ํ™”์™€ sํšŒ์˜ ๋Œ ๋˜์ง€๊ธฐ๊ฐ€ ์ด๋ฃจ์–ด์กŒ์„ ๋•Œ์˜ ๊ธฐ์—ฌ๋„ ํ•ฉ์ด๋‹ค.
            // ๊ทธ๋ฃน B์˜ ์•ˆ์ „ ์กฐ๊ฑด์€ ds ≤ r์ด๋‹ค.
            double[][] dpB = new double[M + 1][N + 1];
            dpB[0][0] = 1.0;
            for (int i = 0; i < countB; i++) {
                double[][] newdp = new double[M + 1][N + 1];
                for (int r0 = 0; r0 <= M; r0++) {
                    for (int s0 = 0; s0 <= N; s0++) {
                        double cur = dpB[r0][s0];
                        if (cur == 0.0) continue;
                        int remR = M - r0;
                        int remS = N - s0;
                        // ๊ทธ๋ฃน B์˜ ๊ฒฝ์šฐ, ๊ฐ€๋Šฅํ•œ (dr, ds) ์กฐํ•ฉ์€ ds ≤ dr๋ฅผ ๋งŒ์กฑํ•œ๋‹ค.
                        for (int dr = 0; dr <= remR; dr++) {
                            int maxDs = Math.min(remS, dr);
                            for (int ds = 0; ds <= maxDs; ds++) {
                                double add = invFact[dr] * invFact[ds];
                                newdp[r0 + dr][s0 + ds] += cur * add;
                            }
                        }
                    }
                }
                dpB = newdp;
            }
            
            // ๋‘ ๊ทธ๋ฃน์˜ DP ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์„ฑํ•˜์—ฌ ์ „์ฒด generating function์—์„œ x^M · y^N ํ•ญ์˜ ๊ณ„์ˆ˜ S_total์„ ๊ตฌํ•œ๋‹ค.
            double S_total = 0.0;
            for (int rA = 0; rA <= M; rA++) {
                for (int sA = 0; sA <= N; sA++) {
                    int rB = M - rA;
                    int sB = N - sA;
                    if (rB < 0 || sB < 0) continue;
                    S_total += dpA[rA][sA] * dpB[rB][sB];
                }
            }
            
            // ์ „์ฒด ๋ฐฉ์ด ์•ˆ์ „ํ•œ ์ƒํƒœ(์ฆ‰, ํ•œ ๊ฐœ์˜ ์ฐฝ๋ฌธ๋„ ๊นจ์ง€์ง€ ์•Š์€ ์ƒํƒœ)๊ฐ€ ๋  ํ™•๋ฅ  P_safe๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๊ณ„์‚ฐ๋œ๋‹ค.
            // P_safe = (M! × N! / K^(M+N)) × S_total
            // ํฐ ์ˆ˜์˜ ๊ณ„์‚ฐ์„ ์œ„ํ•˜์—ฌ ๋กœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ„์‚ฐํ•œ๋‹ค.
            double logP_safe;
            if (S_total == 0.0) {
                logP_safe = Double.NEGATIVE_INFINITY;
            } else {
                logP_safe = logFact[M] + logFact[N] + Math.log(S_total) - (M + N) * Math.log(K);
            }
            double P_safe = (logP_safe == Double.NEGATIVE_INFINITY ? 0.0 : Math.exp(logP_safe));
            double ans = 1.0 - P_safe;
            if (ans < 0) ans = 0.0;
            if (ans > 1) ans = 1.0;
            
            out.printf("Case #%d: %.8f%n", t, ans);
        }
        out.flush();
        out.close();
    }
}

โฑ๏ธ ์‹œ๊ฐ„ ๋ณต์žก๋„ ๋ถ„์„

๋ณธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๊ฐ ์ฐฝ๋ฌธ๋งˆ๋‹ค ๊ฐ€๋Šฅํ•œ ๊ฐ•ํ™”์™€ ๋Œ ๋˜์ง€๊ธฐ ์กฐํ•ฉ์„ 2์ฐจ์› ๋™์  ๊ณ„ํš๋ฒ•(DP)์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ„์‚ฐํ•œ๋‹ค. DP ๋ฐฐ์—ด์˜ ํฌ๊ธฐ๋Š” (M+1)×(N+1)์ด๋ฉฐ, ๋‚ด๋ถ€ ๋ฐ˜๋ณต๋ฌธ์—์„œ๋Š” ๊ฐ•ํ™” ํšŸ์ˆ˜์™€ ๋Œ ๋˜์ง€๊ธฐ ํšŸ์ˆ˜๋ฅผ ๋ชจ๋‘ ๊ณ ๋ คํ•œ๋‹ค.

๊ทธ๋ฃน A์™€ ๊ทธ๋ฃน B์˜ ์ฐฝ๋ฌธ ์ˆ˜์˜ ํ•ฉ์€ K(์ตœ๋Œ€ 200)๊ฐœ์ด๋ฏ€๋กœ, ์ „์ฒด ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” ์ œํ•œ ๋‚ด์—์„œ ์ถฉ๋ถ„ํžˆ ๊ณ„์‚ฐ ๊ฐ€๋Šฅํ•˜๋‹ค.


๐Ÿ’ก ๋Š๋‚€์ 

๋ณธ ๋ฌธ์ œ๋Š” ๋‹จ์ˆœํ•ด ๋ณด์ด๋Š” ์ƒํ™ฉ์„ ์ˆ˜ํ•™์  ๋ชจ๋ธ๋ง๊ณผ ๋™์  ๊ณ„ํš๋ฒ•์„ ํ†ตํ•˜์—ฌ ํšจ๊ณผ์ ์œผ๋กœ ํ•ด๊ฒฐํ•œ ๋ชจ๋ฒ”์ ์ธ ์‚ฌ๋ก€์ด๋‹ค. ๊ฐ ์ฐฝ๋ฌธ์˜ ๋‚ด๊ตฌ์„ฑ์„ ๊ฐ•ํ™”์™€ ๋Œ ๋˜์ง€๊ธฐ์˜ ์กฐํ•ฉ์œผ๋กœ ์„ธ๋ถ„ํ™”ํ•˜์—ฌ ์•ˆ์ „ ์กฐ๊ฑด์„ ์—„๋ฐ€ํ•˜๊ฒŒ ์ •์˜ํ•œ ์ ์ด ์ธ์ƒ์ ์ด๋‹ค. ๋˜ํ•œ, ํฐ ์ˆ˜์˜ ์—ฐ์‚ฐ์—์„œ ๋กœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๋ฅผ ๋ฐฉ์ง€ํ•œ ์ ‘๊ทผ๋ฒ•์€ ๊ณ„์‚ฐ์˜ ์•ˆ์ •์„ฑ์„ ๋ณด์žฅํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐฉ๋ฒ•๋ก ์€ ๋ณต์žกํ•œ ์กฐํ•ฉ๋ก  ๋ฌธ์ œ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋œ๋‹ค.

๋ฐ˜์‘ํ˜•

'์•Œ๊ณ ๋ฆฌ์ฆ˜ > BOJ - Java' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[BOJ/Java] 3628. Knockdown  (0) 2025.03.14
[BOJ/Java] 6902. Orko  (1) 2025.03.13
[BOJ/Java] 5266. Strange Dream  (0) 2025.03.13
[BOJ/Java] 11404. ํ”Œ๋กœ์ด๋“œ  (1) 2025.03.10
[BOJ/Java] 2931. ๊ฐ€์Šค๊ด€  (0) 2025.03.10
Comments