C++ 带c+的素数+;,代码有什么问题,如何优化?
我试图解决这个问题,我需要以最快的方式找到介于1到3501之间的素数,因为时间限制可能不会超过1秒 我计算这些素数的方法是检查它们在平方根之前是否为素数,然后消除第一个素数的倍数[2,3,5,7],以提高算法的性能。然而,时间已经超过了 我的代码(采用1.560s作为提交系统的内部测试)C++ 带c+的素数+;,代码有什么问题,如何优化?,c++,C++,我试图解决这个问题,我需要以最快的方式找到介于1到3501之间的素数,因为时间限制可能不会超过1秒 我计算这些素数的方法是检查它们在平方根之前是否为素数,然后消除第一个素数的倍数[2,3,5,7],以提高算法的性能。然而,时间已经超过了 我的代码(采用1.560s作为提交系统的内部测试) #包括 #包括 #包括 #包括 #包括 #包括 使用名称空间std; 设立保监会; 设置素数; /*计算列表素数*/ 无效n_素数(整数qtd){ int a,flag=1,l_素数=1; 浮动n; 对于(in
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
设立保监会;
设置素数;
/*计算列表素数*/
无效n_素数(整数qtd){
int a,flag=1,l_素数=1;
浮动n;
对于(int i=0;i7)
而(l|u素数%2==0 | l|u素数%3==0 | l|u素数%5==0 | l|u素数%7==0)l|u素数++;
n=sqrt(l_素数);
对于(a=2;a而言,最简单的方法是,以下是我的实现:
//return the seive of erstothenes
std::vector<int> generate_seive(const ulong & max) {
std::vector<int> seive{2};
std::vector<bool> not_prime(max+1);
ulong current_prime = seive.back();
bool done = false;
while(!done){
for (int i = 2; i * current_prime <= max;i++) {
not_prime[i*current_prime]=true;
}
for (int j = current_prime+1;true;j++) {
if (not_prime[j] == false) {
if( j >= max) {
done = true;
break;
}
else {
seive.push_back(j);
current_prime = j;
break;
}
}
}
}
return seive;
}
有一种更好的求素数的算法。你听说过吗
此外,您在代码中使用了大量STL(即集合)和余数操作。这只会降低程序的速度。一些基本建议,然后是一个基本(尽管未经测试)答案
建议:如果您有一个非常有限的资源,请利用其他资源。在这种情况下,由于时间有限,会占用大量空间。不要动态分配任何内存,而是将其全部设置为固定长度数组
我的方法是简单地使用一个布尔数组,并对其应用Aristophanes筛:
void findPrimes(int cap) { // set to void for now, since I don't know your return type
bool[] possibilities = new bool[cap + 1]; // has to be dynamic so that you can scale for any top
possibilities[0] = false;
possibilities[1] = false;
int found = 0;
for (int i = 2; i < cap; ) {
++found;
for (int j = i + i; j < cap; j += i) {
possibilities[j] = false;
}
do {
++i;
} while (!possibilities[i]);
}
// at this point, found says how many you've found, and everything in possibilities that is true is a factor. Just return it however you need.
void findpremes(int cap){//暂时设置为void,因为我不知道您的返回类型
bool[]posabilities=new bool[cap+1];//必须是动态的,以便可以缩放任何顶部
可能性[0]=假;
可能性[1]=错误;
int=0;
对于(int i=2;i
我看到aaronman用筛子的想法击败了我。我的是一个稍微不同的实现(更像原来的筛子,只使用加法),并使用更少的动态内存,因此我仍在提交它。通过预先排除偶数,您可以获得相当好的加速,只需将增量更改为I+=2
,并确保在结果数组中不忽略2。您甚至可能会考虑预先排除3的倍数,但这会开始变脏nes:
for(long i = 1; i < qtd; i += 6) {
//check if i is prime
//check if i+4 is prime
}
for(长i=1;i
这应该足以让您低于限制。正如其他人所建议的那样,Eratosthenes筛子是正确的方法。但是我在这里看到的实现非常复杂。筛子非常容易实现。例如:
std::vector<int> get_primes(uint max) {
std::vector<int> primes;
std::vector<bool> is_composite(max+1,false);
for (uint i = 2; i <= max; ++i) {
if (!is_composite[i]) {
primes.push_back(i);
for (uint j = i+i; j <= max; j += i) {
is_composite[j] = true;
}
}
}
return primes;
}
std::向量get_素数(uint max){
向量素数;
std::向量是_复合的(max+1,false);
对于(uint i=2;i,代码中有两个大的技术性能损耗:
将素数插入向量。每当向量超过其分配的大小时,它将获得一个新的、更大的缓冲区,复制所有内容并删除旧的缓冲区。new
在性能方面非常昂贵,甚至比所涉及的复制更昂贵。您可以通过告诉向量reserve()
足够的空间
在内部循环中使用sqrt()
。这也是一个缓慢的函数,取而代之的是平方素数(在现代硬件上只需要一个周期),它会更快
只需使用它,这是ErasoStes筛选器的一个优化版本。但是对于你的小范围,很可能速度差只有三分之一。BTW如果你喜欢这样的问题,你应该真的尝试STL没有什么问题,在大多数情况下使用它会大大提高你的代码是什么意思?“模块操作”?你知道什么[漂亮]结构隐藏在集合后面?这里的问题是它完全不相关——你可以使用一个简单的数组。STL是否改进了你的代码是另一个话题。当然它对你有很大帮助。但是,如果你想要最快的解决方案,最好自己实现所有内容。@DavidBrown我指的是余数(或模数)谢谢,我会纠正它。@亚森我并没有说你应该使用一套,但是STL数据结构一般不会减慢你的代码的任何数量,任何C++专家都会告诉你总是喜欢C标准样式的标准库中的东西,或者你可能会想到在T之前预先排除每个素数的倍数。他是你正在考虑的一个…但是你会是Eratosthenes.:-p你的代码实现至少排除了3和19。不,筛选意味着必须从字段中标记出数字并始终检查标记,或者压缩一个数字数组,这更慢。我认为,他的基本方法很好,可以轻松改进已充分禁用。@ScottMermelstein如果您记得事先将其添加到结果数组中,则不需要。19=3*6+1,这已被选中。这很好,但没有实现is_compositeabout 1:重新分配和复制的次数太少,以至于与最终性能完全无关(如毫秒)。使用reserve()
还是有道理的,只是说它对这里的慢度没有真正的帮助。有人想告诉我为什么-1?不是我,但你确实完全拼写了Eratostheneswrong@aaronman责怪谷歌!:->如果你输入“ar筛选”,它会自动将其填写到“aristophanes”并链接到
for(long i = 1; i < qtd; i += 6) {
//check if i is prime
//check if i+4 is prime
}
std::vector<int> get_primes(uint max) {
std::vector<int> primes;
std::vector<bool> is_composite(max+1,false);
for (uint i = 2; i <= max; ++i) {
if (!is_composite[i]) {
primes.push_back(i);
for (uint j = i+i; j <= max; j += i) {
is_composite[j] = true;
}
}
}
return primes;
}