Coloured Configurations
Consider configurations built from 25 copies of unit A and 75 copies of unit B, glued together along their vertical edges, with vertices coloured from 1984 available colours so that adjacent vertic...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
Consider graphs built with the units \(A\):
and \(B\):
, where the units are glued along the vertical edges as
in the graph
.
A configuration of type \((a, b, c)\) is a graph thus built of \(a\) units \(A\) and \(b\) units \(B\), where the graph’s vertices are coloured using up to \(c\) colours, so that no two adjacent vertices have the same colour.
The compound graph above is an example of a configuration of type \((2,2,6)\), in fact of type \((2,2,c)\) for all \(c \ge 4\).
Let \(N(a, b, c)\) be the number of configurations of type \((a, b, c)\).
For example, \(N(1,0,3) = 24\), \(N(0,2,4) = 92928\) and \(N(2,2,3) = 20736\).
Find the last \(8\) digits of \(N(25,75,1984)\).
Problem 194: Coloured Configurations
Mathematical Development
Theorem 1. (Chromatic Polynomial of .) The number of proper -colourings of the complete graph is the falling factorial
Proof. In a proper colouring of , every pair of vertices must receive distinct colours. Assign colours greedily: the first vertex has choices, the second , …, the -th vertex has choices. Since has all edges, every greedy assignment is valid and every valid colouring arises exactly once.
Theorem 2. (Clique Separator Theorem.) If where is a clique , then
Proof. Let with , and induces a clique in both and . For any proper colouring of , the restriction is a proper colouring of . Conversely, for a fixed proper colouring of :
-
The number of extensions of to all of is , since every colouring of restricts to some colouring of , and by symmetry (all colourings of are equivalent under colour permutation in terms of extension count), each colouring of has exactly extensions.
-
Similarly, the number of extensions of to is .
Since and are disjoint and share no edges, the extensions are independent. Summing over all colourings of :
Lemma 1. (Application.) For with (a shared edge):
Proof. By Theorems 1 and 2 with :
Since , the factor cancels exactly.
Editorial
Fix the colours on the leftmost vertical edge first. There are c(c-1) ordered ways to do that, and once those two boundary colours are fixed, the number of valid colourings of a single unit depends only on whether the unit is of type A or type B. Enumerating the five remaining vertices of one unit gives two polynomials:
Every time another unit is glued onto the chain, the new left boundary is again just an ordered pair of distinct colours, so the same single-unit count applies again. That means a configuration with a copies of A and b copies of B contributes
for any fixed order of the units. The only remaining combinatorics is choosing which a of the a+b positions contain unit A, giving the binomial factor \binom{a+b}{a}. The final computation is therefore one binomial coefficient and two modular exponentiations.
Pseudocode
Set c = 1984, a = 25, b = 75, and MOD = 10^8.
Evaluate the single-unit colouring polynomials A(c) and B(c).
Compute the binomial factor C(a + b, a).
Start with the c(c-1) choices for the colours on the first vertical edge.
Multiply by A(c)^a and B(c)^b.
Multiply by C(a + b, a) to account for the placements of the A-units.
Take the result modulo MOD and return it.
Complexity Analysis
- Time: modular multiplications. For , this is 98 multiplications.
- Space: .
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <cassert>
#include <iostream>
#include <vector>
using namespace std;
unsigned long long unit_a_count(unsigned long long c) {
return c * c * c * c * c - 9 * c * c * c * c + 34 * c * c * c - 69 * c * c + 77 * c - 38;
}
unsigned long long unit_b_count(unsigned long long c) {
return c * c * c * c * c - 8 * c * c * c * c + 27 * c * c * c - 50 * c * c + 52 * c - 24;
}
unsigned long long exact_binomial_small(int n, int k) {
if (k > n - k) {
k = n - k;
}
unsigned long long result = 1;
for (int i = 1; i <= k; ++i) {
result = result * static_cast<unsigned long long>(n - k + i) / static_cast<unsigned long long>(i);
}
return result;
}
unsigned long long pow_ull(unsigned long long base, int exp) {
unsigned long long result = 1;
while (exp > 0) {
if (exp & 1) {
result *= base;
}
base *= base;
exp >>= 1;
}
return result;
}
unsigned long long configuration_count_small(int a_units, int b_units, unsigned long long colors) {
return colors * (colors - 1) * exact_binomial_small(a_units + b_units, a_units)
* pow_ull(unit_a_count(colors), a_units) * pow_ull(unit_b_count(colors), b_units);
}
unsigned long long mod_pow(unsigned long long base, int exp, unsigned long long mod) {
unsigned long long result = 1 % mod;
unsigned long long value = base % mod;
while (exp > 0) {
if (exp & 1) {
result = (result * value) % mod;
}
value = (value * value) % mod;
exp >>= 1;
}
return result;
}
int prime_exponent_in_factorial(int n, int p) {
int exponent = 0;
while (n > 0) {
n /= p;
exponent += n;
}
return exponent;
}
unsigned long long binomial_mod_100_25(unsigned long long mod) {
const int n = 100;
const int k = 25;
const int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47,
53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
unsigned long long result = 1;
for (int p : primes) {
int exponent = prime_exponent_in_factorial(n, p)
- prime_exponent_in_factorial(k, p)
- prime_exponent_in_factorial(n - k, p);
if (exponent > 0) {
result = result * mod_pow(static_cast<unsigned long long>(p), exponent, mod) % mod;
}
}
return result;
}
int main() {
const unsigned long long mod = 100000000ULL;
const unsigned long long colors = 1984;
assert(configuration_count_small(1, 0, 3) == 24ULL);
assert(configuration_count_small(0, 2, 4) == 92928ULL);
assert(configuration_count_small(2, 2, 3) == 20736ULL);
unsigned long long answer = colors % mod;
answer = answer * ((colors - 1) % mod) % mod;
answer = answer * binomial_mod_100_25(mod) % mod;
answer = answer * mod_pow(unit_a_count(colors) % mod, 25, mod) % mod;
answer = answer * mod_pow(unit_b_count(colors) % mod, 75, mod) % mod;
assert(answer == 61190912ULL);
cout << answer << '\n';
return 0;
}
"""
Project Euler Problem 194: Coloured Configurations
Count colourings of chains made from 25 A-units and 75 B-units, modulo 10^8.
"""
from math import comb
def unit_a_count(colors):
c = colors
return c**5 - 9 * c**4 + 34 * c**3 - 69 * c**2 + 77 * c - 38
def unit_b_count(colors):
c = colors
return c**5 - 8 * c**4 + 27 * c**3 - 50 * c**2 + 52 * c - 24
def configuration_count(a_units, b_units, colors):
return (
colors
* (colors - 1)
* comb(a_units + b_units, a_units)
* unit_a_count(colors) ** a_units
* unit_b_count(colors) ** b_units
)
def solve():
mod = 10**8
return configuration_count(25, 75, 1984) % mod
if __name__ == "__main__":
assert configuration_count(1, 0, 3) == 24
assert configuration_count(0, 2, 4) == 92928
assert configuration_count(2, 2, 3) == 20736
answer = solve()
assert answer == 61190912
print(answer)