D - ボールの箱詰め / Packing Balls into Boxes Editorial by admin Editorial for printing
Claude 4.6 Opus (Thinking)Overview
This problem asks you to group \(K\) balls based on constraints that “certain balls must be placed in the same box,” and then count the number of surjections (mappings where no box is empty) from the resulting \(G\) distinguishable groups to \(N\) distinguishable boxes.
Analysis
Grouping constraints together
If “Ball \(A\) and \(B\) are in the same box” and “Ball \(B\) and \(C\) are in the same box,” then \(A, B, C\) must all be in the same box. Since this is a transitive relation, we can efficiently determine the sets of balls (groups) that must be in the same box using Union-Find (Disjoint Set Union).
Reducing to a group distribution problem
Since balls in the same group must be placed in the same box, we can treat each group as a single “unit.” If the number of groups is \(G\), the problem reduces to:
Count the number of ways to distribute \(G\) distinguishable groups into \(N\) distinguishable boxes such that every box contains at least one group.
Counting surjections
This is exactly the “number of surjections from a set of \(G\) elements to a set of \(N\) elements.”
- If \(G < N\): Since there are fewer groups than boxes, at least one box must be empty, so the answer is \(0\).
- If \(G \geq N\): We compute the answer using the inclusion-exclusion principle.
Surjection formula via inclusion-exclusion
To exclude cases where at least one of the \(N\) boxes is empty, we apply the inclusion-exclusion principle:
\[\text{Number of surjections} = \sum_{i=0}^{N} (-1)^i \binom{N}{i} (N - i)^G\]
Intuitively: - \(i = 0\): Number of ways to place \(G\) groups into \(N\) boxes without restriction \(= N^G\) - When we decide that \(i\) specific boxes are “not used,” the number of ways to place into the remaining \((N-i)\) boxes \(= (N-i)^G\) - We add and subtract this over all \(\binom{N}{i}\) ways to choose those boxes
Algorithm
- Use Union-Find to group the \(K\) balls and determine the number of groups \(G\).
- If \(G < N\), the answer is \(0\).
- If \(G \geq N\), compute the inclusion-exclusion formula \(\sum_{i=0}^{N} (-1)^i \binom{N}{i} (N-i)^G\).
- Precompute factorials and their modular inverses for binomial coefficient calculations.
Concrete Example
For \(N=2, K=3, M=1\) with the constraint “Ball 1 and Ball 2 are in the same box”: - Groups: \(\{1, 2\}, \{3\}\) → \(G = 2\) - Number of surjections \(= \sum_{i=0}^{2} (-1)^i \binom{2}{i}(2-i)^2 = 1 \cdot 4 - 2 \cdot 1 + 1 \cdot 0 = 2\) - The distributions are: “Group \(\{1,2\}\) → Box 1, \(\{3\}\) → Box 2” and “Group \(\{1,2\}\) → Box 2, \(\{3\}\) → Box 1” — 2 ways.
Complexity
- Time complexity: \(O(K \cdot \alpha(K) + N \log G)\)
- Union-Find construction: \(O(K \cdot \alpha(K))\) (\(\alpha\) is the inverse Ackermann function)
- Inclusion-exclusion loop: \(O(N \log G)\) (each term requires \(O(\log G)\) for \(\text{pow}(N-i, G, \text{MOD})\))
- Space complexity: \(O(K + N)\) (Union-Find arrays and factorial table)
Implementation Notes
Use path compression and union by rank in Union-Find for efficiency.
Compute modular inverses of factorials by first computing the inverse of the largest factorial (using Fermat’s little theorem to find \(\text{fact}[n]^{-1}\)), then computing downward via \(\text{inv\_fact}[i] = \text{inv\_fact}[i+1] \times (i+1)\).
When subtracting in the inclusion-exclusion, add
MODbefore taking the remainder to avoid negative numbers.Source Code
import sys
from sys import stdin
def main():
input = stdin.readline
N, K, M = map(int, stdin.readline().split())
MOD = 998244353
# Union-Find to group balls that must be in the same box
parent = list(range(K + 1))
rank = [0] * (K + 1)
def find(x):
while parent[x] != x:
parent[x] = parent[parent[x]]
x = parent[x]
return x
def union(x, y):
px, py = find(x), find(y)
if px == py:
return
if rank[px] < rank[py]:
px, py = py, px
parent[py] = px
if rank[px] == rank[py]:
rank[px] += 1
for _ in range(M):
u, v = map(int, stdin.readline().split())
union(u, v)
# Count number of groups
groups = set()
for i in range(1, K + 1):
groups.add(find(i))
G = len(groups) # number of groups (each group must go into exactly one box)
# We need to distribute G groups into N boxes such that:
# - each group goes into exactly one box
# - no box is empty
# This is equivalent to surjective functions from G groups to N boxes
# which is S(G, N) * N! where S is Stirling numbers of the second kind
# But since groups are distinguishable and boxes are distinguishable,
# it's the number of surjective functions from a G-element set to an N-element set.
# If G < N, answer is 0 (can't fill all boxes)
if G < N:
print(0)
return
# Number of surjective functions from G-set to N-set:
# sum_{i=0}^{N} (-1)^i * C(N, i) * (N - i)^G
# Using inclusion-exclusion
# Precompute factorials and inverse factorials
max_n = max(N, G) + 1
fact = [1] * (max_n + 1)
for i in range(1, max_n + 1):
fact[i] = fact[i - 1] * i % MOD
inv_fact = [1] * (max_n + 1)
inv_fact[max_n] = pow(fact[max_n], MOD - 2, MOD)
for i in range(max_n - 1, -1, -1):
inv_fact[i] = inv_fact[i + 1] * (i + 1) % MOD
ans = 0
for i in range(N + 1):
# C(N, i) * (N - i)^G * (-1)^i
comb = fact[N] * inv_fact[i] % MOD * inv_fact[N - i] % MOD
term = comb * pow(N - i, G, MOD) % MOD
if i % 2 == 0:
ans = (ans + term) % MOD
else:
ans = (ans - term + MOD) % MOD
print(ans % MOD)
main()
This editorial was generated by claude4.6opus-thinking.
posted:
last update: