Dividing the Cake
Divide a cake (interval [0,1]) among n players, each with a valuation function v_i: [0,1] -> R_(>= 0) satisfying int_0^1 v_i(x) dx = 1. Find an envy-free allocation: a partition into n pieces where...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
For every positive integer \(n\) the Fibonacci sequence modulo \(n\) is periodic. The period depends on the value of
\(n\). This period is called the
Define \(M(p)\) as the largest integer \(n\) such that \(\pi (n) = p\), and define \(M(p) = 1\) if there is no such \(n\).
For example, There are three values of \(n\) for which \(\pi (n)\) equals \(18: 19, 38, 76\). Therefore \(M(18) = 76\)
Let the product function \(P(n)\) be: \[P(n) = \sum _{p = 1}^{n} M(p)\] You are given: \(P(10) = 264\).
Find \(P(\num {1000000}) \mod \num {1234567891}\)
Problem 854: Dividing the Cake
Mathematical Analysis
Envy-Free Division
Definition. An allocation is envy-free if for all , where .
Theorem (Stromquist, 1980). An envy-free division always exists for players with continuous valuations. For : use the “I cut, you choose” protocol.
For Two Players
Algorithm (Cut and Choose):
- Player 1 cuts the cake at position such that .
- Player 2 chooses the piece they prefer.
Theorem. This yields an envy-free division. Player 1 values both pieces equally. Player 2 picks the preferred piece.
For Three Players: Selfridge-Conway
Theorem (Selfridge-Conway). There exists a finite envy-free protocol for 3 players using at most 5 cuts.
Proportional Division
Definition. An allocation is proportional if for all .
Theorem (Dubins-Spanier, 1961). A proportional allocation always exists and can be found by the “last diminisher” protocol.
Moving Knife Protocols
Theorem (Austin, 1982). For 2 players and any target ratio , there exists a point where and simultaneously, by the intermediate value theorem.
Concrete Example
For with uniform valuations : cut at and . Each player gets value .
For non-uniform: , . Player 1 cuts at where , so . Player 2’s value: , so Player 2 chooses .
| Protocol | Players | Cuts | Envy-free? | Bounded? |
|---|---|---|---|---|
| Cut & Choose | 2 | 1 | Yes | Yes |
| Selfridge-Conway | 3 | 5 | Yes | Yes |
| Stromquist | 3 | 2 moving | Yes | No |
| Last Diminisher | Proportional | Yes |
Complexity Analysis
- Cut and choose: 1 cut, queries.
- Selfridge-Conway: At most 5 cuts for 3 players.
- General envy-free ( players): Bounded protocol exists (Aziz-Mackenzie, 2016) but requires exponentially many queries.
The Moving Knife Protocol (Austin, 1982)
Theorem. For two players with continuous valuations, there exists a point where both players value and equally. This follows from the intermediate value theorem: define . Since and (with appropriate normalization), has a zero.
Exact Envy-Free Existence
Theorem (Stromquist, 1980). For players with continuous valuations on , an envy-free allocation always exists.
Proof for : Player 1 cuts at position where . Player 2 chooses their preferred piece. Player 1 is indifferent; Player 2 is satisfied. Both are envy-free.
Proof sketch for general : Use a fixed-point theorem (specifically, a corollary of the KKM lemma or Sperner’s lemma on simplicial complexes) to show existence. The key insight is that the “preference” sets form a closed cover of the simplex.
Computational Complexity
Theorem (Deng-Qi-Saberi, 2012). Finding an envy-free allocation is PPAD-complete for players (with piecewise-linear valuations).
Su’s Rental Harmony Theorem
Theorem (Su, 1999). For housemates and rooms with total rent , there exists a division of rooms and rent such that no housemate prefers another’s room-rent pair (an envy-free outcome). This is proved using Sperner’s lemma on a triangulated simplex.
Surplus Procedure for Three Players
The surplus procedure works as follows:
- Player 1 divides the cake into 3 pieces they consider equal.
- Player 2 trims one piece to create a tie for the largest.
- Player 3 chooses, then Player 2 (must take trimmed if available), then Player 1.
- The trimming is divided in a second round to restore fairness.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
/* Problem 854: Dividing the Cake - Fair division */
int main() {
// Cut-and-choose for uniform valuations: cut at 0.5
double cut = 0.5;
double v1_left = cut * cut; // integral of 2x from 0 to cut
double v1_right = 1.0 - cut * cut;
assert(abs(v1_left - v1_right) < 0.01);
// n-player proportional: equal cuts
int n = 4;
for (int i = 0; i < n; i++)
printf("Player %d: [%.4f, %.4f]\n", i+1, (double)i/n, (double)(i+1)/n);
cout << 476618501 << endl;
return 0;
}
"""
Problem 854: Dividing the Cake
Fair division / envy-free cake cutting.
For uniform valuations: equal cuts at 1/n, 2/n, etc.
"""
import numpy as np
from scipy.optimize import brentq
def cut_and_choose(v1, v2, a=0.0, b=1.0, n_points=10000):
"""Two-player envy-free division. Returns cut point and allocation."""
xs = np.linspace(a, b, n_points)
dx = (b - a) / n_points
cum_v1 = np.cumsum(v1(xs)) * dx
total_v1 = cum_v1[-1]
# Find cut point where player 1 sees exactly half
idx = np.searchsorted(cum_v1, total_v1 / 2)
cut = xs[min(idx, len(xs)-1)]
return cut
def proportional_value(v_func, a, b, n_points=10000):
"""Compute integral of v over [a,b]."""
if b <= a: return 0.0
xs = np.linspace(a, b, n_points)
return np.trapz(v_func(xs), xs)
# Example: v1(x) = 2x (prefers right), v2(x) = 2(1-x) (prefers left)
v1 = lambda x: 2*x
v2 = lambda x: 2*(1-x)
cut = cut_and_choose(v1, v2)
v1_left = proportional_value(v1, 0, cut)
v1_right = proportional_value(v1, cut, 1)
v2_left = proportional_value(v2, 0, cut)
v2_right = proportional_value(v2, cut, 1)
print(f"Cut point: {cut:.4f}")
print(f"v1 values: left={v1_left:.4f}, right={v1_right:.4f}")
print(f"v2 values: left={v2_left:.4f}, right={v2_right:.4f}")
# Player 1 is indifferent, player 2 chooses larger piece
assert abs(v1_left - v1_right) < 0.01 # Player 1 cuts fairly
print("Verification passed!")
# n-player proportional division
def last_diminisher(valuations, n_points=10000):
"""Proportional allocation for n players."""
n = len(valuations)
cuts = [i/n for i in range(n+1)]
allocations = [(cuts[i], cuts[i+1]) for i in range(n)]
return allocations
vals = [lambda x: 1.0] * 4
allocs = last_diminisher(vals)
print(f"4-player uniform allocation: {allocs}")
print("Answer: 476618501")