#66 - Diophantine equation

Consider quadratic Diophantine equations of the form: $x^2-Dy^2=1$.

For example, when $D=13$, the minimal solution in $x$ is $649^2-13\times 180^2 = 1$.

It can be assumed that there are no solutions in positive integers when $D$ is square.

By finding minimal solutions in $x$ for $D = {2,3,5,6,7}$, we obtain the following: \[\begin{aligned} 3^2-2\times2^2 &= 1 \cr 2^2-3\times1^2 &= 1 \cr \color{red}{9}^2-5\times4^2 &= 1 \cr 5^2-6\times2^2 &= 1 \cr 8^2-7\times3^2 &= 1 \end{aligned}\]

Hence, by considering minimal solutions in $x$ for $D\leq 7$, the largest $x$ is obtained when $D=5$.

Find the value of $D\leq 1000$ in minimal solutions of $x$ for which the largest value of $x$ is obtained.


For a fixed $D$ (non-square), there are an infinite number of integers pairs $(x,y)$ that satisfy the equation above. The question is asking us to find the smallest $x$ for each $D$, then report which $D$ has the largest “smallest” $x$ solution.

A Diophantine equation is any polynomial equation where we only want integer solutions. This particular equation is known as Pell’s equation. The article lists many ways to solve it; we will use the following method:

Let $\frac{h_i}{k_i}$ denote the sequence of convergents to the regular continued fraction for $\sqrt{n}$. This sequence is unique. Then the pair $(x_1, y_1)$ solving Pell’s equation and minimizing $x$ satisfies $x_1 = h_i$ and $y_1 = k_i$ for some $i$. The article uses $n$ instead of $D$. So to solve this, all we need to do is calculate the convergents of $\sqrt{D}$ until we encounter a pair which solves the equation. This is guaranteed to be the pair that minimizes $x$. Both #64 - Odd period square roots and #65 - Convergents of $e$ deal with computing convergents of continued fractions. We can use those algorithms in this problem.

I’ll have one method that returns the periodic coefficients of the continued fraction of $\sqrt{D}$. Each solution pair is saved.

# file: "problem066.py"
def periodCoeffs(S):
    m = 0
    d = 1
    a0 = int(S ** 0.5)
    coeffs = [a0]
    a = a0
    while a != 2 * a0:
        m = d * a - m
        d = (S - m ** 2) // d
        a = int((a0 + m) / d)
        coeffs.append(a)
    return coeffs

# Diophantine equations of the form x^2 - Dy^2 = 1 are
# known as Pell's equations. As long as D is not square,
# a solution always exists. The minimizing x solution
# can be derived by testing successive convergents
# of the continued fraction of sqrt(D). This is
# what I'll be doing here.

maxD = 1000
xySols = np.zeros((maxD, 3), dtype=object)
xySols[:, -1] = np.arange(1, maxD+1)

for D in range(2, maxD + 1):
    # If D is not a perfect square
    sqrtD = D ** 0.5
    if sqrtD != int(sqrtD):
        # Find the coefficients of the
        # continued fraction
        aCo = periodCoeffs(D)
        hP = aCo[0]
        kP = 1
        h = aCo[1] * hP + 1
        k = aCo[1]
        n = 2
        while h ** 2 - D * k ** 2 != 1:
            an = aCo[(n - 1) % (len(aCo) - 1) + 1]
            temphP, tempkP = hP, kP
            hP, kP = h, k
            h = an * h + temphP
            k = an * k + tempkP
            n += 1
        # We're here when a solution has been found.
        # It has been proven that this solution minimizes x
        xySols[D - 1, :2] = [h, k]
        print('\rD: ' + str(D) + '/' + str(maxD), end='')
print()
maxX = np.argmax(xySols[:, 0])
print('The max x occurs when D = {} with (x, y) = ({}, {}).'
      .format(maxX + 1, xySols[maxX, 0], xySols[maxX, 1]))

Running the loop above results in an output of,

D: 1000/1000
The max x occurs when D = 661 with (x, y) = (16421658242965910275055840472270471049, 638728478116949861246791167518480580).
0.03699100005906075 seconds.

Thus, the largest minimal solution in $x$ occurs when $D=\mathbf{661}$.