Problem 728: Circle of Coins
View on Project EulerProject Euler Problem 728 Solution
EulerSolve provides an optimized solution for Project Euler Problem 728, Circle of Coins, with C++, Python, Java, and a step-by-step mathematical explanation.
Problem Summary For each pair \((n,k)\) with \(1 \le k \le n\), the circle-of-coins problem has a counting function \(F(n,k)\) for the admissible binary coin configurations associated with that pair. The overall task is to evaluate $S(N)=\sum_{n=1}^{N}\sum_{k=1}^{n} F(n,k)\pmod{10^9+7}.$ The key point in the implementations is that the combinatorics collapse to arithmetic data: only \(\gcd(n,k)\), the exponent of \(2\) dividing \(n\) and \(k\), and a totient-based regrouping are needed. That removes any need to enumerate coin states directly. Mathematical Approach The C++, Python, and Java implementations all use the same arithmetic decomposition. Once the fixed-pair formula is known, the remaining work is to reorganize the double sum so that equal contributions are collected together efficiently. Step 1: Closed Form for a Fixed Pair Let $g=\gcd(n,k),$ and let \(v_2(x)\) denote the exponent of \(2\) in \(x\). The implementations use the closed form $F(n,k)=\begin{cases} 2^{n-g+1}, & v_2(k)\le v_2(n),\\ 2^{n-g}, & v_2(k)>v_2(n). \end{cases}$ So the entire dependence on the original circle is compressed into two quantities: the common divisor \(g\), which controls the main exponent \(n-g\), and a single parity-sensitive comparison of 2-adic valuations, which decides whether there is one extra factor of \(2\)....
Detailed mathematical approach
Problem Summary
For each pair \((n,k)\) with \(1 \le k \le n\), the circle-of-coins problem has a counting function \(F(n,k)\) for the admissible binary coin configurations associated with that pair. The overall task is to evaluate
$S(N)=\sum_{n=1}^{N}\sum_{k=1}^{n} F(n,k)\pmod{10^9+7}.$
The key point in the implementations is that the combinatorics collapse to arithmetic data: only \(\gcd(n,k)\), the exponent of \(2\) dividing \(n\) and \(k\), and a totient-based regrouping are needed. That removes any need to enumerate coin states directly.
Mathematical Approach
The C++, Python, and Java implementations all use the same arithmetic decomposition. Once the fixed-pair formula is known, the remaining work is to reorganize the double sum so that equal contributions are collected together efficiently.
Step 1: Closed Form for a Fixed Pair
Let
$g=\gcd(n,k),$
and let \(v_2(x)\) denote the exponent of \(2\) in \(x\). The implementations use the closed form
$F(n,k)=\begin{cases} 2^{n-g+1}, & v_2(k)\le v_2(n),\\ 2^{n-g}, & v_2(k)>v_2(n). \end{cases}$
So the entire dependence on the original circle is compressed into two quantities: the common divisor \(g\), which controls the main exponent \(n-g\), and a single parity-sensitive comparison of 2-adic valuations, which decides whether there is one extra factor of \(2\).
Step 2: Separate the GCD from the Reduced Step
Write
$n=t h,\qquad k=t r,\qquad t=\gcd(n,k),\qquad \gcd(r,h)=1.$
Then \(t\) is exactly the gcd that appears in the fixed-pair formula, so
$n-g=t h-t=t(h-1).$
After removing the common factor \(t\), every pair \((n,k)\) is described by a reduced denominator \(h\) and a reduced residue \(r\) coprime to \(h\). The formula becomes
$F(t h,t r)=\begin{cases} 2^{t(h-1)+1}, & v_2(r)\le v_2(h),\\ 2^{t(h-1)}, & v_2(r)>v_2(h). \end{cases}$
This shows that, for fixed \(h\) and \(t\), all dependence on the reduced step is packed into how many coprime residues \(r\) satisfy the valuation test.
Step 3: Count the Reduced Residues for Fixed \(h\)
Now fix \(h \ge 2\) and sum over all \(r\) with \(1 \le r \le h\) and \(\gcd(r,h)=1\).
If \(h\) is even, every residue coprime to \(h\) must be odd. Hence \(v_2(r)=0\le v_2(h)\), so every reduced residue contributes the larger value \(2^{t(h-1)+1}\). Since there are \(\varphi(h)\) such residues, their total contribution is
$\varphi(h)\cdot 2^{t(h-1)+1}=2\varphi(h)\,2^{t(h-1)}.$
If \(h\) is odd, the reduced residues split evenly into odd and even values. Indeed, for every reduced residue \(r\), the paired residue \(h-r\) is also reduced and has opposite parity. Therefore exactly half of the \(\varphi(h)\) residues satisfy \(v_2(r)=0=v_2(h)\), while the other half fail the inequality.
Step 4: Derive the Coefficient \(c(h)\)
From the parity split above, the total contribution for one fixed \(h \ge 2\) and one fixed \(t\) is
$c(h)\,2^{t(h-1)},$
where
$c(h)=\begin{cases} 2\varphi(h), & h \text{ even},\\ \dfrac{3\varphi(h)}{2}, & h \text{ odd}. \end{cases}$
The odd case is just
$\frac{\varphi(h)}{2}\cdot 2^{t(h-1)+1}+\frac{\varphi(h)}{2}\cdot 2^{t(h-1)} =\frac{3\varphi(h)}{2}\,2^{t(h-1)}.$
This is the crucial compression step: once pairs are grouped by \(h\), all the messy dependence on \(k\) is replaced by a single totient-based coefficient.
Step 5: Rebuild the Whole Sum
The case \(h=1\) is special. Then \(k=n\), so \(g=n\) and the fixed-pair formula gives \(F(n,n)=2\). Summed over \(n=1,\dots,N\), this contributes
$2N.$
For every \(h \ge 2\), the remaining parameter is \(t\), and the condition \(n=t h \le N\) means
$1\le t\le \left\lfloor\frac{N}{h}\right\rfloor.$
Therefore the full sum becomes
$\boxed{S(N)=2N+\sum_{h=2}^{N} c(h)\sum_{t=1}^{\lfloor N/h\rfloor} 2^{t(h-1)} \pmod{10^9+7}.}$
Mathematically the inner sum is a finite geometric progression, but the implementations simply step through its exponents directly after precomputing powers of \(2\).
Worked Example: \(N=3\)
The special term is
$2N=6.$
For \(h=2\), we have \(\varphi(2)=1\) and \(c(2)=2\). Also \(\lfloor 3/2\rfloor=1\), so this block contributes
$2\cdot 2^{1}=4.$
For \(h=3\), we have \(\varphi(3)=2\) and \(c(3)=3\). Also \(\lfloor 3/3\rfloor=1\), so this block contributes
$3\cdot 2^{2}=12.$
Hence
$S(3)=6+4+12=22,$
which matches the checkpoint used by the implementation. A single-pair checkpoint is \(F(9,3)=2^{9-3+1}=128\), because \(\gcd(9,3)=3\) and \(v_2(3)\le v_2(9)\).
How the Code Works
The implementations first build Euler's totient values for all integers up to \(N\) with a linear sieve. They also precompute the table
$2^0,2^1,\dots,2^N \pmod{10^9+7},$
so every power lookup in the main sum is constant time.
After that, the algorithm starts with the special contribution \(2N\). It then iterates through \(h=2,3,\dots,N\), computes the coefficient \(c(h)\) from the parity of \(h\) and the totient value, and adds
$c(h)\,2^{t(h-1)}$
for each \(t=1,\dots,\lfloor N/h\rfloor\). All arithmetic is reduced modulo \(10^9+7\) after each addition. The C++, Python, and Java implementations follow exactly the same mathematical plan; the C++ version also includes small checkpoint assertions before producing the final large-input result.
Complexity Analysis
The totient sieve runs in \(O(N)\) time and uses \(O(N)\) memory. The double summation over blocks costs
$\sum_{h=2}^{N}\left\lfloor\frac{N}{h}\right\rfloor=O(N\log N).$
Therefore the total running time is \(O(N\log N)\), while the memory usage remains \(O(N)\).
Footnotes and References
- Problem page: Project Euler 728 — Circle of Coins
- Greatest common divisor: Wikipedia — Greatest common divisor
- Euler's totient function: Wikipedia — Euler's totient function
- \(p\)-adic valuation, including the special case \(v_2\): Wikipedia — \(p\)-adic valuation
- Geometric progression: Wikipedia — Geometric progression