【发布时间】:2012-05-29 01:01:13
【问题描述】:
我在编程网站上遇到了以下问题: Peter 想为他的密码系统生成一些素数。帮助他!你的任务是生成两个给定数字之间的所有素数!
输入
输入以单行中的测试用例数量 t (t
我想出了以下解决方案:
import java.util.*;
public class PRIME1 {
static int numCases;
static int left, right;
static boolean[] initSieve = new boolean[32000];
static boolean[] answer;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
numCases = sc.nextInt();
initSieve[0] = true;
initSieve[1] = true;
Sieve();
for (int j = 0; j < numCases; j++) {
String line = sc.next();
String line2 = sc.next();
left = Integer.parseInt(line);
right = Integer.parseInt(line2);
answer = new boolean[right - left + 1];
getAnswer();
for (int i = 0; i < answer.length; i++) {
if (!answer[i]) {
int ans = i + left;
System.out.println(ans);
}
}
System.out.println();
}
}
public static void Sieve() {
for (int i = 2; i < 32000; i++) {
if (!initSieve[i]) {
for (int j = 2 * i; j < 32000; j += i) {
initSieve[j] = true;
}
}
if (i * i > 32000)
break;
}
}
public static void getAnswer() {
for (int i = 2; i < 32000 && i <= right; i++) {
if (!initSieve[i]) {
int num = i;
if (num * 2 >= left) {
num *= 2;
} else {
num = (num * (left / num));
if (num < left)
num += i;
}
for (int j = num; j >= left && j <= right; j += i) {
answer[j - left] = true;
}
}
}
}
}
在阅读了一些建议后,我编辑了我的解决方案。我仍然收到超出时间限制的错误。关于如何进一步优化这一点的更多建议?我正在计算直到 32000 的所有素数,然后使用这些来找到 n 到 m 之间的素数。
谢谢, 罗希特
【问题讨论】:
-
如果您从 3 开始,而不是在筛子中的 2,并设法在循环外将值交换为 2,则可以通过 i+=2; 进行迭代。然后,而不是在外循环中运行到 isNotPrime.length,
√(isNotPrime.length)应该就足够了。不相关:Scanner 有一个方法 nextInt。 -
您可以通过仅循环范围内的赔率(从奇数开始,在
for (int i = 0; i < answer.length; i+=2)中以i+=2递增)来立即减半运行时间。确保i对应的奇数不低于left。 2 以上的偶数永远不会是素数。 :) 那将是稀疏寻址方案,更快的是使用压缩数组,其中索引i处的条目代表数字n=left_odd + 2i。在Sieve()内部,j+=2*i也可以工作(虽然这个筛子很小),但更重要的是,在getAnswer()内部。看看丹尼尔的回答。
标签: java algorithm primes sieve-of-eratosthenes