我在Glassdoor遇到了这个问题并尝试实施。问题如下 -
考虑数字123,数字及其数字(123 * 1 * 2 * 3 = 738)的乘积是738.因此,123是738的种子根。写一个程序接受一个数字并找到所有可能的种子根。例如,如果用户输入4977,则答案应为79和711。
我想到了一种方式:
找到2到9之间的所有数字,除以数字。
然后从最大的数字(在步骤1中找到的数字中)开始,找到构成数字的数字,然后打印这些数字的所有排列。
但是,这假定数字不会重复,其次它不会打印所有数字,例如4977,它可以找到79但不会找到711。
有更好的方法吗?
答案 0 :(得分: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;
}
}
}
答案 1 :(得分:4)
另一个解决方案是检查n的每个除数,看看这是否可能是种子。要检查所有除数,只需要检查n的平方根。所以这个算法在O(sqrt(n))中运行。你能更快地完成吗?
这是一个简单的C ++程序,展示了这个想法。
#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;
}
}
}
答案 2 :(得分:0)
首先,找出影响数字的所有方法:
100 - 2 * 50 - 4 * 25 - 2 * 2 * 25 - ......等等...... - 2 * 2 * 5 * 5
如果数字中有任何1位数,请使用以下内容添加一些因素:
运行所有这些因素,看看是否有正确的形式。
“正确形式”是一个因子分解,其中一个因子具有与因子数相同的位数(少于一个),而其他因子等于数字
这提示了一种在找到它们时过滤分解因素的方法,因为一旦找到
分解不起作用。
以下是一些对数字进行分解的方法的链接: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;
}
}
答案 3 :(得分:0)
这是一个简单的程序。在1秒内获得176852740608
的种子根。 Live demo
更新:找到376,352,349 - &gt;需要27秒153,642,082,955,760。你呢?我不知道这是否好。
Update2:@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;
}
答案 4 :(得分: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;
}
}
*
答案 5 :(得分:0)
实现一个程序来找出一个数字是否是另一个数字的种子。 如果 X 乘以其每个数字等于 Y,则称 X 是数字 Y 的种子。 例如:123 是 738 的种子,因为 12312*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
}
}