C. Fair Division
After sailing the Seven Seas and raiding many ships, Cap’n Red and his crew of fellow pirates are finally ready to divide their loot. According to ancient traditions, the crew stands in a circle ordered by a strict pirate hierarchy. Cap’n Red starts by taki...
Problem Statement
Formatted from the contest statement text, with sample tests broken out into copyable blocks.
After sailing the Seven Seas and raiding many ships, Cap’n Red and his crew of fellow pirates are finally ready to divide their loot. According to ancient traditions, the crew stands in a circle ordered by a strict pirate hierarchy. Cap’n Red starts by taking a fraction f of the loot and passing the remainder on to the next pirate. That pirate takes the same fraction f of the loot left over by the previous pirate and passes the remainder on to the following pirate. Each pirate behaves in the same way, taking a fraction f of what is left and passing on the rest. The last pirate in the hierarchy passes the remainder on to Cap’n Red, who starts another round of this “fair” division, and so on, indefinitely. Fortunately, pirates in the 21st century can use a computer to avoid this Image by ZedH at Pixabay lengthy process and constant nitpicking when the fraction f does not ex- actly divide the loot at some step. You have been captured by the pirates and asked to come up with a suitable fraction f . As an incentive, Cap’n Red has promised to leave you alive if you succeed. The fraction f needs to be a rational number strictly between 0 and 1. It is not necessary that f exactly divides the loot remaining at any step of the round-robin process described above. However, the total loot that would be assigned to each pirate by carrying out this process infinitely needs to be an integer.
Input
The input contains one line with two integers n and m, where n (6 ≤ n ≤ 106 ) is the number of pirates including Cap’n Red and m (1 ≤ m ≤ 1018 ) is the total value of their loot.
Output
Output one line with two positive integers p and q, where f = pq as specified above. If there are multiple suitable fractions, choose one with the smallest q. Among multiple suitable fractions with the same smallest q choose the one with the smallest p. If there is no suitable fraction, output impossible instead and hope for mercy.
Sample Tests
8 51000 1 2 6 91000 2 3 10 1000000000000000000 impossible Editorial
The solution write-up is rendered from the LaTeX source, with equations kept live through MathJax.
From Infinite Process to Integer Geometric Progression
Let \[ r = 1 - f. \] If the total loot is $m$, then pirate $i$ receives \[ m \cdot f \cdot r^i \] in the first round, then the same amount multiplied by $r^n$ in the next round, and so on. Therefore the total share of pirate $i$ is \[ x_i = m \cdot \frac{f r^i}{1-r^n}. \]
So the pirates' final shares form a geometric progression: \[ x_{i+1} = r x_i. \] The problem is equivalent to asking for integer values \[ x_0, x_1, \dots, x_{n-1} \] with common ratio $r \in (0,1)$ and total sum $m$.
Lowest-Term Form
Write \[ r = \frac{a}{q} \] in lowest terms, where $1 \le a < q$ and $\gcd(a,q)=1$. Then every share has the form \[ x_i = y \cdot q^{n-1-i} a^i \] for some positive integer $y$. Indeed, the denominators force the first term to contain a factor $q^{n-1}$, and after that all terms are integral automatically.
Summing the progression gives \[ m = y \sum_{i=0}^{n-1} q^{n-1-i} a^i = y \cdot D(q,a), \] where \[ D(q,a) = q^{n-1} + q^{n-2}a + \cdots + a^{n-1}. \]
Therefore a fraction is valid exactly when \[ D(q,a) \mid m. \]
Since \[ f = 1-r = \frac{q-a}{q}, \] the output numerator is \[ p = q-a. \] Because $\gcd(a,q)=1$, we also have $\gcd(p,q)=1$, so this denominator is already minimal for that choice.
Search Strategy
We search denominators $q=2,3,4,\dots$ in increasing order. For a fixed $q$, we try numerators $p=1,2,\dots,q-1$ in increasing order, which is exactly the required tie-break order.
For one candidate:
the remainder ratio is $a = q-p$;
the candidate works iff $\gcd(p,q)=1$ and $D(q,a)$ divides $m$.
The smallest possible value of $D(q,a)$ for this denominator happens when $a=1$, namely \[ 1 + q + q^2 + \cdots + q^{n-1}. \] Once even this minimum exceeds $m$, no larger denominator can work and the search stops.
Useful Bound
The absolute smallest divisor over all valid fractions occurs at $q=2$ and $a=1$, which gives \[ 2^n - 1. \] If $n \ge 60$, then \[ 2^n - 1 > 10^{18} \ge m, \] so no solution exists at all. This removes the large-$n$ cases immediately.
Algorithm
If $n \ge 60$, output
impossible.For $q = 2,3,\dots$:
compute $D(q,1)$; if it already exceeds $m$, stop and output
impossible;for each $p=1,2,\dots,q-1$:
skip it if $\gcd(p,q) \ne 1$;
let $a=q-p$;
compute $D(q,a)$ with overflow capping at $m+1$;
if $D(q,a)$ divides $m$, output $p$ and $q$.
enumerate
To evaluate \[ D(q,a) = q^{n-1} + q^{n-2}a + \cdots + a^{n-1}, \] we use the recurrence \[ S_1 = 1, \qquad S_{k+1} = qS_k + a^k. \] This avoids separate exponentiation.
Correctness Proof
We prove that the algorithm returns the required fraction whenever one exists.
Lemma 1.
If the final shares are integers, then they form an integer geometric progression with ratio $r=1-f$.
Proof.
Pirate $i$ receives a fraction $f$ of the amount arriving at their position in every round. Between pirate $i$ and pirate $i+1$, the remaining loot is multiplied by $r=1-f$. Therefore every contribution to pirate $i+1$ is exactly $r$ times the corresponding contribution to pirate $i$, and summing over all rounds gives $x_{i+1}=r x_i$. □
Lemma 2.
Let $r=\frac{a}{q}$ be in lowest terms. There exists a valid division if and only if $D(q,a)$ divides $m$.
Proof.
Suppose a valid division exists. By Lemma 1, the shares are an integer geometric progression with ratio $\frac{a}{q}$. Because $\gcd(a,q)=1$, integrality forces the first term to be a multiple of $q^{n-1}$, so the progression has the form \[ y q^{n-1},\; y q^{n-2}a,\; \dots,\; y a^{n-1} \] for some positive integer $y$. Summing yields $m = y D(q,a)$, so $D(q,a)\mid m$.
Conversely, if $D(q,a)\mid m$, let $y = \frac{m}{D(q,a)}$ and define \[ x_i = y q^{n-1-i} a^i. \] These are integers, their ratio is $\frac{a}{q}$, and their sum is exactly $m$. Taking $f = 1-\frac{a}{q} = \frac{q-a}{q}$ produces exactly those total shares. □
Lemma 3.
For a fixed denominator $q$, checking $p=1,2,\dots,q-1$ in increasing order finds the correct tie-break winner for that denominator.
Proof.
The output fraction is $f=\frac{p}{q}$, and the statement asks for the smallest numerator among equal denominators. The loop checks these numerators in exactly that order and stops at the first valid one. □
Lemma 4.
If $D(q,1) > m$, then no denominator larger than $q$ can be valid.
Proof.
For fixed $q$, the smallest possible remainder numerator is $a=1$, which minimizes $D(q,a)$. Also $D(q,1)$ increases with $q$. Therefore if the minimum value for this denominator already exceeds $m$, then every candidate with denominator at least $q$ has divisor larger than $m$ and cannot divide $m$. □
Theorem.
The algorithm outputs
impossibleexactly when no suitable fraction exists; otherwise it outputs the valid fraction with smallest denominator, and among those, smallest numerator.Proof.
By Lemma 2, a candidate fraction is valid exactly when the algorithm's divisibility test succeeds. By Lemma 4, once the outer loop stops, no unseen denominator can work. Since denominators are tested in increasing order and, for each denominator, numerators are tested in increasing order, the first valid fraction found is exactly the one required by the problem. If no candidate is found before the stopping condition, then no valid fraction exists. □
Complexity Analysis
If $n \ge 60$, the answer is immediate.
Otherwise, every candidate evaluation takes $O(n)$ time, and the outer search stops quickly because $D(q,1)$ grows as a degree-$(n-1)$ polynomial in $q$. The memory usage is $O(1)$.
Implementation Notes
The recurrence for $D(q,a)$ is evaluated with
__int128and capped at $m+1$ to avoid overflow.Because $\gcd(q-a,q)=\gcd(a,q)$, checking $\gcd(p,q)=1$ is enough.
Code
C++ solution used for this page.
#include <bits/stdc++.h>
using namespace std;
namespace {
long long n;
long long m;
long long gcd_ll(long long a, long long b) {
while (b != 0) {
long long r = a % b;
a = b;
b = r;
}
return a;
}
long long capped_mul(long long a, long long b, long long cap) {
if (a == 0 || b == 0) {
return 0;
}
if (a > cap / b) {
return cap + 1;
}
return a * b;
}
long long capped_divisor(long long q, long long rem_num, long long rounds, long long cap) {
long long sum = 1;
long long power = 1;
for (long long i = 1; i < rounds; ++i) {
power = capped_mul(power, rem_num, cap);
if (power > cap) {
return cap + 1;
}
long long scaled = capped_mul(sum, q, cap);
if (scaled > cap || scaled > cap - power) {
return cap + 1;
}
sum = scaled + power;
}
return sum;
}
void solve() {
cin >> n >> m;
if (n >= 60) {
cout << "impossible\n";
return;
}
for (long long q = 2;; ++q) {
long long smallest_divisor = capped_divisor(q, 1, n, m);
if (smallest_divisor > m) {
break;
}
for (long long p = 1; p < q; ++p) {
if (gcd_ll(p, q) != 1) {
continue;
}
long long rem_num = q - p;
long long divisor = capped_divisor(q, rem_num, n, m);
if (divisor <= m && m % divisor == 0) {
cout << p << ' ' << q << '\n';
return;
}
}
}
cout << "impossible\n";
}
} // namespace
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}
Source Files and Assets
Raw files are still available here when you want the original TeX, C++, or statement assets.
Show raw files
competitive_programming/icpc/2021/C-fair-division/solution.texC++ implementationcompetitive_programming/icpc/2021/C-fair-division/solution.cppStatement textcompetitive_programming/icpc/2021/C-fair-division/statement.txtStatement PDFcompetitive_programming/icpc/2021/C-fair-division/statement.pdfMetadatacompetitive_programming/icpc/2021/C-fair-division/meta.jsonYear packetcompetitive_programming/icpc/2021/contest_problems.pdf