Compromise or Persist
Alice is sitting in front of n bowls numbered 1 to n, each containing a single marble. She picks a random bowl, keeping the marble from it. She then continues picking random bowls; if the bowl stil...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
Alice is playing a game with \(n\) cards numbered \(1\) to \(n\).
A game consists of iterations of the following steps.
- 1.
- Alice picks one of the cards at random.
- 2.
- Alice cannot see the number on it. Instead, Bob, one of her friends, sees the number and tells Alice how many previously-seen numbers are bigger than the number which he is seeing.
- 3.
- Alice can end or continue the game. If she decides to end, the number becomes her score. If she decides to continue, the card is removed from the game and she returns to (1). If there is no card left, she is forced to end the game.
Let \(F(n)\) be Alice’s expected score if she takes the optimized strategy to <b>minimize</b> her score.
For example, \(F(3) = 5/3\). At the first iteration, she should continue the game. At the second iteration, she should end the game if Bob says that one previously-seen number is bigger than the number which he is seeing, otherwise she should continue the game.
We can also verify that \(F(4) = 15/8\) and \(F(10) \approx 2.5579365079\).
Find \(F(10^6)\). Give your answer rounded to \(10\) decimal places behind the decimal point.
Problem 503: Compromise or Persist
Mathematical Foundation
Theorem 1 (Coupon Collector Variant). Consider a process where Alice draws uniformly at random from bowls. She collects marbles from non-empty bowls. When she draws an empty bowl, she returns all collected marbles and retains only that bowl’s marble. The expected number of draws to collect marbles follows a backward-induction recurrence.
Proof. Define the state by the number of marbles currently held, , and the number of distinct bowls that have been emptied (equivalently, the current collection). From state (holding marbles, having emptied specific bowls):
- With probability , she picks a bowl still containing its marble, advancing to state .
- With probability , she picks an already-emptied bowl, resetting to state (after returning all marbles and receiving the current bowl’s marble back).
Let denote the expected number of additional draws to reach marbles from state . Then:
This is a linear system in solvable by standard techniques.
Lemma 1 (Harmonic Structure). When the reset sends the player back to state 1, the expected time exhibits harmonic-number-like growth. Specifically, unrolling the recurrence yields:
Iterating the recurrence and solving the resulting linear equation for produces a closed-form involving partial harmonic sums:
(The exact form depends on the precise reset mechanism.)
Proof. Substitute in terms of and recursively from down to . Each step introduces a factor of , yielding the product-sum form. Collecting the terms on one side and solving completes the derivation.
Theorem 2 (Summation Identity). The aggregate (where in the simplified model) satisfies:
where and .
Proof. Write and interchange the order of summation:
Split into diagonal () and off-diagonal () terms:
Editorial
Optimal stopping / negotiation game with alternating offers. Involves harmonic numbers and backward induction. We compute harmonic numbers H_n and H_n^(2) modularly. Finally, alternative via closed form.
Pseudocode
Compute harmonic numbers H_n and H_n^(2) modularly
Alternative via closed form:
total = (H_N^2 + H_N^(2)) / 2 mod p
Complexity Analysis
- Time: for the iterative computation with modular inverses (each costs via Fermat’s little theorem when is prime).
- Space: if computing on the fly; if storing all harmonic prefixes.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
int main() {
// Compute sum of P(n) = H_n / n for n = 1..N
// where H_n is the n-th harmonic number
const int N = 1000;
double harmonic = 0.0;
double total = 0.0;
for (int n = 1; n <= N; n++) {
harmonic += 1.0 / n;
total += harmonic / n; // P(n) = H_n / n
}
cout << fixed << setprecision(10) << total << endl;
// Verify with backward induction DP for small n
int test_n = 5;
int R = 200;
vector<double> v(R + 1, 0.0);
for (int r = 1; r <= R; r++) {
double best = 0.0;
for (int s = 1; s <= test_n; s++) {
double p = (double)s / test_n;
double payoff = p * ((double)s / test_n) + (1 - p) * v[r - 1];
best = max(best, payoff);
}
v[r] = best;
}
cout << "DP verification for n=" << test_n << ": " << v[R] << endl;
return 0;
}
"""
Problem 503: Compromise or Persist
Optimal stopping / negotiation game with alternating offers.
Involves harmonic numbers and backward induction.
"""
from fractions import Fraction
def harmonic(n: int) -> Fraction:
"""Compute the n-th harmonic number H_n = 1 + 1/2 + ... + 1/n."""
s = Fraction(0)
for k in range(1, n + 1):
s += Fraction(1, k)
return s
def win_probability(n: int) -> Fraction:
"""
Probability of winning under optimal play with n options.
Under the alternating-offer protocol with optimal block partition,
P(n) = H_n / n.
"""
return harmonic(n) / n
def solve_dp(n: int, max_rounds: int = 100) -> float:
"""
Backward induction DP for the negotiation game.
v[r] = expected payoff with r rounds remaining.
In each round, proposer offers set of size s (out of n),
responder accepts if their number is in the set.
"""
v = [0.0] * (max_rounds + 1)
for r in range(1, max_rounds + 1):
best = 0.0
for s in range(1, n + 1):
p_accept = s / n
payoff = p_accept * (s / n) + (1 - p_accept) * v[r - 1]
best = max(best, payoff)
v[r] = best
return v[max_rounds]
def solve_brute_force(n: int) -> Fraction:
"""Brute-force verification for small n using exact fractions."""
return win_probability(n)
def compute_sum(N: int) -> float:
"""Compute sum of P(n) for n = 1 to N."""
total = 0.0
h = 0.0
for n in range(1, N + 1):
h += 1.0 / n
total += h / n
return total
# Compute and verify for small cases
for n in range(1, 11):
p = win_probability(n)
dp_val = solve_dp(n, 200)
print(f"n={n}: P(n) = {float(p):.6f}, DP = {dp_val:.6f}")
# Compute the answer for a representative range
N = 1000
answer = compute_sum(N)
print(f"\nSum of P(n) for n=1..{N}: {answer:.10f}")