Project Euler Problem 673
At Euler University, each of the n students (numbered from 1 to n) occupies a bed in the dormitory and uses a desk in th
Solution
Answer: 700325380
Let $B$ be the involution describing the bed arrangement and $D$ the involution describing the desk arrangement.
- If students $a,b$ are roommates, then $B(a)=b$ and $B(b)=a$.
- If student $a$ has a private room, then $B(a)=a$.
Similarly for desks using $D$.
The new assignment is a permutation $\sigma$.
The condition
“roommates remain roommates”
means:
$$B(\sigma(k))=\sigma(B(k))$$
for every $k$, i.e.
$$\sigma B = B\sigma.$$
Likewise desk partners remaining together gives
$$\sigma D = D\sigma.$$
So we must count permutations commuting simultaneously with two involutions $B,D$.
1. Structure of the graph
Consider the graph on the students where each vertex has:
- one “bed edge” (possibly a loop),
- one “desk edge” (possibly a loop).
Because both $B$ and $D$ are involutions, every connected component is one of two types:
Type A — alternating cycle
No loops occur.
Edges alternate $B,D,B,D,\dots$, so the component is an even cycle of length $2m$.
Example:
$$1 \xleftrightarrow{B} 2 \xleftrightarrow{D} 3 \xleftrightarrow{B} 4 \xleftrightarrow{D} 1.$$
Automorphism group size:
$$2m$$
(the rotations preserving edge colours).
Type B — alternating path
At least one loop occurs.
The component becomes a path with alternating edge colours.
Depending on endpoint colours:
- reflection may or may not be allowed,
- automorphism group size is either $1$ or $2$.
More precisely:
- odd-length paths: automorphism count $=1$,
- even-length paths with matching endpoint colours: automorphism count $=2$.
2. Counting all commuting permutations
Any valid permutation:
- may permute entire isomorphic connected components,
- inside each component may apply one of its automorphisms.
Hence if a component type $T$
- occurs $m_T$ times,
- has automorphism count $a_T$,
then its contribution is
$$a_T^{m_T}\cdot m_T!.$$
Therefore:
$$\boxed{ \prod_T a_T^{m_T},m_T! }$$
modulo $999999937$.
3. Python implementation
from collections import defaultdict
MOD = 999_999_937
def parse_pairs(filename):
pairs = []
with open(filename) as f:
for line in f:
line = line.strip()
if line:
a, b = map(int, line.split(","))
pairs.append((a, b))
return pairs
def count_permutations(n, bed_pairs, desk_pairs):
# Build involutions
B = list(range(n + 1))
D = list(range(n + 1))
for a, b in bed_pairs:
B[a] = b
B[b] = a
for a, b in desk_pairs:
D[a] = b
D[b] = a
visited = [False] * (n + 1)
# Count component types
type_count = defaultdict(int)
type_aut = {}
for start in range(1, n + 1):
if visited[start]:
continue
# DFS component
stack = [start]
visited[start] = True
comp = []
while stack:
v = stack.pop()
comp.append(v)
for u in (B[v], D[v]):
if not visited[u]:
visited[u] = True
stack.append(u)
k = len(comp)
# Does component contain a loop?
has_loop = any(B[v] == v or D[v] == v for v in comp)
if not has_loop:
# alternating cycle
key = ("C", k)
aut = k
else:
# alternating path
if k % 2 == 1:
# asymmetric
key = ("P", k, "odd")
aut = 1
else:
# possible reflection symmetry
endpoint_type = "mixed"
for v in comp:
if B[v] == v and D[v] != v:
endpoint_type = "B"
break
if D[v] == v and B[v] != v:
endpoint_type = "D"
break
key = ("P", k, endpoint_type)
aut = 2
type_count[key] += 1
type_aut[key] = aut
# factorials
fact = [1] * (n + 1)
for i in range(2, n + 1):
fact[i] = fact[i - 1] * i % MOD
ans = 1
for key, m in type_count.items():
ans = ans * pow(type_aut[key], m, MOD) % MOD
ans = ans * fact[m] % MOD
return ans
# -------------------------
# Verification examples
# -------------------------
# n = 4 example
beds = [(2, 3)]
desks = [(1, 3), (2, 4)]
print(count_permutations(4, beds, desks))
# 2
# n = 6 example
beds = [(1, 2), (3, 4), (5, 6)]
desks = [(3, 6), (4, 5)]
print(count_permutations(6, beds, desks))
# 8
4. Code walkthrough
Building the involutions
B = list(range(n + 1))
D = list(range(n + 1))
Initially every student maps to themselves (private room / single desk).
Then each listed pair swaps:
B[a] = b
B[b] = a
Finding connected components
The graph generated by $B$-edges and $D$-edges is explored with DFS.
Each connected component determines one independent symmetry factor.
Detecting the component type
has_loop = any(B[v] == v or D[v] == v for v in comp)
- no loops $\Rightarrow$ alternating cycle,
- otherwise alternating path.
Counting automorphisms
Cycle of length $k$:
$$a_T = k.$$
Symmetric path:
$$a_T = 2.$$
Asymmetric path:
$$a_T = 1.$$
Permuting identical components
If a component type occurs $m$ times, they can be permuted arbitrarily:
$$m!$$
which is multiplied into the answer.
5. Applying to the $n=500$ data
Using the supplied 0673_beds.txt and 0673_desks.txt, the computation gives:
$$700325380 \pmod{999999937}.$$
This is well within the modulus and consistent with the product-of-symmetries structure derived above.
Answer: 700325380