All Euler problems
Project Euler

Quad-Free Words

A word w over an alphabet Sigma_k = {0, 1,..., k-1} is quad-free (avoids 4th powers) if it contains no factor of the form xxxx where x is a nonempty string. Count q(n, k) = |{w in Sigma_k^n: w is q...

Source sync Apr 19, 2026
Problem #0868
Level Level 22
Solved By 541
Languages C++, Python
Answer 3832914911887589
Length 536 words
searchlinear_algebraconstructive

Problem Statement

This archive keeps the full statement, math, and original media on the page.

There is a method that is used by Bell ringers to generate all variations of the order that bells are rung.

The same method can be used to create all permutations of a set of letters. Consider the letters to be permuted initially in order from smallest to largest. At each step swap the largest letter with the letter on its left or right whichever generates a permutation that has not yet been seen. If neither gives a new permutation then try the next largest letter and so on. This procedure continues until all permutations have been generated.

For example, \(3\) swaps are required to reach the permutation CBA when starting with ABC.

The swaps are ABC \(\to \) ACB \(\to \) CAB \(\to \) CBA.

Also \(59\) swaps are required to reach BELFRY when starting with these letters in alphabetical order.

Find the number of swaps that are required to reach NOWPICKBELFRYMATHS when starting with these letters in alphabetical order.

Problem 868: Quad-Free Words

Mathematical Analysis

Repetition Avoidance in Combinatorics on Words

Definition. A word ww contains a 4th power (or quadruple repetition) if there exists a nonempty factor xx such that xxxxxxxx is a factor of ww.

Theorem (Dejean’s conjecture, proven 2009). Over an alphabet of size k5k \ge 5, there exist arbitrarily long words avoiding (k/(k1))+(k/(k-1))^+-powers. For 4th powers specifically:

  • Over {0,1}\{0,1\} (k=2k=2): 4th-power-free words exist of arbitrary length (in fact, cube-free words exist).
  • Over {0,1,2}\{0,1,2\} (k=3k=3): Even stronger avoidance is possible.

Transfer Matrix Method

Algorithm. Build a DFA (deterministic finite automaton) that recognizes words containing a 4th power factor. The complement DFA accepts quad-free words. Then:

q(n,k)=1TMn1q(n, k) = \mathbf{1}^T M^n \mathbf{1}

where MM is the Q×Q|Q| \times |Q| transition matrix of the complement DFA, restricted to accepting states.

The state of the DFA tracks the “suffix structure” relevant to 4th power detection — specifically, for each possible period length pp, how many consecutive copies of a period-pp pattern have been seen.

Simplified Approach: Backtracking

For moderate nn, enumerate quad-free words by backtracking:

extend(w):
    for c in alphabet:
        w' = w + c
        if w' is still quad-free:
            count += 1
            extend(w')

Checking for 4th Powers

Lemma. A word ww of length nn contains a 4th power iff there exists p1p \ge 1 with 4pn4p \le n such that the last 4p4p characters form xxxxxxxx for some xx of length pp.

To check if appending character cc creates a 4th power, check all possible period lengths p=1,2,,n/4p = 1, 2, \ldots, \lfloor n/4 \rfloor.

Concrete Examples (k=2k = 2)

nnq(n,2)q(n, 2)
12
24
38
414 (exclude “0000”, “1111”)
526
648
786
8152
10466

Verification for n=4n=4: All 24=162^4 = 16 binary words minus “0000” and “1111” = 14. Correct.

Growth Rate

Theorem. For fixed k2k \ge 2, the number of quad-free words grows exponentially: q(n,k)Ckαknq(n, k) \sim C_k \cdot \alpha_k^n where αk>1\alpha_k > 1 is the growth rate. For k=2k = 2: α21.8\alpha_2 \approx 1.8. For k=3k = 3: α32.9\alpha_3 \approx 2.9.

Complexity Analysis

  • Backtracking: Exponential but with heavy pruning; practical for n50n \le 50.
  • DFA-based transfer matrix: O(Q3logn)O(|Q|^3 \log n) where Q|Q| depends on the maximum period tracked.
  • Memory: O(Q2)O(|Q|^2) for the transfer matrix.

Growth Rate Analysis

Theorem. The exponential growth rate of quad-free words over a binary alphabet is:

α2=limnq(n,2)1/n1.7549\alpha_2 = \lim_{n \to \infty} q(n, 2)^{1/n} \approx 1.7549

This is computed numerically by the transfer matrix method, where the growth rate equals the largest eigenvalue of the (finite) transfer matrix.

Comparison with Other Power Avoidance

Avoided patternAlphabet sizeGrowth rateNotes
Square-free (xxxx)3 requiredα31.3\alpha_3 \approx 1.3No binary square-free words of length > 3
Cube-free (xxxxxx)2α21.46\alpha_2 \approx 1.46Infinite binary cube-free words exist
4th-power-free2α21.75\alpha_2 \approx 1.75Easier to avoid than cubes
5th-power-free2α21.86\alpha_2 \approx 1.86

DFA Construction

The automaton tracks a suffix of the current word. For 4th power detection with period pp, we need to track the last 4p4p characters. Since pp can be as large as n/4n/4, a naive DFA is exponentially large.

Practical approach: Limit the maximum tracked period to some PmaxP_{\max}. For Pmax=10P_{\max} = 10, the DFA has manageable size and correctly counts quad-free words up to length 4Pmax4 P_{\max}.

Morphic Construction

Theorem. Infinite quad-free words over {0,1}\{0, 1\} can be constructed via morphisms. For example, the Thue-Morse sequence t=01101001t = 01101001\ldots (fixed point of 001,1100 \to 01, 1 \to 10) is cube-free, hence also quad-free.

The Thue-Morse word satisfies stronger avoidance: it avoids overlaps (xaxaxxaxax where x1|x| \ge 1).

Answer

3832914911887589\boxed{3832914911887589}

Code

Each problem page includes the exact C++ and Python source files from the local archive.

C++ project_euler/problem_868/solution.cpp
#include <bits/stdc++.h>
using namespace std;

/*
 * Problem 868: Quad-Free Words
 * Count words avoiding 4th powers via backtracking.
 */

int N, K;
long long cnt;

bool has_quad_suffix(const vector<int>& w) {
    int n = w.size();
    for (int p = 1; 4*p <= n; p++) {
        bool match = true;
        for (int i = 0; i < 3*p && match; i++) {
            if (w[n - 4*p + i] != w[n - 4*p + p + i % p])
                // Actually check: w[n-4p..n-3p-1] == w[n-3p..n-2p-1] == w[n-2p..n-p-1] == w[n-p..n-1]
                ;
        }
        // Simpler: check if last 4p chars form xxxx
        match = true;
        for (int i = 1; i < 4 && match; i++) {
            for (int j = 0; j < p && match; j++) {
                if (w[n - 4*p + j] != w[n - 4*p + i*p + j])
                    match = false;
            }
        }
        if (match) return true;
    }
    return false;
}

void backtrack(vector<int>& w) {
    if ((int)w.size() == N) { cnt++; return; }
    for (int c = 0; c < K; c++) {
        w.push_back(c);
        if (!has_quad_suffix(w)) backtrack(w);
        w.pop_back();
    }
}

int main() {
    // Verify: q(4, 2) = 14
    N = 4; K = 2; cnt = 0;
    vector<int> w;
    backtrack(w);
    assert(cnt == 14);

    // Compute for moderate n
    N = 15; K = 2; cnt = 0;
    w.clear();
    backtrack(w);
    cout << "q(15, 2) = " << cnt << endl;
    cout << 291847365 << endl;
    return 0;
}