All Euler problems
Project Euler

Magic Bracelets

A bracelet is made by connecting at least three numbered beads in a circle. Each bead can display either 1, 2, or a number of the form p^k or 2p^k where p is an odd prime. A bracelet is called "mag...

Source sync Apr 19, 2026
Problem #0846
Level Level 33
Solved By 249
Languages C++, Python
Answer 9851175623
Length 424 words
graphnumber_theorysearch

Problem Statement

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

A bracelet is made by connecting at least three number beads in a circle. Each bead can only display $1$, $2$, or any number of the form $p^k$ or $2p^k$ for odd prime $p$.

In additino a magic bracelet must satisfy the following two conditions:

  • no two beads display the same number

  • the product of the numbers of any two adjacent beads is of the form $x^2 + 1$

Problem illustration

Define the potency of a magic bracelet to the sum of numbers on its beads.

The example is a magic bracelet with five beads which has a potency of $155$.

Let $F(N)$ be the sum of the potency of each magic bracelet which can be formed using positive integers not exceeding $N$, where rotations and reflections of an arrangement are considered equivalent. You are given $F(20) = 258$ and $F(10^2) = 53876$.

Find $F(10^6)$.

Problem 846: Magic Bracelets

Mathematical Analysis

Characterizing Valid Adjacencies

Two numbers aa and bb can be adjacent if and only if ab=x2+1ab = x^2 + 1 for some non-negative integer xx. This means ab1(mod4)ab \equiv 1 \pmod{4} or ab=1,2ab = 1, 2.

We need to build a graph where vertices are the valid bead numbers (1,2,pk,2pk1, 2, p^k, 2p^k for odd primes pp) up to NN, and edges connect pairs whose product has the form x2+1x^2 + 1.

A number mm can be written as x2+1x^2 + 1 if and only if in the prime factorization of mm, every prime p3(mod4)p \equiv 3 \pmod{4} appears to an even power. This is because x21(modp)x^2 \equiv -1 \pmod{p} has a solution iff p=2p = 2 or p1(mod4)p \equiv 1 \pmod{4}.

Graph Construction

For each pair of valid numbers (a,b)(a,b) with aba \neq b and a,bNa,b \leq N, we check if abab can be represented as x2+1x^2 + 1. This is equivalent to checking that ab1ab - 1 is a perfect square… but more precisely, we need abab to be representable as x2+1x^2 + 1.

Cycle Enumeration via Burnside’s Lemma

Since bracelets are equivalence classes of cycles under the dihedral group, we need to count cycles in the graph and apply Burnside’s lemma. For a cycle of length nn, the number of distinct bracelets is the number of distinct cycles divided by 2n2n (accounting for nn rotations and nn reflections).

The sum of potencies over all bracelets equals the sum over all valid cycles of their vertex sums, divided by 2n2n for each cycle of length nn.

Editorial

A bracelet uses beads with values in {1, 2, p^k, 2p^k} for odd primes p. Two adjacent beads a,b must satisfy: ab = x^2 + 1 for some integer x. All beads distinct, bracelet length >= 3. F(N) = sum of potencies of all magic bracelets using values <= N. We build the adjacency graph on valid numbers up to NN. We then enumerate all simple cycles of length 3\geq 3. Finally, iterate over each cycle of length nn, add (sum of vertices) / 2n2n to the total (since each cycle is counted 2n2n times by rotations and reflections).

Pseudocode

Build the adjacency graph on valid numbers up to $N$
Enumerate all simple cycles of length $\geq 3$
For each cycle of length $n$, add (sum of vertices) / $2n$ to the total (since each cycle is counted $2n$ times by rotations and reflections)

Complexity Analysis

The main bottleneck is cycle enumeration on the adjacency graph. The graph is relatively sparse for the constraint ab=x2+1ab = x^2 + 1, making enumeration feasible.

Answer

9851175623\boxed{9851175623}

Code

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

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

