3 回答
TA贡献1866条经验 获得超5个赞
给定您的factorGenerator函数,这是一个应该工作的divisorGen:
def divisorGen(n):
factors = list(factorGenerator(n))
nfactors = len(factors)
f = [0] * nfactors
while True:
yield reduce(lambda x, y: x*y, [factors[x][0]**f[x] for x in range(nfactors)], 1)
i = 0
while True:
f[i] += 1
if f[i] <= factors[i][1]:
break
f[i] = 0
i += 1
if i >= nfactors:
return
该算法的整体效率将完全取决于factorGenerator的效率。
TA贡献1757条经验 获得超8个赞
您应该只在1到n的平方根之间运行循环。然后找到对,执行n / i,这将覆盖整个问题空间。
还应指出的是,这是一个NP或“困难”的问题。穷举搜索(您正在执行的方式)与保证答案的效果差不多。加密算法等使用此事实来帮助保护它们。如果有人要解决这个问题,那么我们目前大多数的“安全”通信,即使不是全部,也会变得不安全。
Python代码:
import math
def divisorGenerator(n):
large_divisors = []
for i in xrange(1, int(math.sqrt(n) + 1)):
if n % i == 0:
yield i
if i*i != n:
large_divisors.append(n / i)
for divisor in reversed(large_divisors):
yield divisor
print list(divisorGenerator(100))
应该输出如下列表:
[1、2、4、5、10、20、25、50、100]
TA贡献1827条经验 获得超7个赞
尽管已经有很多解决方案,但我确实必须发布此内容:)
快速(在有很多主要因素和因数的情况下,比公认的解决方案快10倍以上)
符合python3,python2和pypy
码:
def divisors(n):
# get factors and their counts
factors = {}
nn = n
i = 2
while i*i <= nn:
while nn % i == 0:
factors[i] = factors.get(i, 0) + 1
nn //= i
i += 1
if nn > 1:
factors[nn] = factors.get(nn, 0) + 1
primes = list(factors.keys())
# generates factors from primes[k:] subset
def generate(k):
if k == len(primes):
yield 1
else:
rest = generate(k+1)
prime = primes[k]
for factor in rest:
prime_to_i = 1
# prime_to_i iterates prime**i values, i being all possible exponents
for _ in range(factors[prime] + 1):
yield factor * prime_to_i
prime_to_i *= prime
# in python3, `yield from generate(0)` would also work
for factor in generate(0):
yield factor
添加回答
举报