题目:https://projecteuler.net/problem=32
题意:求所有满足如下条件的数z的和:z能分解成两个数x、y的积,且x、y、z中的digits刚好是1~9各出现一次
分析:1~9的permutation总共也就362880,对其枚举即可,这里有一个重要的剪枝:x末位 * y末位 % 10如果不等于z的末位,则继续下一次枚举,实测发现加上这一剪枝比不加的情况快1倍多
from itertools import permutations as Permute
def unite(arr):
n = 0
for x in arr:
n = n * 10 + x
return n
seq = range(1, 10)
tot = 0
his = set()
for arr in Permute(seq, 9):
# enumerate lhs length, no more than 4
for i in range(1, 5):
# enumerate rhs length, no more than lhs
for j in range(1, i+1):
k = 9 - i - j
# the product should has length no less than i and j
if k < i or k < j:
break
# so arr[:i] is lhs, arr[i:i+j] is rhs, arr[i+j:] is product
if arr[i-1] * arr[i+j-1] % 10 != arr[-1]:
# last digit do not match, so cut it off
continue
z = unite(arr[i+j:])
if z in his:
continue
x = unite(arr[:i])
y = unite(arr[i:i+j])
if x * y == z:
print('%d * %d = %d' % (x, y, z))
tot += z
his.add(z)
print(tot)