All Euler problems
Project Euler

Standing on the Shoulders of Trolls

N trolls are trapped in a hole of depth D_N cm. Each troll n (0 <= n < N) has shoulder height h_n, arm length l_n, and IQ (Irascibility Quotient) q_n, generated by: r_n = [(5^n mod (10^9+7)) mod 10...

Source sync Apr 19, 2026
Problem #0732
Level Level 32
Solved By 261
Languages C++, Python
Answer 45609
Length 461 words
dynamic_programminggreedymodular_arithmetic

Problem Statement

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

$N$ trolls are in a hole that is $D_N$ cm deep. The $n$-th troll is characterized by:

  • the distance from his feet to his shoulders in cm, $h_n$

  • the length of his arms in cm, $l_n$

  • his IQ (Irascibility Quotient), $q_n$.

Trolls can pile up on top of each other, with each troll standing on the shoulders of the one below him. A troll can climb out of the hole and escape if his hands can reach to the surface. Once a troll escapes he cannot participate any further in the escaping effort.

The trolls execute an optimal strategy for maximizing the total IQ of the escaping trolls, defined as $Q(N)$.

Let \begin{align*} r_n &= \left[ \left( 5^n \bmod (10^9 + 7) \right) \bmod 101 \right] + 50 \\ h_n &= r_{3n} \\ l_n &= r_{3n + 1} \\ q_n &= r_{3n + 2} \\ D_N &= \frac{1}{\sqrt{2}} \displaystyle \sum_{n=0}^{N-1} h_n \end{align*} For example, the first troll ($n=0$) is 51cm tall to his shoulders, has 55cm long arms, and has an IQ of 75.

You are given that $Q(5) = 401$ and $Q(15)=941$.

Find $Q(1000)$.

Problem 732: Standing on the Shoulders of Trolls

Mathematical Foundation

Lemma 1 (Escape Condition). A troll ii standing on top of a pile of total shoulder height HH can escape if and only if H+liDNH + l_i \ge D_N. After troll ii escapes, the remaining pile height is HhiH - h_i.

Proof. Troll ii stands on the shoulders of the troll below it, so its feet are at height HhiH - h_i and its shoulders are at height HH. Its hands reach H+liH + l_i. The troll escapes if H+liDNH + l_i \ge D_N. When it leaves the pile, the pile loses hih_i in height. \square

Theorem 1 (Optimal Escape Ordering). Let SS be a set of trolls that can all escape from an initial pile of non-escapees. The optimal order in which trolls escape is by non-decreasing hih_i: the troll with the smallest shoulder height escapes first.

Proof. Suppose trolls ii and jj are both escapable, with hi<hjh_i < h_j, and jj escapes before ii. After jj escapes, the pile height drops by hjh_j. For ii to still escape, we need Hhj+liDNH - h_j + l_i \ge D_N. Had ii escaped first instead, the pile drops by hi<hjh_i < h_j, leaving more height for jj: Hhi+ljDNH - h_i + l_j \ge D_N is easier to satisfy. So escaping the shorter troll first never makes things worse and can make them strictly better. By an exchange argument, sorting by non-decreasing hih_i is optimal. \square

Theorem 2 (DP Formulation). Let the trolls be sorted by non-decreasing hih_i. Define the total shoulder height Htotal=n=0N1hnH_{\text{total}} = \sum_{n=0}^{N-1} h_n. Process trolls in order of decreasing hih_i. For each troll, decide: (a) it stays in the pile (contributing hih_i to the pile), or (b) it escapes (contributing qiq_i to the IQ total). The constraint for escape of troll ii (the mm-th troll to escape, with current pile height HH) is H+liDNH + l_i \ge D_N. This yields a knapsack-like DP on the pile height.

Proof. By Theorem 1, the escape order is fixed once the escape set is chosen. Processing trolls from largest hh to smallest, we greedily decide membership. At each step, the pile height HH is the sum of hjh_j for all trolls designated as non-escapees so far. The DP state is HH, and transitions are: include troll ii in the pile (HH+hiH \gets H + h_i) or let it escape if H+liDNH + l_i \ge D_N, adding qiq_i to total IQ. The optimal solution maximizes total IQ subject to the sequential escape feasibility. \square

Editorial

N trolls in a hole of depth D. Maximize total IQ of escapees. A troll can escape from a pile of height H if H + l_i >= D. After escaping, pile height decreases by h_i. We generate troll parameters. We then sort trolls by h in non-decreasing order. Finally, we process the trolls in reverse order with dynamic programming.

Pseudocode

Generate troll parameters
Sort trolls by h in non-decreasing order
DP: process in reverse order (largest h first)
State: pile height H (discretized)
For each troll: pile it or escape it
for each state H in dp
Option 1: troll i stays in pile
Option 2: troll i escapes (if feasible)

Complexity Analysis

  • Time: O(NHmax)O(N \cdot H_{\max}) where Hmax=hi100NH_{\max} = \sum h_i \approx 100N, so O(N2100)=O(100N2)O(N^2 \cdot 100) = O(100\,N^2). For N=1000N = 1000, this is 108\sim 10^8 operations.
  • Space: O(Hmax)=O(100N)O(H_{\max}) = O(100N) for the DP table.

Answer

45609\boxed{45609}

Code

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

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

/*
 * Problem 732: Standing on the Shoulders of Trolls
 *
 * N trolls in hole of depth D. Maximize total IQ of trolls that escape.
 * Troll can escape from pile of height H if H + l_i >= D.
 * Greedy: repeatedly escape highest-IQ troll that can reach surface.
 */

const long long MOD_GEN = 1000000007LL;

int main() {
    int N = 1000;
    // Generate parameters
    vector<long long> r(3*N+3);
    r[0] = 1;
    for (int i = 1; i < 3*N+3; i++)
        r[i] = r[i-1] * 5 % MOD_GEN;
    for (int i = 0; i < 3*N+3; i++)
        r[i] = r[i] % 101 + 50;

    vector<int> h(N), l(N), q(N);
    double total_h = 0;
    for (int n = 0; n < N; n++) {
        h[n] = r[3*n]; l[n] = r[3*n+1]; q[n] = r[3*n+2];
        total_h += h[n];
    }
    double D = total_h / sqrt(2.0);

    // Greedy escape
    vector<bool> escaped(N, false);
    double pile_h = total_h;
    int total_iq = 0;

    while (true) {
        int best = -1, best_q = -1;
        for (int i = 0; i < N; i++) {
            if (escaped[i]) continue;
            if (pile_h + l[i] >= D - 0.001 && q[i] > best_q) {
                best_q = q[i];
                best = i;
            }
        }
        if (best == -1) break;
        escaped[best] = true;
        pile_h -= h[best];
        total_iq += best_q;
    }

    printf("Q(%d) = %d\n", N, total_iq);
    return 0;
}