@Override
    public BigInteger solve() {

        final BigInteger[] primes = toBigIntegerArray(primes(190));

        final List<BigInteger> l = new ArrayList<BigInteger>();
        final List<BigInteger> h = new ArrayList<BigInteger>();
        
        l.add(ONE);
        h.add(ONE);
        
        for (BigInteger prime : copyOfRange(primes, 0, primes.length / 2)) {
            for (BigInteger p : new ArrayList<BigInteger>(l)) {
                l.add(prime.multiply(p));
            }
        }
        for (BigInteger prime : copyOfRange(primes, primes.length / 2, primes.length)) {
            for (BigInteger p : new ArrayList<BigInteger>(h)) {
                h.add(prime.multiply(p));
            }
        }
        
        sort(l);
        sort(h);
        
        final int lMax = l.size() - 1;
        final int hMax = h.size() - 1;
        final BigInteger sqrt = sqrt(l.get(lMax).multiply(h.get(hMax)));
        
        BigInteger best = ZERO;
        
        for (int i = 0, j = hMax; i <= lMax && j >= 0; ) {
            
            final BigInteger current = l.get(i).multiply(h.get(j));
            final int c = current.compareTo(sqrt);
            
            if (c > 0) {
                j -= 1;
            } else if (c < 0) {
                if (current.compareTo(best) > 0) best = current;
                i += 1;
            }
        }
        
        return best.mod(TEN.pow(16));
    }