找到最大的素数因子 - 代码的复杂性

时间:2015-05-17 20:47:37

标签: c++ c prime-factoring

我在编码网站上尝试了一个代码来找到一个数字的最大素数因子,并且它超过了最后一个测试用例的时间限制,可能他们使用的是一个大的素数。能帮我降低以下代码的复杂性吗?

int main()
{
    long n;
    long int lar, fact;
    long int sqroot;
    int flag;

    cin >> n;
    lar=2, fact=2;
    sqroot = sqrt(n);
    flag = 0;
    while(n>1)
    {
        if((fact > sqroot) && (flag == 0))         //Checking only upto Square Root
        {
            cout << n << endl;
            break;
        }
        if(n%fact == 0)
        {
            flag = 1;
            lar = fact;
            while(n%fact == 0)
                n = n/fact;
        }
        fact++;
    }
    if(flag == 1)         //Don't display if loop fact reached squareroot value
        cout << lar << endl;
}

此处我还负责循环检查,直到Square Root值。不过,我怎样才能进一步降低其复杂性?

3 个答案:

答案 0 :(得分:1)

您可以通过提供用于初始值fact的前N个素数的硬编码列表来加快速度(如果不降低复杂性),因为使用fact的复合值是浪费时间。之后,避免明显的fact复合值(如偶数)。

答案 1 :(得分:1)

您可以通过跳过大于2的偶数来减少测试次数,如果找到较小的因子,则可以更快地停止测试。这是一个更简单,更快速的版本:

int main() {
    unsigned long long n, lar, fact, sqroot;

    cin >> n;
    lar = 0;
    while (n && n % 2 == 0) {
        lar = 2;
        n /= 2;
    }
    fact = 3;
    sqroot = sqrt(n);
    while (fact <= sqroot) {
        if (n % fact == 0) {
            lar = fact;
            do { n /= fact; } while (n % fact == 0);
            sqroot = sqrt(n);
        }
        fact += 2;
    }
    if (lar < n)
        lar = n;
    cout << lar << endl;
    return 0;
}

我不确定输入数字可能变得多大,使用较大类型unsigned long long进行这些计算会比long更远。使用预先计算的素数数组会有所帮助,但不是很大的因素。

答案 2 :(得分:1)

我获得的更好的结果是使用下面的函数(lpf5())。它基于primality()函数(下面)使用公式6k + 1,6k-1来个别化素数。所有素数&gt; = 5可以以p=k*6+1p=k*6-1中的一种形式表示,其中k> 0(但不是具有这种形式的所有数字都是素数)。开发这些公式我们可以看到如下序列:

k=1 5,7
k=2 11,13
k=3 17,19
k=4 23,25*
k=5 29,31
.
.
.
k=10 59,61
k=11 65*,67
k=12 71,73
...

5,7,11,13,17,19,23,25,29,31,...,59,61,65,67,71,73,...

我们观察到术语之间的差异是2和4.这样的结果也可以使用简单的数学来获得。很明显,k * 6 + 1和k * 6-1之间的差异是2.很容易注意到k * 6 + 1和(k + 1)* 6-1之间的差异是4。

当x为素数(或0 - 小心)时,函数primality(x)返回x,当x不是素数时,第一个除数发生。

我认为您可以在primality()函数中获得更好的结果lpf5()函数。

我还尝试在素数函数中插入一个带有一些素数的表(从1到383 - 所示公式的前128个结果中的素数),但速度差异是不可靠的。

这里是代码:

#include <stdio.h>
#include <math.h>

typedef  long long unsigned int uint64;
uint64 lpf5(uint64 x);
uint64 primality(uint64 x);

uint64 lpf5(uint64 x)
{
    uint64 x_=x;

    while ( (x_=primality(x))!=x)
        x=x/x_;

    return x;
}

uint64 primality(uint64 x)
{
    uint64 div=7,f=2,q;

    if (x<4 || x==5)
        return x;

    if (!(x&1))
        return 2;

    if (!(x%3))
        return 3;

    if (!(x%5))
        return 5;

    q=sqrt(x);
    while(div<=q) {
        if (!(x%div)) {
            return div;
        }
        f=6-f;
        div+=f;
    }

    return x;
}

int main(void) {
    uint64 x,k;

    do {
        printf("Input long int: ");
        if (scanf("%llu",&x)<1)
            break;

        printf("Largest Prime Factor: %llu\n",lpf5(x));
    } while(x!=0);

    return 0;
}