在此代码中,我输入一个测试用例编号t,然后输入t个编号(n)。然后我的代码打印出第n个素数。在函数的第一行,prime(),如果我写if(a > 43000) return;
那么代码完美无缺。但如果我在同一个地方写if(a >= 165000) return;
,则代码块表示该程序已停止工作。但我不明白为什么。
#include <iostream>
#include <cmath>
using namespace std;
int p[15000];
void prime(int a, int i)
{
if(a >= 165000) return;
else {
int q = 0;
int s=sqrt(a), d=3;
while(d<=s){
if(a % d == 0) {
q = 1;
}
d += 2;
}
if(q == 0) {
p[i] = a;
i++;
a += 2;
prime(a, i);
}
else {
a += 2;
prime(a, i);
}
}
}
int main()
{
p[0]=2;
prime(3, 1);
int k, T;
cin >> T;
for(int i = 1; i <= T; i++){
cin >> k;
cout << p[k - 1] << endl;
}
return 0;
}
答案 0 :(得分:1)
首先,我要指出你的阵列p
只有15000个元素,而第15001个素数是163,847。这意味着如果在退出之前检查a >= 165000
,最终会尝试填充数组中超出数组范围的索引。
其次,在进行递归时你应该小心每个人都是对的。每次运行prime()
,您需要为5个新的整数变量a
,i
,q
,s
和{{1}分配空间}。这意味着当你(从你的方法看起来)你真正需要的只是5时,你为成千上万的整数分配内存。
由于看起来这些值与所有其他迭代无关,因此您可以使用几个技巧。首先,对于q,s和d,通过将它们声明为全局变量,它们将仅被分配一次。其次,通过将d
更改为prime(int a, int i)
,您将不会为每个循环分配prime(int &a, int &i)
和a
的内存。这会将您的代码更改为如下所示:
i
其他一些变化:
现在编译并运行给出:
#include <iostream>
#include <cmath>
using namespace std;
const int max_size = 15000 ;
int p[max_size];
int q ;
int s ;
int d ;
void prime(int &a, int &i)
{
if (i>=max_size) return ;
q = 0;
s=sqrt(a) ;
d=3;
while(d<=s){
if(a % d == 0) {
q = 1;
}
d += 2;
}
if(q == 0) {
p[i] = a;
i++;
a += 2;
prime(a, i);
}
else {
a += 2;
prime(a, i);
}
}
int main()
{
p[0]=2;
int a(3), i(1) ;
prime(a, i);
int k, T;
cin >> T;
for(int i = 1; i <= T; i++){
cin >> k;
// You should do a check of whether k is larger than
// the size of your array, otherwise the check on p[k-1]
// will cause a seg fault.
if (k>max_size) {
std::cout << "That value is too large, try a number <= " << max_size << "." << std::endl;
} else {
cout << p[k - 1] << endl;
}
}
return 0;
}