繁体   English   中英

按升序打印一个数字的所有唯一素因数

[英]Print all unique prime factors of a number in ascending order

我是一个初学者并且完全困惑,我需要显示一个数字的所有主要除数,但是在第一个代码中计算需要很长时间,在第二个代码中,如果我输入数字 2,那么 java 打印 1 和2.但我只需要2。

例子:

input 360
output 2 3 5

input 2
output 2

input 999999797
output 999999797

如果我输入 999999797 那么“时间限制”我的错误是什么?

for (d = 2; x > 1; d++) {
    if (x % d == 0) {
        x = x / d;
        for (int i = 0; x % d == 0; i++) {
            x = x / d;
        }
        System.out.println(d);
    }
}

 for (d = 2; x % d == 0; d++) {
     for (int i = 0; x % d == 0; i++) {
        x = x / d;
     }
     System.out.println(d);
 }
 System.out.println(x);

清理第一个片段的代码(实际上很好)将是:

    int d = 2;
    int step = 1;
    while (x > 1) {
        if (x % d == 0) {
            System.out.println(d);
            x /= d;
            while (x % d == 0) {
                x /= d;
            }
        }
        d += step;
        step = 2;
    }

我添加了一个小优化,只测试了 2、3、5、7、9 等,以证明不需要测试许多除数。 一半的候选人。

推广到跳过 2、3、5:

对于模 2 * 3 * 5 的数字:

// Unneeded code:
boolean[] dividable = new int[2*3*5]; // non-candidates to be skipped.
for (int i = 0; i < dividable.length; ++i) {
    dividable[i] = i % 2 == 0 || i % 3 == 0 || i % 5 == 0;
}
// cycle length: 2*3*5 == 30.
// result: tfttt ttftt tftft ttftf tttft ttttf
// steps:   2      7   11 13  17 19  23     29 (8 from 30 candidates, a fourth)

然后可以进一步优化代码(虽然更丑陋):

final int cycleLength = 2*3*5;
final int[] initialSteps = {  2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
final int[] nextSteps =    {1,         7, 11, 13, 17, 19, 23, 29};
int[] steps = initialSteps;
for (int b = 0; x > 1; b += cycleLength) {
    for (int i = 0; x > 1 && i < steps.length; ++i) {
        int d = b + steps[i];
        while (x > 1) {
            if (x % d == 0) {
                System.out.println(d);
                x /= d;
                while (x % d == 0) {
                    x /= d;
                }
            }
        }
    }
    steps = nextSteps;
}

快了不到五倍。 (未经测试的代码。)

对于那些对数学感兴趣的人:注意这些steps当然是素数,并且初始步骤的initialSteps应该包含(i % P == 0 && i / P == 1)


没有 arrays,使用位代替

由于其中一项要求似乎是避免 arrays (尽管在这里它们的长度是固定的),因此可以使用位。 对于 30 位,一个 int 就足够了。

final int cycleLength = 2*3*5;
final int common = 1<<7 | 1<<11 | 1<<13 | 1<<17
       | 1<<19 | 1<<23 | 1<<29;
final int initialSteps = 1<<2 | 1<<3 | 1<<5 | common;
final int nextSteps =   1<<1 | common;
long steps = initialSteps;
for (int b = 0; x > 1; b += cycleLength) {
    for (int i = 0, int mask = 1; x > 1 && i < cycleLength; ++i, mask <<= 1) {
        if ((steps & mask) != 0) {
            int d = b + i;
            while (x > 1) {
                if (x % d == 0) {
                    System.out.println(d);
                    x /= d;
                    while (x % d == 0) {
                        x /= d;
                    }
                }
            }
        }
    }
    steps = nextSteps;
}

请注意,这更难看,我不确定代码是否正确。

暂无
暂无

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

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