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