你可能已经猜到我正在通过标题做项目euler#12。我的暴力解决方案耗时太长,所以我一直在寻找可以理解的优化。
我有兴趣扩展概述here
的策略我尝试解决这个问题的方法是使用Eratosthenes的Sieve来获得这样的主要因素:
divs = []
multiples = set()
for i in xrange(2, n + 1):
if i not in multiples:
if n % i == 0:
divs.append(i)
multiples.update(xrange(2*i, n+1, i))
return divs
这本身就是一个问题,因为第8行在程序进入答案范围之前很久就会产生溢出错误(76576500)。
现在,假设我能够得到主要因素,我怎样才能有效地找到它们各自的多重性?
答案 0 :(得分:1)
借用其他答案:
数字a1 ^ k1 * a2 ^ k2 * ... an ^ kn的因子数=(k1 + 1)*(k2 + 1)......(kn + 1)
您可以使用以下代码获取低于特定数字的素数: 由Fastest way to list all primes below N
提供n = number
def primesfrom2to(n):
""" Input n>=6, Returns a array of primes, 2 <= p < n """
sieve = numpy.ones(n/3 + (n%6==2), dtype=numpy.bool)
for i in xrange(1,int(n**0.5)/3+1):
if sieve[i]:
k=3*i+1|1
sieve[ k*k/3 ::2*k] = False
sieve[k*(k-2*(i&1)+4)/3::2*k] = False
return numpy.r_[2,3,((3*numpy.nonzero(sieve)[0][1:]+1)|1)]
primes = primesfrom2to(n).tolist() # list of primes.
primes = map(int, primes)
factors = {}
for prime in primes:
n = number
factor = 0
while True:
if n%prime == 0:
factor += 1
n /= prime
factors[prime] = factor
else: break
因素将为您提供多种主要因素。
答案 1 :(得分:1)
我的标准素数脚本附在下面;它提供了Eratsothenes的Sieve来生成质数,一个Miller-Rabin素性检验,一个使用2,3,5轮和Pollard的rho方法计算整数的函数,数值理论函数sigma计算x'的总和一个整数除数的幂,使用你在帖子中引用的方法,以及一个从给定整数开始计算等分序列的函数。鉴于该脚本,很容易解决Project Euler 12,记住x = 0的sigma返回整数除数的计数:
$ python
Python 2.6.8 (unknown, Jun 9 2012, 11:30:32)
[GCC 4.5.3] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> execfile('primes.py')
>>> factors(76576500)
[2, 2, 3, 3, 5, 5, 5, 7, 11, 13, 17]
>>> sigma(0,76576500)
576
>>> i, t = 1, 1
>>> while sigma(0, t) < 500:
... i += 1; t += i
...
>>> print t
76576500
您可以在 http://programmingpraxis.codepad.org/V5LiI8V9运行该程序,您会在my blog找到很多素数。这是代码:
# prime numbers
def primes(n): # sieve of eratosthenes
i, p, ps, m = 0, 3, [2], n // 2
sieve = [True] * m
while p <= n:
if sieve[i]:
ps.append(p)
for j in range((p*p-3)/2, m, p):
sieve[j] = False
i, p = i+1, p+2
return ps
# from random import randint
seed = 17500728 # RIP j s bach
def random(): # float on range [0,1)
global seed
seed = (69069 * seed + 1234567) % 4294967296
return seed / 4294967296.0
def randint(lo,hi): # int on range [lo,hi)
return int((hi - lo) * random()) + lo
def isPrime(n, k=5): # miller-rabin
if n < 2: return False
for p in [2,3,5,7,11,13,17,19,23,29]:
if n % p == 0: return n == p
s, d = 0, n-1
while d % 2 == 0:
s, d = s+1, d/2
for i in range(k):
x = pow(randint(2, n-1), d, n)
if x == 1 or x == n-1: continue
for r in range(1, s):
x = (x * x) % n
if x == 1: return False
if x == n-1: break
else: return False
return True
# from fractions import gcd
def gcd(a,b): # greatest common divisor
if b == 0: return a
return gcd(b, a % b)
def insertSorted(x, xs): # insert x in order
i, ln = 0, len(xs)
while i < ln and xs[i] < x: i += 1
xs.insert(i,x)
return xs
def factors(n, b2=-1, b1=10000): # 2,3,5-wheel, then rho
if -1 <= n <= 1: return [n]
if n < -1: return [-1] + factors(-n)
wheel = [1,2,2,4,2,4,2,4,6,2,6]
w, f, fs = 0, 2, []
while f*f <= n and f < b1:
while n % f == 0:
fs.append(f)
n /= f
f, w = f + wheel[w], w+1
if w == 11: w = 3
if n == 1: return fs
h, t, g, c = 1, 1, 1, 1
while not isPrime(n):
while b2 <> 0 and g == 1:
h = (h*h+c)%n # the hare runs
h = (h*h+c)%n # twice as fast
t = (t*t+c)%n # as the tortoise
g = gcd(t-h, n); b2 -= 1
if b2 == 0: return fs
if isPrime(g):
while n % g == 0:
fs = insertSorted(g, fs)
n /= g
h, t, g, c = 1, 1, 1, c+1
return insertSorted(n, fs)
def sigma(x, n, fs=[]): # sum of x'th powers of divisors of n
def add(s, p, m):
if x == 0: return s * (m+1)
return s * (p**(x*(m+1))-1) / (p**x-1)
if fs == []: fs = factors(n)
prev, mult, sum = fs.pop(0), 1, 1
while len(fs) > 0:
fact = fs.pop(0)
if fact <> prev:
sum, prev, mult = add(sum, prev, mult), fact, 1
else: mult += 1
return add(sum, prev, mult)
def aliquot(n): # print aliquot sequence
s, ss, k, fs = n, [n], 0, factors(n)
print n, k, s, fs
while s > 1:
s, k = sigma(1,s,fs) - s, k + 1
fs = factors(s)
print n, k, s, fs
if s in ss: return "cycle"
ss.append(s)
return ss.pop(-2)
答案 2 :(得分:1)
即使您将自己局限于相对简单的算法(即不是布伦特算法或任何更高级的算法),您的分解方法也远非最优化。
每次找到素数因子时,除以该因子直到它不再可被整除。你能做到的次数就是多样性。
除法后继续使用商,而不是原始数字。
找出因子并除以直到剩余商小于你的除数的平方。在这种情况下,商是1或素数(具有多重性1的最后一个素数因子)。
要找到因子,从2开始进行试验除法,从3开始进行奇数。任何非素数都不会成为问题,因为它的素因子在到达之前就已经被删除了。
使用正确的数据结构来表示素数因子及其多样性(地图或多重集)。
您也可以直接计算除数的数量,而不存储分解。每当您找到素数因子及其多重性时,您可以通过乘以除数的公式中的相应因子来累积结果。
如果你需要对不太大的数字进行多次分解,你可以为每个数组索引预先计算一个具有最小除数的数组,并使用它来快速找到除数。
答案 3 :(得分:0)
示例:28 = 2 ^ 2 * 7 ^ 1 因子数=(2 + 1)*(1 + 1)= 6
通常a ^ k1 * a ^ k2 .. a ^ kn 因子数=(k1 + 1)*(k2 + 1)......(kn + 1)