如何编写快速函数来计算数字的总除数?

时间:2012-09-05 19:45:43

标签: c++ algorithm numbers primes

我必须找到给定数N的除数总数,其中可以大到10 ^ 14.我尝试计算高达10 ^ 7的素数然后使用素数的指数找到除数然而,由于使用筛子找到填料需要0.03秒,结果太慢了。如何在不计算质数的情况下更快地计算除数的总数?请非常感谢伪代码/解释良好的算法。

3 个答案:

答案 0 :(得分:4)

使用atkin筛子找到小于10 ^ 7的所有质数。 (这里有664,579个)

http://en.wikipedia.org/wiki/Sieve_of_Atkin

理想情况下,这应该在编译时完成。

接下来计算素数分解:

int x; // the number you want to factor
Map<int to int> primeFactor; // this is a map that will map each prime that appears in the prime factorization to the number of times it appears.

while(x > 1) {
  for each prime p <= x {
     if x % p == 0 {
       x = x / p; 
       primeFactor(p) = primeFactor(p) +1;
     }
  }
}

在此结束时,您将获得完整的素数分解。从这里你可以通过迭代地图的值来计算除数的总数: https://math.stackexchange.com/questions/66054/number-of-combinations-of-a-multiset-of-objects

int result = 1;
for each value v in primeFactors {
  result*= (v+1);
}

答案 1 :(得分:1)

我在blog实施了阿特金筛选,但仍然发现优化的Eratosthenes筛子更快。

但我怀疑这是你的问题。对于大到10 ^ 14的数字,无论你如何产生素数,波拉德rho因子分解都将超过素数的试验除法。我也在我的blog那样做了。

答案 2 :(得分:1)

您可以使用Pollard's rho-algorithm进行分解。对于所有improvements,数字最快可达到至少10 ^ 20。

以下是我在Java中查找因子的实现:

/**
 * Finds a factor of a number using Brent's algorithm.
 *
 * @param n  The number.
 *
 * @return  A factor of n.
 */
public static BigInteger findFactor(BigInteger n)
{
    final BigInteger result;
    if (n.isProbablePrime(80))
    {
        result = n;
    }
    else
    {
        BigInteger gcd = n;
        BigInteger c = ONE;
        while (gcd.equals(n))
        {
            int limitPower = 0;

            long k = 0;
            BigInteger y = ONE;
            boolean done = false;
            while (!done)
            {
                limitPower++;
                final long limit = Numbers.pow(2, limitPower);
                final int productLimit = (int) Numbers.pow(2, limitPower / 2);

                final BigInteger x = y;
                while (!done && k < limit)
                {
                    final BigInteger savedY = y;
                    int j = 0;
                    final int jLimit = (int) Math.min(productLimit, limit - k);
                    BigInteger p = ONE;
                    while (j < jLimit)
                    {
                        y = next(n, c, y);
                        p = p.multiply(x.subtract(y)).mod(n);
                        j++;
                    }
                    gcd = Numbers.gcd(p, n);

                    if (gcd.equals(ONE))
                    {
                        // Move along, nothing to be seen here
                        k += jLimit;
                    }
                    else
                    {
                        // Restart and find the factor
                        y = savedY;
                        while (!done)
                        {
                            k++;
                            y = next(n, c, y);
                            gcd = Numbers.gcd(x.subtract(y), n);
                            done = !gcd.equals(ONE);
                        }
                    }
                }
            }
            c = c.add(ONE);
        }
        result = gcd;
    }
    return result;
}


private static BigInteger next(BigInteger m, BigInteger c, BigInteger x)
{
    return square(x).subtract(c).mod(m);
}

要将数字分解为10 14 ,你也可以进行试验除法,奇数最多为10 7