在m和n之间生成素数[重复]

Posted

技术标签:

【中文标题】在m和n之间生成素数[重复]【英文标题】:Generating prime numbers between m and n [duplicate] 【发布时间】:2014-05-22 13:38:01 【问题描述】:

这是spoj.com上的练习题http://www.spoj.com/problems/PRIME1/..

我的提交给出了“超出时间限制”

约束是:1

我根据eratosthenes的筛子写了如下代码,

void sieve(int m,int n)

       bool prime[1000005]; 
        bool prime2[1000005];
  int i;
    int k;

   prime[0]=1;
   prime[1]=1;

   int mi=sqrt(n);

   for (int i=2; i<=mi; i++)
      if (prime[i]==0)
         for ( k=i*i; k<=n; k+=i)
            
                if(k<=mi)
            prime[k]=1;

            if(k>=m)
            

            prime2[k-m]=1;
            

            


    int u=min(n,(int)1000000);
   for(i=0;i<u;i++)

    if(prime2[i]==0 && i+m>=2 && i+m<=n)
    printf("%d\n",i+m);
   
            printf("\n");



这里的“m”和“n”是我们必须生成素数的数字范围。

我面临的问题是当我将输入作为 100000000 100100000 运行需要 1.04 秒 (ideone.com C++ 4.3.2) 和 10000000 10100000 需要0.07秒

1)为什么时代差异如此之大,是什么原因造成的?

2) 有没有更快的方法来解决这个问题?

【问题讨论】:

不要每次都重新计算筛子,计算一次,然后对每个输入进行迭代。代码也有点乱,首先你声明 i,然后在 for 循环中隐藏它,u 检查没有多大意义,等等。 -EDIT- 等等!您是否每次都认真地从 0 迭代到最大值并检查该索引是否在范围内? 真的这样缩进你的代码吗?你发在这里的时候不觉得丢脸吗?你没有想到“嗯,我在公开发布这个并要求人们免费查看它,所以也许我应该让它看起来不像撒旦的后路,更像是快乐的 C++ 代码?” @user2657257:你有很多关于编程的知识——仅仅因为某些东西似乎可以工作并不意味着它没有错误。您肯定可以看到这些数组从未初始化,因此您有未定义的行为? @Dukeling 好吧,Erastothenes 筛子的复杂度为O(n log log n),你有 6 秒的时间来完成这项任务。对其进行惰性评估非常非常低效,因此通过消除过程,您只需要计算完整的筛子(并享受所述算法的相当好的缓存行为),然后对其进行迭代。 @user2657257 在调试模式下可以。在发布时,绝对不是。 【参考方案1】:

1) 为什么时代差异如此之大,是什么促成了 这 ?

时间差异即将到来,因为两个范围内构建筛子所需的时间不同。更大的数字会更高。

2) 有没有更快的方法来解决这个问题?

如 cmets 中所述,您正在计算每个测试用例的筛子。您只需要构建一次筛子,并且最多只能构建 sqrt(1000000000) = 100000。

我的解决方案(很久以前)如下:

#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <iterator>

bool is_prime (const int& n, std::vector<int>& v);

int main() 
  int t;
  std::cin >> t;
  std::vector<int> prime_array;

  // build the sieve
  for (int i=2; i<=100000; i++)
    if ( is_prime( i, prime_array ) ) 
        prime_array.push_back( i );

  while (t--) 
    long long m;
    long long n;

    std::cin >> m;
    std::cin >> n;

    if (m<2) m = 2;

    //check for the prime numbers in the range.
    for (int i=m; i<=n; i++)
      if ( is_prime( i, prime_array ) ) 
        std::cout << i << std::endl;
    std::cout << std::endl;

  
  return 0;



// we need to check for prime factors up to sqrt(n)
bool is_prime (const int& n, std::vector<int>& v) 
  double root = sqrt (n);
  std::vector<int>::iterator it = v.begin();
  while ( it != v.end() && *it <= root ) 
    if (!( n % *it)) return 0;
    it++;
  
  return 1;

【讨论】:

修改了我的代码,正如你所建议的那样,被接受了。有点慢,但现在可以了

以上是关于在m和n之间生成素数[重复]的主要内容,如果未能解决你的问题,请参考以下文章

4 列表中的素数

求m至n之间的所有素数(编程)

C语言m~n之间的素数

素数和

素数和

素数和