"Like [problem 71](https://projecteuler.net/problem=71), we're looking at [Farey sequences](https://en.wikipedia.org/wiki/Farey_sequence). This time we're interested in the cardinality of $F_{1000000}$.\n",
"\n",
"To begin, first note that $F_1 = \\{0, 1\\}$, so $|F_1| = 2$ (this problem isn't counting 0 and 1 in its totals - we'll handle that at the end). Then consider that for any Farey sequence $F_n$, the next sequence $F_{n+1}$ will contain all the terms from $F_n$, along with all irreducible fractions $\\frac{k}{n+1}$, (since any *reducible* fraction would already be in $F_n$).\n",
"How many new fractions does this get us? Well, the fraction only reduces if $k$ and $n+1$ have a common factor - in other words, if $k$ and $n+1$ are coprime, the fraction will not reduce. How many number less than $n+1$ are coprime to $n+1$? The [totient function](https://en.wikipedia.org/wiki/Euler%27s_totient_function) will tell us! So the number of irreducible fractions with denominator $n+1$ is simply $\\phi(n+1)$. This gives us\n",
"The [sum of totients](https://en.wikipedia.org/wiki/Totient_summatory_function) is denoted $\\Phi(n)$.\n",
"As mentioned before, we'll actually subtract two from this total, since the problem isn't counting 0 or 1. So this problem boils down to computing $\\Phi(1000000) - 1$.\n",
"\n",
"## Using SageMath\n",
"\n",
"Since SageMath implements a decently fast totient function, we could opt for the most straightforward approach."
"If you try to implement the totient function yourself, you might find it difficult to make this approach fast enough. An alternative is to \"sieve\" the values of totient - see [problem 70](https://projecteuler.net/problem=70). However, there's a few more *very* interesting methods to compute totient sums.\n",
"You might think a fast totient function is key to solving this problem quickly, but it turns out there's a crazy recursive formula for $\\Phi(n)$ that does not require implementing the totient function at all! Since it's a little hard to believe it works, here's a derivation of it.\n",
"\n",
"We start with the following identity, proven by Gauss:\n",
"$$\\sum_{d|k}\\phi(d) = k$$\n",
"\n",
"Then, we can apply the formula for [triangular numbers](https://en.wikipedia.org/wiki/Triangular_number):\n",
"$$\\sum_{k=1}^n \\sum_{d|k}\\phi(d) = \\sum_{k=1}^n k = \\frac{n(n+1)}{2}$$\n",
"\n",
"Now we'll rewrite the bounds.\n",
"$$\\sum_{1 \\leq k \\leq n} \\sum_{xy=k}\\phi(x) = \\frac{n(n+1)}{2}$$\n",
"\n",
"This makes it easier to see that we can condense the two nested summations into one.\n",
"Not a super intuitive definition for $\\Phi(n)$, but pretty simple to implement, and surprisingly quick!"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "858a64d2",
"metadata": {},
"outputs": [],
"source": [
"from functools import cache\n",
"\n",
"@cache\n",
"def totient_sum(n):\n",
" if n == 1:\n",
" return 1\n",
" \n",
" return n*(n+1)/2 - sum(totient_sum(n//d) for d in range(2, n + 1))"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "3f21311a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"303963552391"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"totient_sum(1000000) - 1"
]
},
{
"cell_type": "markdown",
"id": "6f1085a3",
"metadata": {},
"source": [
"Both of the above strategies are simple and fast enough to get the job done on a modern computer, but it turns out we can go even deeper. But first, we need to become familiar with some important formulas.\n",
"\n",
"## Dirichlet convolution\n",
"\n",
"The [Dirichlet convolution](https://en.wikipedia.org/wiki/Dirichlet_convolution) of two [arithmetic functions](https://en.wikipedia.org/wiki/Arithmetic_function) $f$ and $g$ is\n",
"Several important mathematical functions have some representation as a Dirichlet convolution - see the above page for a list. An important one for our purposes is $\\phi * 1 = \\mathrm{Id}$, where $1$ is just the constant function $1(n) = 1$ and $\\mathrm{Id}(n) = n$ is the [identity function](https://en.wikipedia.org/wiki/Identity_function) (note that this convolution identity is the same as Gauss's identity presented above).\n",
"This might seem complicated, but note that in the second summation on the right, when $y=1$, we have $\\Phi(n)$. We can extract that term and rearrange to get a recursive formula for $\\Phi(n)$:\n",
"$$\\Phi(n) = \\frac{n(n+1)}{2} + \\lfloor b \\rfloor\\Phi(\\lfloor a \\rfloor) - \\sum_{x=1}^a \\phi(x)\\left\\lfloor\\frac{n}{x}\\right\\rfloor - \\sum_{y=2}^b \\Phi\\left(\\left\\lfloor\\frac{n}{y}\\right\\rfloor\\right)$$\n",
"The major advantage of this formula is that we only need the values of the totient function up to $a$, instead of up to $n$. We can set $a = \\sqrt{1000000} = 1000$.\n",
"* Partial sums of totient function: [A002088](https://oeis.org/A002088)\n",
"\n",
"#### Copyright (C) 2025 filifa\n",
"\n",
"This work is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International license](https://creativecommons.org/licenses/by-sa/4.0/) and the [BSD Zero Clause license](https://spdx.org/licenses/0BSD.html)."