我想遍历每个数字< N,并且知道每个数字素数因子分解。我的问题是,最好的方法是什么?
我知道我可以使用试验分割方法找到给定数字的素数因子分解,并且只对每个小于N的数字重复该数,但这样做效率低,并且比从数字生成每个数字需要更长的时间。已知的素因子。我已经编写了一个实现,生成每个小于N的数字,来自所有小于N的素因子。有更快的方法吗?我试图使用这样一个事实,因为我为所有小于N的数字做这个以节省计算时间,而不是做试验分割方法。
我想要实现的目标: 我有一个算法,我想在每个小于N的数字上运行。对于这个算法,我需要每个数字的素数因子分解。我试图在最短的时间内得到每个数字的素数因子分解。我实际上并不需要存储主要的因子分解,我只需要使用素数分解来运行我的算法。 (该算法在代码中解决(curNum,curFactors))
我编写了一个python3程序,以递归方式生成每个数字,并了解其主要因素,但速度非常慢。 (当N = 10 ^ 7时,处理时间需要大约58秒。函数求解对此基准没有任何作用。)
curFactors是一个列表,其中每个偶数元素都是分解中素数的索引,每个奇数元素都是素数指数。我从列表列表中将其展平以节省计算时间。主起始索引用于确保我不会重复计算数字。目前Solve什么都不做,所以我可以对这个功能进行基准测试。
def iterateThroughNumbersKnowingFactors(curNumber, curFactors, primeStartIndex):
#Generate next set of numbers
#Handle multiplying by a prime already in the factorization seperately.
for i in range(primeStartIndex+1,lenPrimes):
newNum = curNumber * primelist[i]
if(newNum > upperbound):
break
newFactors = curFactors[:]
newFactors.append(i)
newFactors.append(1)
#Do something with this number and its factors
solve(newNum, newFactors)
#Go get more numbers
iterateThroughNumbersKnowingFactors(newNum,newFactors,i)
if(primeStartIndex > -1):
newNum = curNumber * primelist[primeStartIndex]
if(newNum > upperbound):
return
currentNumPrimes = len(curFactors)
curFactors[currentNumPrimes-1] += 1
#Do something with this number and its factors
solve(newNum, curFactors)
#Go get more numbers
iterateThroughNumbersKnowingFactors(newNum,curFactors,primeStartIndex)
upperbound = 10**7
#https://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n
primelist = primesfrom2to(upperbound+1)
lenPrimes = len(primelist)
t0 = time.clock()
iterateThroughNumbersKnowingFactors(1,[],-1)
print(str(time.clock() - t0) +" seconds process time")
有谁知道更好的方法吗?
答案 0 :(得分:4)
如果您已经实施了Eratosthenes的Sieve并且其性能可以接受,那么您可以对其进行修改以存储素因子。
基本方法是这样的:每当你想要"交叉"一个数字或从列表中删除它作为素数的倍数,而是检查你可以将它除以素数而没有余数的次数(使用/
和%
)。这将为您提供一个(素数,指数)对,表示素数因子分解的组成部分。将这些对存储在与原始编号关联的列表或词典中。当Sieve完成时,每个列表将描述相应数字的素数因子化。
答案 1 :(得分:1)
如果您想找点乐子,可以使用 Bach's algorithm 在 [1,N]
时间内在区间 O(log(N))
中生成一个随机数。重复此操作直到找到所有小于 N 的数的质因数分解理论上可能需要无限的时间,但该算法的预期运行时间将为 O(log^2(n))
。
这在效率方面可能有点损失,但如果您想要一个不以线性顺序迭代的有趣算法,那么这可能是您最好的选择:)
答案 2 :(得分:1)
利用埃拉托色尼筛法的一些灵感,您可以通过将质数传播到最多 N 的质因数列表来构建因数列表:
只知道存在哪些素数:
def primeFactors(N):
result = [[] for _ in range(N+1)] # lists of factors from 0..N
for p in range(1,N+1,2):
if p<2: p=2
if result[p]: continue # empty list is a prime
for k in range(p,len(result),p):
result[k].append(p) # propagate it to all multiples
return result
print(*enumerate(primeFactors(10)))
# (0, []) (1, []) (2, [2]) (3, [3]) (4, [2]) (5, [5]) (6, [2, 3]) (7, [7]) (8, [2]) (9, [3]) (10, [2, 5])
要获得因式分解中每个素数的每个实例:
def primeFactorsAll(N):
result = [[] for _ in range(N+1)]
for p in range(1,N+1,2):
if p<2: p=2
if result[p]: continue
pn = p
while pn < N:
for k in range(pn,len(result),pn): # propagate to multiples of
result[k].append(p) # each power of p
pn *= p
return result
print(*enumerate(primeFactorsAll(10)))
# (0, []) (1, []) (2, [2]) (3, [3]) (4, [2, 2]) (5, [5]) (6, [2, 3]) (7, [7]) (8, [2, 2, 2]) (9, [3, 3]) (10, [2, 5])
对于大 N,这应该比除法方法运行得快得多。 对于 N= 10^7,在我的笔记本电脑上,primeFactors(N) 需要 8.1 秒,primeFactorsAll(N) 需要 9.7 秒。