Task: Powerful numbers


C++: #include <algorithm>
#include <cmath>
#include <cstdint>
#include <iostream>
#include <numeric>
#include <vector>

bool is_square_free(uint64_t n) {
    static constexpr uint64_t primes[] {
        2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
        43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
    }; 
    for (auto p : primes) {
        auto p2 = p * p;
        if (p2 > n)
            break;
        if (n % p2 == 0)
            return false;
    }
    return true;
}

uint64_t iroot(uint64_t n, uint64_t r) {
    
    static constexpr double adj = 1e-6;
    return static_cast<uint64_t>(std::pow(n, 1.0/r) + adj);
}

uint64_t ipow(uint64_t n, uint64_t p) {
    uint64_t prod = 1;
    for (; p > 0; p >>= 1) {
        if (p & 1)
            prod *= n;
        n *= n;
    }
    return prod;
}

std::vector<uint64_t> powerful(uint64_t n, uint64_t k) {
    std::vector<uint64_t> result;
    std::function<void(uint64_t, uint64_t)> f = [&](uint64_t m, uint64_t r) {
        if (r < k) {
            result.push_back(m);
            return;
        }
        uint64_t root = iroot(n/m, r);
        for (uint64_t v = 1; v <= root; ++v) {
            if (r > k && (!is_square_free(v) || std::gcd(m, v) != 1))
                continue;
            f(m * ipow(v, r), r - 1);
        }
    };
    f(1, 2*k - 1);
    std::sort(result.begin(), result.end());
    return result;
}

uint64_t powerful_count(uint64_t n, uint64_t k) {
    uint64_t count = 0;
    std::function<void(uint64_t, uint64_t)> f = [&](uint64_t m, uint64_t r) {
        if (r <= k) {
            count += iroot(n/m, r);
            return;
        }
        uint64_t root = iroot(n/m, r);
        for (uint64_t v = 1; v <= root; ++v) {
            if (is_square_free(v) && std::gcd(m, v) == 1)
                f(m * ipow(v, r), r - 1);
        }
    };
    f(1, 2*k - 1);
    return count;
}

int main() {
    const size_t max = 5;
    for (uint64_t k = 2, p = 100; k <= 10; ++k, p *= 10) {
        auto result = powerful(p, k);
        std::cout << result.size() << " " << k
            << "-powerful numbers <= 10^" << k << ":";
        for (size_t i = 0; i < result.size(); ++i) {
            if (i == max)
                std::cout << " ...";
            else if (i < max || i + max >= result.size())
                std::cout << ' ' << result[i];
        }
        std::cout << '\n';
    }
    std::cout << '\n';
    for (uint64_t k = 2; k <= 10; ++k) {
        std::cout << "Count of " << k << "-powerful numbers <= 10^j for 0 <= j < "
            << k + 10 << ":";
        for (uint64_t j = 0, p = 1; j < k + 10; ++j, p *= 10)
            std::cout << ' ' << powerful_count(p, k);
        std::cout << '\n';
    }
}




Java: import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class PowerfulNumbers {

    public static void main(String[] args) {
        System.out.printf("Task:  For k = 2..10, generate the set of k-powerful numbers <= 10^k and show the first 5 and the last 5 terms, along with the length of the set%n");
        for ( int k = 2 ; k <= 10 ; k++ ) {
            BigInteger max = BigInteger.valueOf(10).pow(k);
            List<BigInteger> powerfulNumbers = getPowerFulNumbers(max, k);
            System.out.printf("There are %d %d-powerful numbers between 1 and %d.  %nList: %s%n", powerfulNumbers.size(), k, max, getList(powerfulNumbers));
        }
        System.out.printf("%nTask:  For k = 2..10, show the number of k-powerful numbers less than or equal to 10^j, for 0 <= j < k+10%n");
        for ( int k = 2 ; k <= 10 ; k++ ) {
            List<Integer> powCount = new ArrayList<>();
            for ( int j = 0 ; j < k+10 ; j++ ) {
                BigInteger max = BigInteger.valueOf(10).pow(j);
                powCount.add(countPowerFulNumbers(max, k));
            }
            System.out.printf("Count of %2d-powerful numbers <= 10^j, j in [0, %d]: %s%n", k, k+9, powCount);
        }
        
    }
    
    private static String getList(List<BigInteger> list) {
        StringBuilder sb = new StringBuilder();
        sb.append(list.subList(0, 5).toString().replace("]", ""));
        sb.append(" ... ");
        sb.append(list.subList(list.size()-5, list.size()).toString().replace("[", ""));
        return sb.toString();
    }

    private static int countPowerFulNumbers(BigInteger max, int k) {
        return potentialPowerful(max, k).size();
    }

    private static List<BigInteger> getPowerFulNumbers(BigInteger max, int k) {
        List<BigInteger> powerfulNumbers = new ArrayList<>(potentialPowerful(max, k));
        Collections.sort(powerfulNumbers);
        return powerfulNumbers;
    }

    private static Set<BigInteger> potentialPowerful(BigInteger max, int k) {
        
        int[] indexes = new int[k];
        for ( int i = 0 ; i < k ; i++ ) {
            indexes[i] = 1;
        }

        Set<BigInteger> powerful = new HashSet<>();
        boolean foundPower = true;
        while ( foundPower ) {
            
            boolean genPowerful = false;
            for ( int index = 0 ; index < k ; index++ ) {
                BigInteger power = BigInteger.ONE;
                for ( int i = 0 ; i < k ; i++ ) {
                    power = power.multiply(BigInteger.valueOf(indexes[i]).pow(k+i));
                }
                if ( power.compareTo(max) <= 0 ) {
                    powerful.add(power);
                    indexes[0] += 1;
                    genPowerful = true;
                    break;
                }
                else {
                    indexes[index] = 1;
                    if ( index < k-1 ) {
                        indexes[index+1] += 1;
                    }
                }
            }
            if ( ! genPowerful ) {
                foundPower = false;
            }
        }

        return powerful;
    }
    
}