我的方法是这样的。这是一种递归算法,它使用集合 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;
}
}
}