如何找到三角形数字的因子数量?

时间:2016-05-12 03:30:03

标签: python

我正在做Project Euler Problem 12而我遇到了一个问题。这是我的代码:

def print_factors(x):
    count = 0 
    for i in range(1, x + 1):
        if x % i == 0:
            count = count + 1
    return count
count = 0
div = 0
while True:
    if print_factors(count + count + 1) == 500:
        print(count)
        break;
    count = count + 1

有更快的方法吗?这花了太长时间。

3 个答案:

答案 0 :(得分:0)

对于每个三角形数字,您可以从2开始迭代素数。对于每次素数检查,可以分割数量的次数。例如,自28 / 2 = 1414 / 2 = 7以来,28可以分为两次,分为两次。然后将当前除数的数量乘以+ 1.然后将剩余数量分配给数字并移至下一个素数。在prime <= number时重复。下面是在实践中实现它的代码:

# Generate bunch of primes and cache them for efficiency
primes = [2, 3]

for i in xrange(5, 1000):
    for j in primes:
        if i % j == 0:
            break
    else:
        primes.append(i)

i = 2
while True:
    res = triangle = i * (i - 1) / 2
    divisors = 1

    for j in primes:
        if j > triangle:
            break

        cur = 1
        while triangle % j == 0:
            triangle /= j
            cur += 1

        divisors *= cur

    if divisors > 500:
        break
    i += 1

print res

答案 1 :(得分:0)

这是我的代码。

!/usr/bin/python
primes = [2]
def fp():
    i=3
    while i<10000:
        for j in primes:
            if i%j == 0:
                break
        else:
            primes.append(i)
        i+=1
def fac(n):
    f={}
    i = 0
    while n > 1:
        p=primes[i]
        if p*p > n :
            p=n
        while n%p==0:
            f[p]=f.get(p,0)+1
            n/=p
        i+=1
    n=1
    for i in f:
        n*=f[i]+1
    return n

from time import time
def f1():
    t=time()
    fp()
    j=0
    i=0
    max = 0
    while True:
        i+=1
        j+=i
        f=fac(j)
        if f >= 500:
            break

    print j,f
    print time()-t

f1()

编辑:

素数:包含从2到最后素数小于10000的素数的列表(由fp构造)

fp:找到小于10000的所有素数并将它们存储在&#34; primes&#34;中。我们必须在此之后多次检查素数,因此预先找到并将它们存储在列表中将使整个过程更快。此功能很快,因为1.它只通过素数2.它停在目标数的sqrt。

fac:为给定数量的因子数量提供资金的函数。它比蛮力更好,因为它只是试图使用&#34; primes&#34;来找到所有的素因子。列表再次,停在目标号码的sqrt。在知道所有素数因子后,它使用某种组合算法计算因子的数量,这是每个不同素数因子的乘积。

例如:40 =(2 * 2 * 2)(5)然后40有(3(+1))(1(+1))= 8个因子

说明:您可以将其视为一个问题,即您有两组材料(示例中为2和5),并且您希望通过混合这些材料来查找可以生成的结果数。如果你专注于材料&#39; 2&#39;你可以选择只有一个&#39; 2&#39;得到2或2&#39; 2&#39;得到4或3 2得到&#39; 8&#39;或者没有&#39; 2&#39;根本得到1,所以你有3次+1的可能性。与&#39; 5&#39;相同,您可以通过选择和取消选择1 + 1种可能性。这就是(+1)的来源。

f1:主要功能。它跳转到下一个和下一个三角形数字,然后找到超过500个因子然后停止的那个,打印它所花费的时间。

答案 2 :(得分:0)

这个非常好的解决方案完全基于http://www.tech-thoughts-blog.com/2012/08/1-introduction-in-this-article-i-will.html的基础(仅有一些小的修正),rahmu提供了代码和对它的出色解释,所以这一切都归于他。无论是比原始代码还是其他解决方案更快,我都不确定。在我的机器上,它会在大约6秒内产生答案。

from collections import Counter
from operator import mul
from functools import reduce


def prime_factors(n):
    """
    Generates all the prime factors of a positive integer n
    :param n:
    """
    d = 2
    while n > 1:
        while n % d == 0:
            n /= d
            yield d
        d += 1


def format_prime(n):
    """
    Returns a collection.Counter() built from the prime factors decomposition of n.
    :param n:
    """
    return Counter(prime_factors(n))


def prime_count(c):
    """ c is a Counter() object holding the prime factor decomposition of an integer. It returns the total number of
    divisors by applying the following formula:
    Let N = a^x * b^y * c^z (a, b and c prime) and F(N) the total number of divisors of N.
    F(N) = (x + 1) * (y + 1) * (c + 1)
    :param c:
    """
    return reduce(mul, (c[j] + 1 for j in c))


def triangle(k):
    """
    k is an int. This function returns a collections.Counter that is the application of triangle(k) = k * (k+1) / 2.
    :param k:
    """
    a = format_prime(k)
    b = format_prime(k+1)
    c = a + b
    c[2] -= 1  # This is equivalent to a division by 2
    return c

if __name__ == "__main__":
    i = 2
    number_of_factors = 500
    while prime_count(triangle(i)) <= number_of_factors:
        i += 1
    print(i * (i+1) // 2)