#! /usr/bin/python3 # Last edited on 2026-09-08 17:21:33 by stolfi import math, sys from math import comb def prob(N, C, M, F): # Consider a set of N boxes, C of which contain one coin each. # This function computes the probability that picking M # of the N boxes at random will yield F of the C coins. # That is comb(C,F)*comb(N-C,M-F)/comb(N,M). # Boundary logic checks if F < 0 or F > C or F > M or (M - F) > (N - C): return 0.0 def ln_fact(n): # Computes ln(n!) safely. return math.lgamma(n + 1) def ln_comb(n,k): # Computes ln(comb(n,k)) safely. assert n > 0 and k >= 0 and k <= n return ln_fact(n) - ln_fact(k) - ln_fact(n-k) # Combine the log pieces and convert back via exponentiation ln_prob = ln_comb(C,F) + ln_comb(N-C,M-F) - ln_comb(N,M) return math.exp(ln_prob) assert abs(prob(10,1,1,1) - 1/10) < 1.0e-6 assert abs(prob(10,3,1,1) - 3/10) < 1.0e-6 assert abs(prob(10,3,2,1) - 42/90) < 1.0e-6 assert abs(prob(10,3,2,2) - 6/90) < 1.0e-6 ia = 1 N = int(sys.argv[ia]); ia += 1 C = int(sys.argv[ia]); ia += 1 M = int(sys.argv[ia]); ia += 1 F = int(sys.argv[ia]); ia += 1 assert ia == len(sys.argv) # if ln_comb(M,F) < ln_comb(MAX_INT): print("comb(%d,%d) = %d" % (M, F, comb(M,F))) P = prob(N,C,M,F) print("P = %.30f" % P) print("1/P = %.0f" % (1/P))