繁体   English   中英

快速素数分解算法

[英]Fast Prime Factorization Algorithm

我正在用 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.的数的质因数分解的最快算法2147483742.

多么奇怪的限制; 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 测试被证明是准确且相当快的。 您可以在我的博客上阅读更多关于使用质数编程的信息。

但无论如何,鉴于如此小的限制,我认为您最好使用素数试除。 其他任何东西都可能渐近地更快,但实际上更慢。

编辑:这个答案最近收到了几个赞成票,所以我添加了一个简单的程序,用 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;
}

我在 我的博客中讨论了轮子分解; 解释很长,所以我不会在这里重复。 对于适合long整数,您不太可能显着改善上面给出的wheel函数。

有一种快速的方法可以减少候选人的数量。 此例程尝试 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
}

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM