7

我在Glassdoor遇到了这个问题并试图实现它。问题如下 -

考虑一个数字 123,该数字与其数字的乘积 (123*1*2*3 = 738) 是 738。因此,123 是 738 的种子根。编写程序接受一个数字并找到所有可能的种子根. 例如,如果用户输入 4977,那么答案应该是 79 和 711。

我想到了一种方法:

  1. 找出 2 到 9 中除数的所有数字。

  2. 然后从最大的数字(在步骤 1 中找到的数字中)开始,找到组成数字的数字,然后打印这些数字的所有排列。

但是,这假设数字不重复,其次它不会像 4977 那样打印所有数字,它可以找到 79 但找不到 711。

有更好的方法吗?

4

7 回答 7

4

Another solution is to check every divisor of n and see if this could be a seed. To check all the divisors, you just need to check to the square root of n. So this algorithm runs in O(sqrt(n)). Could you do it faster?

Here is a simple C++ programme demonstrating this idea.

#include<iostream>

using namespace std;

int prod(int n){
  int res=n;
  while(n!=0){
    res*=n%10;
    n/=10;
  }
  return res;
}

int main(){
  int n;
  cin >> n;

  for(int i=1;i*i<=n;++i){
    if(n%i==0){
      if(prod(i)==n)
        cout << i << endl;
      if(n/i!=i && prod(n/i)==n)
        cout << n/i << endl;
    }
  }
}
于 2013-10-17T20:26:04.237 回答
4

我的方法是这样的。这是一种递归算法,它使用集合 S,它是一个包含从 2 到 9 的数字的多重集,可能是多次。

try (N, S, digit) {
    for d = digit, digit-1, ..., 2 {
        if N is divisible by d then {
            S' = S + {d};
            if N/d is composed of all the digits in S', perhaps with
               some 1's thrown in, then N/d is an answer;
            try (N/d, S', d);
        }
    }
}

然后为原始号码

try (originalN, empty-set, 9);
also check originalN to see if it has only 1 digits (11, 11111, etc.); if so, then it's also an answer

我认为这会起作用,但我可能错过了一些边界情况。

对于 4977,try(4977, empty, 9)会发现 4977 可以被 9 整除,所以它调用try(553, {9}, 9). 内部try发现 553 可以被 7 整除,并且 553/7 = 79;此时 S' = {7, 9},算法检查 79 是否由数字 {7, 9} 组成,结果成功。不过,该算法仍在继续。最终我们会回溯到外部try,它会在某个时候尝试d = 7,并且 4977/7 = 711,当我们进行检查时,S' = {7} 和 711 由 7 和一些 1 组成,所以这也是一个回答。

编辑:我已经包含了一个完整的 C++ 函数:

#include <iostream>
#include <vector>

using namespace std;

struct digitMultiset {
    int counts[10];  // note: the [0] and [1] elements are not used
};

static const digitMultiset empty = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };

bool hasDigits (const int n, digitMultiset& s) {
    digitMultiset s2 = empty;
    int temp = n;
    int digit;
    while (temp > 0) {
        digit = temp % 10;
        if (digit == 0) return false;
        if (digit != 1) s2.counts[digit]++;
        temp /= 10;
    }
    for (int d = 2; d < 10; d++)
        if (s2.counts[d] != s.counts[d]) return false;
    return true;
}

void tryIt (const int currval, const digitMultiset& s,
            const int digit, vector<int>& answers) {
    digitMultiset newS;
    for (int d = digit; d >= 2; d--) {
        if (currval % d == 0) {
            int quotient = currval / d;
            newS = s;
            newS.counts[d]++;
            if (hasDigits (quotient, newS))
                answers.push_back (quotient);
            tryIt (quotient, newS, d, answers);
        }
    }
}

void seedProduct (const int val) {
    vector<int> answers;
    tryIt (val, empty, 9, answers);
    int temp = val;
    bool allOnes = true;
    while (temp > 0)  {
        if (temp % 10 != 1) {
            allOnes = false;
            break;
        }
        temp /= 10;
    }
    if (allOnes)
        answers.push_back(val);

    int count = answers.size();
    if (count > 0)  {
        if (count == 1)
            cout << val << " has seed product " << answers[0] << endl;
        else  {
            cout << val << " has " << count << " seed products: ";
            for (int& ans : answers)
                cout << ans << " ";
            cout << endl;
        }
    }
}
于 2013-10-17T19:16:53.833 回答
0

176852740608 不到 1 秒。找到所有因素,然后检查特定因素是否是种子根。

import java.util.ArrayList;

public class Number {
    long value;
    public ArrayList<Long> factors= new ArrayList<Long>();

    public Number(long a){
        value = a;
        for(long i=1;i<= Math.sqrt(a);i++){
            if(a%i==0)
                {
                factors.add(i);
                if((a/i)!=i)
                    factors.add(a/i);
                }
        }
        System.out.println(factors);
    }


public static void main(String args[]){
    long x = 24562368L;
    Number N = new Number(x);
    for(long i : N.factors){
        long ProductOfDigits = 1;
        long k = i;
        while(k!=0){
            ProductOfDigits = ProductOfDigits*(k%10);
            k = k/10;
        }
        if(i*ProductOfDigits == N.value)
            System.out.println(i);
    }
}
}
于 2013-10-31T04:18:28.737 回答
0

首先,找出所有因数分解的方法:

100 - 2 * 50 - 4 * 25 - 2 * 2 * 25 - ... 以此类推 ... - 2 * 2 * 5 * 5

如果数字中有任何 1 位,请使用这些添加一些因素:

  • 1 * 2 * 50
  • 1 * 4 * 25
  • ... 等等

遍历所有这些因式分解,看看其中是否有正确的形式。

“正确的形式”是一种因式分解,其中一个因子的位数与因子数相同(减去一个),而其他因子等于位数

这提出了一种在找到分解时过滤分解的方法,因为一旦找到

  • 两个两位数或更高的因子(因为一个因子的解 consts 可能有不止一个数字加上所有其他因子正好有一个数字)-或-
  • 比原始数字中的位数更多的个位数因子(因为一个因子的位数永远不会多于原始数字)
  • 可能还有更多

分解是行不通的。

这是一些分解数字的方法的链接:http ://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.117.1230&rep=rep1&type=pdf

这是一些执行此操作的代码。没有关于在所有情况下都正确的承诺。当它无法解决时,使用蛮力分解和一些过滤器来短路过程。

package com.x.factors;

import java.util.ArrayList;
import java.util.List;

public class Factors {

    private List<Long> solutions;
    private final long original;
    private final int originalDigitCount;
    private List<Long> primes = new ArrayList<Long>();

    public Factors(long original) {
        this.original = original;
        this.originalDigitCount = ("" + original).length();
    }

    public List<Long> findSeeds() {
        // Consider a number 123, the product of the number with its digits (123*1*2*3 = 738) is 738. Therefore, 123 is
        // the seed product of 738. Write a program to accept a number and find all possible seed products. For example,
        // If the user entered 4977 then the answer should be 79 and 711.

        solutions = new ArrayList<Long>();

        // filter out numbers that can't have seeds

        // Number must be positive (and not zero)
        if (original <= 0) {
            return solutions;
        }

        // Find a number with a 0 digit in it
        long temp = original;
        while (temp > 0) {
            if (temp % 10 == 0) {
                return solutions;
            }
            temp = temp / 10;
        }

        collectFactors(original, new ArrayList<Long>(), 0, 0);

        return solutions;
    }

    private void collectFactors(long num, List<Long> factors, int factorCount, int doubleDigitFactorCount) {
        if (primes.contains(num)) {
            return;
        }

        // The seed can't have more digits than the original number. Thus if we find more factors excluding
        // the seed than that, this can't be a solution.
        if (factorCount > originalDigitCount) {
            return;
        }

        boolean isPrime = true; // check whether num is prime
        int newDoubleDigitFactorCount = 0;
        for (long i = num / 2; i > 1; --i) {

            // Once we have one factor 2 digits or over, it has to be the seed, so there is no use trying
            // any more double digit numbers as only single digits are needed.
            if (i > 9) {
                if (doubleDigitFactorCount > 0) {
                    return; // short circuit because of two many non-one-digit factors
                }
                newDoubleDigitFactorCount = 1;
            } else {
                newDoubleDigitFactorCount = 0;
            }

            long remdr = num / i;
            if (remdr * i == num) { // is it a factor?
                isPrime = false; // it has a factor, its not prime

                // add this new factor into the list
                if (factors.size() <= factorCount) {
                    factors.add(i);
                } else {
                    factors.set(factorCount, i);
                }

                // found a list of factors ... add in the remainder and evaluate
                if (factors.size() <= factorCount + 1) {
                    factors.add(remdr);
                } else {
                    factors.set(factorCount + 1, remdr);
                }
                long seed = evaluate(factors, factorCount + 2);
                if (seed > 0) {
                    if (solutions.contains(seed)) {
                        continue;
                    }
                    solutions.add(seed);
                }

                collectFactors(remdr, factors, factorCount + 1, doubleDigitFactorCount + newDoubleDigitFactorCount);
            }
        }
        if (isPrime) { // if its prime, save it
            primes.add(num);
        }
        return;
    }