/*
 * Problem 846: Magic Bracelets
 *
 * A bracelet uses beads with values in {1, 2, p^k, 2p^k} for odd primes p.
 * Two adjacent beads a,b must satisfy: ab = x^2 + 1 for some integer x.
 * All beads are distinct. Bracelet length >= 3.
 * F(N) = sum of potencies of all magic bracelets using values <= N.
 * Rotations and reflections are equivalent.
 *
 * We build a graph and enumerate simple cycles.
 */

typedef long long ll;

// Check if n is of the form x^2 + 1
bool is_sum_sq_plus_one(ll n) {
    if (n < 1) return false;
    ll x = (ll)sqrt((double)(n - 1));
    for (ll t = max(0LL, x - 2); t <= x + 2; t++) {
        if (t * t + 1 == n) return true;
    }
    return false;
}

// Check if n is a valid bead value: 1, 2, p^k, or 2p^k for odd prime p
bool is_valid_bead(int n) {
    if (n == 1 || n == 2) return true;
    int m = n;
    int factor_of_2 = 0;
    while (m % 2 == 0) { m /= 2; factor_of_2++; }
    if (factor_of_2 > 1) return false;
    // m must be a prime power p^k with p odd prime
    if (m == 1) return false; // n was a power of 2 > 2
    // Find the smallest prime factor
    int p = 0;
    for (int i = 3; (ll)i * i <= m; i += 2) {
        if (m % i == 0) { p = i; break; }
    }
    if (p == 0) return true; // m is prime
    // Check m is a power of p
    while (m % p == 0) m /= p;
    return m == 1;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    const int N = 1000000;

    // Generate valid bead values
    vector<int> beads;
    for (int i = 1; i <= N; i++) {
        if (is_valid_bead(i)) {
            beads.push_back(i);
        }
    }

    int sz = beads.size();
    // Map bead value to index
    unordered_map<int, int> bead_idx;
    for (int i = 0; i < sz; i++) {
        bead_idx[beads[i]] = i;
    }

    // Build adjacency list
    vector<vector<int>> adj(sz);
    for (int i = 0; i < sz; i++) {
        for (int j = i + 1; j < sz; j++) {
            ll prod = (ll)beads[i] * beads[j];
            if (is_sum_sq_plus_one(prod)) {
                adj[i].push_back(j);
                adj[j].push_back(i);
            }
        }
    }

    // Enumerate all simple cycles of length >= 3
    // For each cycle, add potency / (2 * length) to the answer
    // Use DFS from the smallest index in cycle to avoid counting duplicates

    ll total = 0;
    int max_depth = sz; // practical limit

    // For each starting vertex, find cycles where start is the minimum index
    vector<bool> visited(sz, false);

    function<void(int, int, int, ll, int)> dfs = [&](int start, int cur, int depth, ll path_sum, int prev) {
        for (int next : adj[cur]) {
            if (next < start) continue; // ensure start is minimum
            if (next == start && depth >= 3) {
                // Found a cycle of length depth
                // Each undirected cycle is found twice (two directions),
                // but since we fix start as minimum, we find each cycle exactly twice
                // (clockwise and counterclockwise)
                // We need to divide by 2*depth for bracelets,
                // but we find each directed cycle once with start fixed as min,
                // so we find 2 directed versions -> divide by 2 to get 1 bracelet contribution
                // Then the bracelet potency is path_sum
                total += path_sum;
                continue;
            }
            if (visited[next] || next == start) continue;
            visited[next] = true;
            dfs(start, next, depth + 1, path_sum + beads[next], cur);
            visited[next] = false;
        }
    };

    for (int s = 0; s < sz; s++) {
        visited[s] = true;
        dfs(s, s, 1, beads[s], -1);
        visited[s] = false;
    }

    // total counts each bracelet exactly twice (two traversal directions with fixed min start)
    // Divide by 2
    total /= 2;

    cout << total << endl;

    return 0;
}