Task: Brilliant numbers


C++: #include <algorithm>
#include <chrono>
#include <iomanip>
#include <iostream>
#include <locale>
#include <vector>

#include <primesieve.hpp>

auto get_primes_by_digits(uint64_t limit) {
    primesieve::iterator pi;
    std::vector<std::vector<uint64_t>> primes_by_digits;
    std::vector<uint64_t> primes;
    for (uint64_t p = 10; p <= limit;) {
        uint64_t prime = pi.next_prime();
        if (prime > p) {
            primes_by_digits.push_back(std::move(primes));
            p *= 10;
        }
        primes.push_back(prime);
    }
    return primes_by_digits;
}

int main() {
    std::cout.imbue(std::locale(""));

    auto start = std::chrono::high_resolution_clock::now();

    auto primes_by_digits = get_primes_by_digits(1000000000);

    std::cout << "First 100 brilliant numbers:\n";
    std::vector<uint64_t> brilliant_numbers;
    for (const auto& primes : primes_by_digits) {
        for (auto i = primes.begin(); i != primes.end(); ++i)
            for (auto j = i; j != primes.end(); ++j)
                brilliant_numbers.push_back(*i * *j);
        if (brilliant_numbers.size() >= 100)
            break;
    }
    std::sort(brilliant_numbers.begin(), brilliant_numbers.end());
    for (size_t i = 0; i < 100; ++i) {
        std::cout << std::setw(5) << brilliant_numbers[i]
                  << ((i + 1) % 10 == 0 ? '\n' : ' ');
    }

    std::cout << '\n';
    uint64_t power = 10;
    size_t count = 0;
    for (size_t p = 1; p < 2 * primes_by_digits.size(); ++p) {
        const auto& primes = primes_by_digits[p / 2];
        size_t position = count + 1;
        uint64_t min_product = 0;
        for (auto i = primes.begin(); i != primes.end(); ++i) {
            uint64_t p1 = *i;
            auto j = std::lower_bound(i, primes.end(), (power + p1 - 1) / p1);
            if (j != primes.end()) {
                uint64_t p2 = *j;
                uint64_t product = p1 * p2;
                if (min_product == 0 || product < min_product)
                    min_product = product;
                position += std::distance(i, j);
                if (p1 >= p2)
                    break;
            }
        }
        std::cout << "First brilliant number >= 10^" << p << " is "
                  << min_product << " at position " << position << '\n';
        power *= 10;
        if (p % 2 == 1) {
            size_t size = primes.size();
            count += size * (size + 1) / 2;
        }
    }

    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> duration(end - start);
    std::cout << "\nElapsed time: " << duration.count() << " seconds\n";
}




Java: import java.util.*;

public class BrilliantNumbers {
    public static void main(String[] args) {
        var primesByDigits = getPrimesByDigits(100000000);
        System.out.println("First 100 brilliant numbers:");
        List<Integer> brilliantNumbers = new ArrayList<>();
        for (var primes : primesByDigits) {
            int n = primes.size();
            for (int i = 0; i < n; ++i) {
                int prime1 = primes.get(i);
                for (int j = i; j < n; ++j) {
                    int prime2 = primes.get(j);
                    brilliantNumbers.add(prime1 * prime2);
                }
            }
            if (brilliantNumbers.size() >= 100)
                break;
        }
        Collections.sort(brilliantNumbers);
        for (int i = 0; i < 100; ++i) {
            char c = (i + 1) % 10 == 0 ? '\n' : ' ';
            System.out.printf("%,5d%c", brilliantNumbers.get(i), c);
        }
        System.out.println();
        long power = 10;
        long count = 0;
        for (int p = 1; p < 2 * primesByDigits.size(); ++p) {
            var primes = primesByDigits.get(p / 2);
            long position = count + 1;
            long minProduct = 0;
            int n = primes.size();
            for (int i = 0; i < n; ++i) {
                long prime1 = primes.get(i);
                var primes2 = primes.subList(i, n);
                int q = (int)((power + prime1 - 1) / prime1);
                int j = Collections.binarySearch(primes2, q);
                if (j == n)
                    continue;
                if (j < 0)
                    j = -(j + 1);
                long prime2 = primes2.get(j);
                long product = prime1 * prime2;
                if (minProduct == 0 || product < minProduct)
                    minProduct = product;
                position += j;
                if (prime1 >= prime2)
                    break;
            }
            System.out.printf("First brilliant number >= 10^%d is %,d at position %,d\n",
                                p, minProduct, position);
            power *= 10;
            if (p % 2 == 1) {
                long size = primes.size();
                count += size * (size + 1) / 2;
            }
        }
    }

    private static List<List<Integer>> getPrimesByDigits(int limit) {
        PrimeGenerator primeGen = new PrimeGenerator(100000, 100000);
        List<List<Integer>> primesByDigits = new ArrayList<>();
        List<Integer> primes = new ArrayList<>();
        for (int p = 10; p <= limit; ) {
            int prime = primeGen.nextPrime();
            if (prime > p) {
                primesByDigits.add(primes);
                primes = new ArrayList<>();
                p *= 10;
            }
            primes.add(prime);
        }
        return primesByDigits;
    }
}