所以我写了一个代码来实现eratosthenes的筛选,它适用于小输入!!一旦我接近1000000000它显示和错误,HeapMemoryOutOfSpace。我在这里一块,无法弄清楚如何让它为这么大的值工作。有没有可以为此做的某种优化?这是针对在线评判的,因此n的最大值是我已经提到过的。这不适用于比赛,仅适用于我自己的练习。任何形式的帮助将不胜感激!
import java.io.*;
class PrimeGenerator
{
public static void main(String args[])
{
try
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int t = Integer.parseInt(br.readLine());
while(t--!=0)
{
String k[] = br.readLine().split(" ");
int m = Integer.parseInt(k[0]);
int n = Integer.parseInt(k[1]);
long arr[] = new long[n+2];
for(long a=2;a<=n;a++)
{
arr[(int)a] = 1;
}
for(long a=2;a*a<=n;a++)
{
if(arr[(int)a]==1)
{
for(long b=a;b*a<=n;b++)
{
arr[(int)(a*b)]=0;
}
}
}
for(int a=2;a<=n;a++)
{
if(arr[a]==1&&arr[a]>=m)
{
System.out.println(a);
}
}
System.out.println();
}
}
catch(Throwable e)
{
e.printStackTrace();
}
}
}
答案 0 :(得分:1)
操作已经指出了代码的几个结构性问题;程序的某些部分根本没有任何意义(如if (arr[a] == 1 && arr[a] >= m)
)。更不用说代码没有实现Eratosthenes的Sieve,即使它使用类似的逻辑。 Eratosthenes通过从指数p * p开始然后以p递增(即,相加步幅)来击出素数p的倍数。
两个观察结果,假设这类似于SPOJ PRIME1 problem,你必须在M和N之间打印素数:
(1)您使用一个64位整数(Java long
)来表示每个候选编号而不是一个位。通过从阵列中排除所有偶数,可以进一步节省空间和时间,必要时可以用空气拉出数字2。比特打包,仅赔率表示只需要您现在使用的空间的1/128。在java.util.BitSet
已经为您完成了艰苦的工作。
(2)为了筛选[M,N]范围内的数字,没有必要筛选2(或3)和N之间的所有数字。事实上,像SPOJ这样的任务是为了让你有时间超时尝试一下,即使它可以使用干净的高性能代码。对于筛选范围[M,N],您只需要所有潜在的素因子(最多sqrt(N)
- 只有几千个)和一个大小为(N-M+1)
的数组用于实际筛分。或(N-M)/2
,仅用于赔率筛选。这只需要几毫秒而且空间不大。
对于SPOJ,您甚至不必使用打包位表示或仅限赔率筛选。只需专注于窗口筛分,您就可以轻松地完成任务,节省空间和时间。
答案 1 :(得分:0)
您需要调整JVM并增加堆大小。
如果您在控制台中运行程序,可以像这样增加大小:
java -Xmx6g myprogram
此命令将堆大小增加到6千兆字节,无论您的系统能够处理什么,都会增加它。
如果您正在运行eclipse或其他IDE,则必须查找如何调整JVM以在IDE中运行该程序,但它可能类似于上面的命令。
答案 2 :(得分:0)
对于高达1000000000的素数,您不需要在正确的实现中增加堆大小 您实施Eratosthenes筛选的一些问题:
为什么在存储0和1时使用long? 有一种原始类型只使用0和1(假和真)称为布尔值。
为什么要重新计算每一个素数?
您可以计算每个单个素数一次(最多为整数最大数),然后只需检查列表或打印它们。