快速素数因子分解算法

时间:2012-10-06 03:06:08

标签: c algorithm prime-factoring

我在C中编写一个代码,它返回一个正整数可以表示为两个正整数的完美平方和的次数。

R(n) is the number of couples (x,y) such that x² + y² = n where x, y, n are all 
non negative integers.

要计算R(n),我需要先找到n的素数因子分解。

问题是我已经尝试了很多可以在C上使用的素数因子分解算法,但是我需要尽可能快地使用我的代码,所以如果有人能给我他/她的话我会很感激的被认为是计算与2147483742.

一样大的数的素数因子分解的最快算法

2 个答案:

答案 0 :(得分:10)

多么奇怪的限制; 2147483742 = 2 ^ 31 + 94。

正如其他人所指出的那样,对于一些人而言,这个由素数组成的小型试验分组很可能足够快。只有不是,你可以尝试Pollard的rho方法:

/* WARNING! UNTESTED CODE! */
long rho(n, c) {
    long t = 2;
    long h = 2;
    long d = 1;

    while (d == 1) {
        t = (t*t + c) % n;
        h = (h*h + c) % n;
        h = (h*h + c) % n;
        d = gcd(t-h, n); }

    if (d == n)
        return rho(n, c+1);
    return d;
}

被称为rho(n,1),此函数返回(可能是复合的)因子 n ;如果要查找 n 的所有因子,请将其置于循环中并重复调用。你还需要一个素数检查器;对于你的极限,基础2,7和61的Rabin-Miller测试被证明是准确且合理的快速。您可以在my blog了解有关素数编程的更多信息。

但无论如何,考虑到这么小的限制,我认为你最好不要使用试验分组。其他任何东西都可能渐近更快,但实际上更慢。

编辑:这个答案已收到几个最近的赞成票,所以我添加了一个简单的程序wheel factorization用2,3,5轮。该程序被称为wheel(n),以递增的顺序打印 n 的因子。

long wheel(long n) {
    long ws[] = {1,2,2,4,2,4,2,4,6,2,6};
    long f = 2; int w = 0;

    while (f * f <= n) {
        if (n % f == 0) {
            printf("%ld\n", f);
            n /= f;
        } else {
            f += ws[w];
            w = (w == 10) ? 3 : (w+1);
        }
    }
    printf("%ld\n", n);

    return 0;
}

我在my blog处讨论车轮分解;解释很冗长,所以我在此不再重复。对于适合long的整数,您不太可能明显改善上面给出的wheel函数。

答案 1 :(得分:0)

有一种减少候选人数量的快捷方法。此例程尝试2,然后是3,然后所有奇数不能被3整除。

long mediumFactor(n)
{
    if ((n % 2) == 0) return 2;
    if ((n % 3) == 0) return 3;
    try = 5;
    inc = 2;
    lim = sqrt(n);
    while (try <= lim)
    {
       if ((n % try) == 0) return try;
       try += inc;
       inc = 6 - inc;  // flip from 2 -> 4 -> 2
    }
    return 1;  // n is prime
}

2和4之间的inc的交替是仔细对齐的,以便它跳过所有偶数和可被3整除的数字。对于这种情况:5(+2)7(+4)11(+2)13(+4 )17

试验在sqrt(n)处停止,因为至少有一个因子必须等于或低于平方根。 (如果两个因子都是&gt; sqrt(n)那么因子的乘积将大于n。)

尝试次数为sqrt(m)/ 3,其中m是系列中可能的最高编号。对于2147483647的限制,最大情况下产生最多15,448个分区(对于2147483647附近的素数),包括2和3个测试。

如果数字是复合数,则总分数通常要少得多,而且很少会更多;甚至考虑到反复调用例程以获得所有因素。