    /* package */long evaluate(List<Long> factors, int factorCount) {
        // Find seed, the largest factor (or one of them if several are the same)
        long seed = 0; // Note seed will be larger than 0
        int seedIndex = 0;
        for (int i = 0; i < factorCount; ++i) {
            if (factors.get(i) > seed) {
                seed = factors.get(i);
                seedIndex = i;
            }
        }

        // Count the digits in the seed, see if there are the right number of factors. Ignore 1's
        boolean[] factorUsed = new boolean[factorCount]; // start off as all false
        int seedDigitCount = 0;
        long temp = seed;
        while (temp > 0) {
            if (temp % 10 != 1) {
                ++seedDigitCount;
            }
            temp = temp / 10;
        }
        if (seedDigitCount != factorCount - 1) {
            return 0; // fail - seed digit count doesn't equal number of single digit factors
        }

        // See if all the seed's digits are present
        temp = seed;
        factorUsed[seedIndex] = true;
        while (temp > 0) {
            int digit = (int) (temp % 10);
            if (digit != 1) { // 1's are never in the factor array, they are just freely ok
                boolean digitFound = false;
                for (int digitIndex = 0; digitIndex < factorCount; ++digitIndex) {
                    if (digit == factors.get(digitIndex) && !factorUsed[digitIndex]) {
                        factorUsed[digitIndex] = true;
                        digitFound = true;
                        break;
                    }
                }
                if (!digitFound) {
                    return 0; // fail, a digit in the seed isn't in the other factors
                }
            }
            temp = temp / 10;
        }

        // At this point we know there are the right number of digits in the seed AND we have
        // found all the seed digits in the list of factors
        return seed;
    }
}
于 2013-10-17T18:47:08.637 回答
0

这是一个简单的程序。1秒内获得种子根176852740608现场演示

更新:找到 376,352,349 -> 153,642,082,955,760 需要 27 秒。你们呢?我不知道这是否好。

更新 2:@ajb 有一个更快的答案,至少在我做的实验中。但是这个答案的优点是更简单!

#include<iostream>
using namespace std;

typedef long long int Big_Int; // To get a 64-bit int

void root_stem(const Big_Int r, const Big_Int product_of_my_digits, const Big_Int target) {

        // There are two rules we can use to prune:
        //
        // First: The product_of_my_digits must divide into the target.
        //        If not, return
        // Second: The products produced lower in the search true will always be higher
        //         than those above. Therefore, we should return early if
        //         my_seed_product is larger than the target

        if (target % product_of_my_digits != 0)
                return;

        Big_Int my_seed_product = r * product_of_my_digits;

        if(my_seed_product >= target) {
                if (my_seed_product == target) {
                        cout << r << "\t->\t" << my_seed_product << endl;
                }
                return;
        }
        // print all roots, with their products, between 10*r and 10*r + 9
        for(Big_Int digit_to_append = 1; digit_to_append<=9; ++digit_to_append) {
                root_stem(r*10 + digit_to_append, product_of_my_digits*digit_to_append, target);
        }
}

int main() {
        root_stem(0,1, 4977);
        root_stem(0,1, 24562368);
        root_stem(0,1, 176852740608);
        return 0;
}
于 2013-10-18T01:01:39.067 回答
0
public class Seeds
    {
        public static void main(String[] args)
        {
             int num=4977;
             if(!seed(num).isEmpty())
                 System.out.println(seed(num));
             else
                 System.out.println("no seed number");
        }
        public static List<Integer> seed(int num)
        {  List<Integer> list=new ArrayList<Integer>();
            for(int i=1; i<=num; i++)
                {
                if(num%i==0)
                {
                    int factor_digit=1;
                    int factor = i;
                    factor_digit=factor_digit*factor;

            // when i is the factor, find factors of i and multiply them together to form number        
            while(factor>=1)
            {
                factor_digit = factor_digit * (factor%10); 
                factor = factor/10;     
            }
            if(factor_digit== num) 
                list.add(i);
        }

    }
            return list;
    }
    }

*
于 2015-07-29T03:31:02.013 回答
0

执行一个程序来确定一个数字是否是另一个数字的种子。如果将 X 乘以它的每个数字等于 Y,则称数字 X 是数字 Y 的种子:123 是 738 的种子,因为 123 1 2*3 = 738 */

class SeedNumber 
{
    public static void main(String[] args) 
    {
        int seed = 45;
        int num = 900;
        int seedNum = seed;
        int check=1;
        for(check=check*seed;seed>0;seed /=10)
        {
            int rem = seed % 10;
            check = check * rem;              
        }
        System.out.println(check);
        if(check == num)
            System.out.println(seedNum+" is a seed of "+num);
        else
            System.out.println(seedNum+" is not a seed of "+num);
        // Implement your code here 
    }
}
于 2021-07-22T18:54:23.823 回答