令 Pi 表示第 i 个素数。现任给两个正整数 M≤N≤104,请输出 PM 到 PN 的所有素数。
输入格式:
输入在一行中给出 M 和 N,其间以空格分隔。
输出格式:
输出从 PM 到 PN 的所有素数,每 10 个数字占 1 行,其间以空格分隔,但行末不得有多余空格。
输入样例:
5 27
输出样例:
11 13 17 19 23 29 31 37 41 43
47 53 59 61 67 71 73 79 83 89
97 101 103
解答:(思路简单,使用素数表,主要说一下做题发现的内存问题)
#include <cstdio>
const int MAX = 1e6 + 10;
bool isPrimes[MAX]; //1 代表不是素数,0 代表是素数
void make_primes()
{
for(int i = 2;i < MAX;i++)
if(!isPrimes[i])
for(int j = i+i;j < MAX;j += i)
isPrimes[j] = true;
}
int main()
{
//初始化 + 读入数据:
make_primes();
int l,r;
scanf("%d %d",&l,&r);
//处理 + 输出:
int num = 0;
int temp = 1;
for(int i = 2;num < r;i++){
if(!isPrimes[i]){
num++;
if(num >= l&&num <= r){
if(temp == 1)
printf("%d",i);
if(temp == 0)
printf(" %d\n",i);
if(temp > 1)
printf(" %d",i);
temp = (temp+1)%10;
}
}
}
return 0;
}
经验:
在通过 oj 时,报出了段错误(我之前定的MAX = 1e4 + 10),是因为自己想当然地将给出的 N 当成了数据范围,而 N 指的是截至到第多少个素数,所以范围一定远大于 10^4。
在发现段错误(我的错误的结果是数组越界)之后,我又想当然的是将全局数组的大小开到最大。因为理论上来说全局数组属于全局变量,最多可以分得几GB,我之前一直将1、2GB认为是比较保守的大小,又因为平时做 oi 基本上开的都是 int 型数组,所以要再除以 4 ,所以我认为开 10^8 次方是没问题的。然而在测评时,我发现我就算开成 10^7 大小还是报了内存超限的错误,所以说有的 oj 的编译器可能并没有给全局区支持很大的空间,这也让我以后尽量开 10^7 以内(保险一点)。
但事实上就算10^8次方都可以开的到,我还是犯了错误,因为题目给的时间限制是200ms,也就是0.2s。因为 2000w 以内的操作数是一定可以保证 1 s内完成,所以要想完成题目要求,要尽量保证操作数在 100w 内,也就是 10^6 内。从这个角度看,我也应该另 MAX = 1e6。所以以后不能觉得自己选的方法高效就大意,不能懒,至少要大致算一下复杂度来估计是否超时。