Optimization story: Switching from GMP to gcc's __int128 reduced run time by 95%
Given N, introducing q=10^N, they are looking for a and b in [0,q) such that<p><pre><code>  (q+2a)^2-(2b-1)^2 = q^2-1
</code></pre>
For example, for N=1, q=10, given 18^2 - 15^2 = 99, we find a solution with a=4, b=8: 48<p>That suggests using <a href="https:&#x2F;&#x2F;en.m.wikipedia.org&#x2F;wiki&#x2F;Midpoint_circle_algorithm#Variant_with_Integer-Based_Arithmetic" rel="nofollow">https:&#x2F;&#x2F;en.m.wikipedia.org&#x2F;wiki&#x2F;Midpoint_circle_algorithm#Va...</a> to get rid of that pesky square root (circle drawing uses sums of squares, but I think that is trivially adjusted for)<p>I also think it is worthwhile to extend this to other bases, as it more easily produces more examples to look at for discovering structure, and gets rid of the arbitrarily chosen number 10.<p>Edit: for those needing some explanation how to get at that claim:<p><pre><code>  let q &gt; 0
</code></pre>
(they pick q=10, q=100, q=1000, but this generalises this)<p>Assume<p><pre><code>  aq+b = b^2 - a^2 for some a,b in [0,q]
</code></pre>
in other words: b^2-a^2, written in base q, is ab<p>Then:<p><pre><code>  b^2 - a^2 = qa+b                          &lt;=&gt; (bring all b’s to the left, all else to the right)
  b^2 - b = qa + a^2                        &lt;=&gt; (factor)
  b(b-1)  = a(a+q)                          &lt;=&gt; (using (p+q)(p-q) = p^2-q^2)
  (b-1&#x2F;2)^2 - (1&#x2F;2)^2 = (a+q&#x2F;2)^2 - (q&#x2F;2)^2 &lt;=&gt; (multiply by 4 on both sides)
  (2b-1)^2 - 1 = (2a+q)^2 - q^2             &lt;=&gt; (bring all a’s and all b’s to the right)
  q^2 - 1 = (2a+q)^2 - (2b-1)^2             &lt;=&gt; (switch sides; slight rewrite)
  (q+2a)^2 - (2b-1)^2 = q^2-1
</code></pre>
Edit 2: for large q, it probably is faster to do the (p+q)(p-q) = p^2-q^2 trick again (apologies for naming the free variable q the same as the q introduced earlier), and get:<p><pre><code>  (q+2a+2b-1)(q+2a-2b+1) = q^2-1
</code></pre>
Next, factor q^2-1, write all ways to write it as product of integers, and check each case for integer solutions for a and b in the right range. For example, for q=10, we have:<p><pre><code>  99 = 1x99 = 3x33 = 9x11 = 11x9 = 33x3 = 99x1, so we solve 6 systems (I guess one easily discard half of them on arguments of the p+q part being larger than the p-q part, but that’s peanuts) of two linear equations in two variables:

  &#x2F; q+2a+2b-1 =  1
  \ q+2a-2b+1 = 99

  &#x2F; q+2a+2b-1 =  3
  \ q+2a-2b+1 = 33

  …

  &#x2F; q+2a+2b-1 = 99
  \ q+2a-2b+1 =  1
</code></pre>
This also suggests that the number of solutions with d base q digits for a and b is correlated with the number of integers that divide q^2-1. That would link it to <a href="http:&#x2F;&#x2F;oeis.org&#x2F;A000010" rel="nofollow">http:&#x2F;&#x2F;oeis.org&#x2F;A000010</a>.<p>Edit 3: and for the 10^N case, one might consider <a href="http:&#x2F;&#x2F;oeis.org&#x2F;A095370" rel="nofollow">http:&#x2F;&#x2F;oeis.org&#x2F;A095370</a>. For example, the 62-digit number 1111…1111 has only 5 prime factors. You have to add 2 factors of 3 to get 9999…9999, so 10^62-1 can be written as product of two integers in 2^7 ways =&gt; only 2^6 = 64 equations to solve.