## Nearly-Square Divisors

### August 5, 2016

We have today a fun little problem from number theory:

Given positive integers

n,aandbsuch thatn=a·bwitha≥b, findaandbsuch that the differencea−bis as small as possible.

For *n* square, the solution is just the square root of *n*; for instance, with *n* = 36, *a* = *b* = 6. Otherwise, *a* and *b* will be the two divisors nearest the square root; for instance, with *n* = 60, *a* = 10 and *b* = 6.

Your task is to write a program to find *a* and *b* as described above; use your program to find the nearly square divisors of *n* = 224403121196654400. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Pages: 1 2

Another method is to start with the square root of n, rounded down, then decrement by one until a divisor is found. On my computer this took 0.6 sec.

The pitfall with any method is to deal with a prime n.

In Python. The divisors are scanned for the maximum value less equal isqrt(n).

@Ernie had the same idea! Here’s a solution that does that in Racket.

I came up with the same idea as the previous commenters. For large n with a higher number of divisors this may become incredibly time consuming, e.g. n = 100#. So I guess there’s a quicker solution than simply testing all possible numbers from floor(sqrt(n)) downward.

Python:

Output in approx. 0.012s: (473670855, 473753280)

Anyhow, this solution is based on the slow brute-force method. I’m almost certain there’s a much faster number-theoretical way to solve this for huge n.

@Ernie and @Milbrae. The number N=224403121196654400 has an incredibly large number of divisors and is the worst-case scenario for a solution using divisors and the best-case scenario for the solution walking down from the root. Now try to use both methods in the range [N-10, N+10). Timing is 90 ms for the divisor solution and the other solution takes forever.

Paul: That is point I was trying to make in my first post: if N has very few divisors, decrementing from the sqrt may take forever, and if N is prime, well don’t ask.

224403121196654400 is the 22nd “colossally abundant” number (and mentioned here: https://programmingpraxis.com/2016/04/22/gcd-sum/#comment-59608)

Finding nearly-square divisors seems about as hard as factoring (if we have a method for finding them we can apply it recursively to get a full factorization, and if we have a factorization, finding such divisors is straightforward).

Fermat factorization seems relevant too, but maybe only applies to odd numbers.

@Paul: You may have a point there. Anyhow, consider n having at least 30 distinct prime factors, each appearing once. n will then have 2**30 factors. You wouldn’t want to try almost all of them to find the correct NSD.

There’s a similar problem on Project Euler (https://projecteuler.net/problem=266). I don’t think the people you have already solved this did it through simply factoring.

@Milbrae: Good point, actually it’s a variant on the knapsack problem – find a maximal subset (or sub-multiset) of prime factors of n, the sum of whose logs is less than log n / 2 (and there are ways of solving the knapsack problem that are better than testing each alternative).

@Milbrae. Thanks for pointing me to Euler 266. I solved for the product of first 30 primes with divisors and it took about 4 hours. The Euler problem needs the first 42 primes. That will indeed need another approach.

@Matthew: A varint of knapsack? Could you elaborate on this?

@Milbrae: One form of knapsack problem is: given a set of real numbers S, and a limit k, find the maximal subset sum less (or equal) to k (ie. find a subset with sum less than or equal to k, and greater or equal to the sum of any other such subset). This is exactly what we want for the nearly-square root of a product of single primes (as in the Project Euler problem) – S is the set of logs of the primes, and k is the log of the square root.

Here’s a simple Haskell program that computes the log of the nearly square root of the product of the first 20 primes:

Scan the tree of subsets, discarding a branch which cannot lead to a solution (here just subsets that would be too large – we could also keep track of the best solution found and discard branches that cannot lead to a better solution).

@Matthew: Wow!! Works fine and extremely fast. I assume correctly the second line of the output is the exponent to e to get the result? I know practically nothing about Haskell.

[…] a recent exercise, we discussed the problem of computing the nearly square divisors of a composite number n = a · b, […]

[…] nearly square divisors exercise has generated a considerable amount of interest, and several excellent solutions in the comments. […]

package test;

import java.util.*;

public class SquareDivisors {

public static int squareDivisor(int n){

int diff=10000;

if (n < 0){

return diff;

}

List pairs = new ArrayList();

//no need to look beyond sqrt hence check for (i*i )<=n

for(int i=1;(i*i)<=n;i++){

if (n%i==0){

System.out.println("Pairs : "+i +" "+ (n/i));

pairs.add(new Pairs(i,n/i));

}

}

for(Pairs pair: pairs){

diff= (diff < (Math.abs(pair.a-pair.b)))?diff:(Math.abs(pair.a-pair.b));

}

return diff;

}

public static void main(String args[]){

System.out.println("Diff : "+squareDivisor(36));

}

}

class Pairs{

public Pairs(int a,int b){

this.a=a;

this.b=b;

}

public int a,b;

}