我确信一定有更好的方法来做到这一点,但这是我的灵感来源。
以下代码查找 n 1-10,000 的所有 f[n] 值,除了最困难的值,恰好是 n = 9999。当我们到达那里时我停止循环。
ClearAll[f];
i3 = 1;
divNotFound = Range[10000];
While[Length[divNotFound] > 1,
i10 = FromDigits[IntegerDigits[i3++, 3]];
divFound = Pick[divNotFound, Divisible[i10, divNotFound]];
divNotFound = Complement[divNotFound, divFound];
Scan[(f[#] = i10) &, divFound]
] // Timing
Divisible 可能对两个参数的列表都有效,我们在这里充分利用了它。整个程序大约需要 8 分钟。
对于 9999,需要进行一些思考。在合理的时间内它不是暴力破解的。
令 P 为我们要寻找的因数,T(仅由 0、1 和 2 组成)为 P 与 9999 相乘的结果,即
9999 P = T
然后
P(10,000 - 1) = 10,000 P - P = T
==> 10,000 P = P + T
令 P1, ...PL 为 P 的数字,Ti 为 T 的数字,那么我们有
和中的最后四个零当然来自乘以 10,000。因此 TL+1,...,TL+4 和 PL-3,...,PL 互为补码。前者仅由 0,1,2 组成,后者允许:
last4 = IntegerDigits[#][[-4 ;; -1]] & /@ (10000 - FromDigits /@ Tuples[{0, 1, 2}, 4])
==> {{0, 0, 0, 0}, {9, 9, 9, 9}, {9, 9, 9, 8}, {9, 9, 9, 0}, {9, 9, 8, 9},
{9, 9, 8, 8}, {9, 9, 8, 0}, {9, 9, 7, 9}, ..., {7, 7, 7, 9}, {7, 7, 7, 8}}
只有 81 个允许的集合,包括 7、8、9 和 0(不是它们的所有可能组合)而不是 10,000 个数字,速度增益是 120 倍。
可以看出P1-P4只能有三进制数,即三进制数和naught之和。您可以看到添加 T5 和 P1 不会产生结转。通过意识到 P1 不能为 0(第一个数字必须是某物),可以进一步减少,如果它是 2 与 9999 的乘积,将导致 T 的结果为 8 或 9(如果发生进位),即也不允许。那么它必须是1。 P2-P4 也可以排除二号。
由于 P5 = P1 + T5,因此 P5
在所有这些情况下,添加不需要包含结转,因为它们不会发生(Pi+Ti 始终
结合所有这些,我们将尝试找到 L=16 的解决方案:
Do[
If[Max[IntegerDigits[
9999 FromDigits[{1, 1, 1, 1, i5, i6, i7, i8, i9, i10, i11, i12}~
Join~l4]]
] < 3,
Return[FromDigits[{1, 1, 1, 1, i5, i6, i7, i8, i9, i10, i11, i12}~Join~l4]]
],
{i5, 0, 3}, {i6, 0, 3}, {i7, 0, 3}, {i8, 0, 3}, {i9, 0, 5},
{i10, 0, 5}, {i11, 0, 5}, {i12, 0, 6}, {l4,last4}
] // Timing
==> {295.372, 1111333355557778}
实际上是 1,111,333,355,557,778 x 9,999 = 11,112,222,222,222,222,222
我们可能已经猜到了
f[9] = 12,222
f[99] = 1,122,222,222
f[999] = 111,222,222,222,222
模式显然是 1 的数量每一步增加 1,连续 2 的数量增加 4。
13 分钟,这超过了 Euler 项目的 1 分钟限制。也许我会很快研究一下。