How to calculate smallest number with certain number of divisors?

前端 未结 9 1403
野性不改
野性不改 2020-12-29 07:51

From Project Euler problem 500

The number of divisors of 120 is 16. In fact 120 is the smallest number having 16 divisors.

Find the smalle

9条回答
  •  盖世英雄少女心
    2020-12-29 08:12

    Here is the high level gist of my Javascript - where factorCount represents the number of divisors:

    • Find the prime factor decomposition of the factorCount
    • Generate every unique combination of these prime factors
    • For each combination, extract these combination values from the original prime factor array and add one value to this array that is the extracted values multiplied together. Then sort elements in descending order.
    • For each array created by the previous step, check which yields the minimal number when computing 2^(b1-1)*3^(b2-1)5^(b3-1)...
    • This minimum number computed is the smallest number with factorCount number of divisors

    Here's a high level code breakdown of my JavaScript functions:

    var primeFactors = findPrimeFactors(factorCount);
    var primeFactorCombinations = removeDuplicateArrays(generateCombinations(primeFactors, 1));
    var combinedFactorCandidates = generateCombinedFactorCombinations(primeFactors, primeFactorCombinations);
    var smallestNumberWithFactorCount = determineMinimumCobination(combinedFactorCandidates);
    

    And here's the full sha-bang:

    function smallestNumberByFactorCount(factorCount) {
    
      function isPrime(primeCandidate) {
        var p = 2;
        var top = Math.floor(Math.sqrt(primeCandidate));
        while(p<=top){
          if(primeCandidate%p === 0){ return false; }
          p++;
        }
        return true;
      }
    
      function findPrimeAfter(currentPrime) {
        var nextPrimeCandidate = currentPrime + 1
        while(true) {
          if(isPrime(nextPrimeCandidate)){
            return nextPrimeCandidate;
          } else {
            nextPrimeCandidate++;
          }
        }
      }
    
      function findPrimeFactors(factorParent) {
        var primeFactors = [];
        var primeFactorCandidate = 2;
        while(factorParent !== 1){
          while(factorParent % primeFactorCandidate === 0 && factorParent !== 1 ){
            primeFactors.push(primeFactorCandidate);
            factorParent /= primeFactorCandidate;
          }
          primeFactorCandidate = findPrimeAfter(primeFactorCandidate);
        }
        return primeFactors;
      }
    
      function sortArrayByValue(a,b){
        return a-b;
      }
    
      function clone3DArray(arrayOfArrays) {
        var cloneArray = arrayOfArrays.map(function(arr) {
          return arr.slice();
        });
        return cloneArray;
      }
    
      function doesArrayOfArraysContainArray(arrayOfArrays, array){
        var aOA = clone3DArray(arrayOfArrays);
        var a = array.slice(0);
        for(let i=0; i 0){
              combinations[combinations.length] = got;
            }
            return;
          }
          for (let j=0; j

    Paste the above code block into your browser console and you can test it out yourself:

    > smallestNumberByFactorCount(3) --> 4
    > smallestNumberByFactorCount(4) --> 6
    > smallestNumberByFactorCount(5) --> 16
    > smallestNumberByFactorCount(6) --> 12
    > smallestNumberByFactorCount(16) --> 120
    > smallestNumberByFactorCount(100) --> 45360
    > smallestNumberByFactorCount(500) --> 62370000
    > smallestNumberByFactorCount(5000) --> 4727833110000
    > smallestNumberByFactorCount(100000000) --> 1.795646397225103e+40
    

    My algorithm starts shitting the bed when the input gets up to around 100 million... so for Project Euler problem 500 where the input would be 2^500500 (a really, really, really big number) you would need another approach. However, this is a good general approach that gets you pretty far. Hope it helps.

    Please leave comments with efficiency optimization suggestions. I would love to hear them.

提交回复
热议问题