C++ SPOJ PRIME1:TLE

C++ SPOJ PRIME1:TLE,c++,algorithm,primes,sieve-of-eratosthenes,sieve,C++,Algorithm,Primes,Sieve Of Eratosthenes,Sieve,我尝试为这个[问题]实现分段筛选算法:http://www.spoj.pl/problems/PRIME1/ 详情如下: #include <iostream> #include <string> #include <set> #include<math.h> #include<vector> #include<cstdlib> #include<cstdio> #include<cstring> #

我尝试为这个[问题]实现分段筛选算法:http://www.spoj.pl/problems/PRIME1/ 详情如下:

#include <iostream>
#include <string>
#include <set>
#include<math.h>
#include<vector>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cstdio>
#define MAX 32000 // sqrt of the upper range
using namespace std;
int base[MAX];  // 0 indicates prime

vector<int> pv;   // vector of primes

int mod (int a, int b)
{
   if(b < 0)
     return mod(-a, -b);   
   int ret = a % b;
   if(ret < 0)
     ret+=b;
   return ret;
}
void sieve(){

     for(int i = 2 ; i * i < MAX ; i++ )
        if(!base[i])
           for(int j = i * i ; j <  MAX ; j += i )
                 base[j] = 1;

     for(int i = 2 ; i < MAX ; i++ )
         if(!base[i]) pv.push_back(i);

}
int fd_p(int p ,int a ,int b){  // find the first number in the range [a,b] which is divisible by prime p

/*  while(1){

        if(a % p == 0 && a !=p) break;
    a++;
    }
    return a;
*/  

    if(a != p){
        return (a + mod(-a,p)) ;

    }
    else{
     return (a + p);
    }

}
void seg_sieve(int a , int b){

    if(b < 2 ){ 
        cout << "" ;
    return;
    }
    if(a < 2){
      a = 2; 
    }
    int i,j;
    int seg_size  = b - a + 1;
    int*is_prime = new int[seg_size];
    memset(is_prime,0,seg_size*sizeof(int));

    vector<int> :: iterator p ;


    for(p = pv.begin(); p!=pv.end(); p++){
       int x = fd_p(*p,a,b);  

       for(i = x; i <= b; i += *p )
           is_prime[i - a] = 1;
      }

for(i=0; i < b - a + 1; i++)
    if(!is_prime[i])
        printf("%u\n", i + a);

 delete []is_prime ;
}


int main()
{
     sieve();
     int a,b,T;
     scanf("%d",&T);

     while(T--){
     scanf("%d%d",&a,&b);
     seg_sieve(a,b);
     printf("\n");   
     }
//     cout<<endl;
//     system("PAUSE");
     return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义上限的最大32000//sqrt
使用名称空间std;
整数基[MAX];//0表示素数
向量pv;//素数向量
内部模式(内部a、内部b)
{
if(b<0)
返回模式(-a,-b);
int ret=a%b;
如果(ret<0)
ret+=b;
返回ret;
}
空隙筛(){
对于(int i=2;i*icout你可以得到区间[a,b]中的第一个数字,这个数字在固定时间内可以被p整除。试着这样做,我认为你应该很乐意去做。

我在很多年前就解决了这个问题。假设,n-m你已经离开了最后一步的改进。只考虑几率

我们知道
2
是素数,并且我们知道没有偶数(2除外)是素数,所以不需要检查它们

奇数素数的Eratosthenes筛是p={3,5,…}\U{p2,p2+2p,…}| p inp。实现这一点就足以让您通过:

  • 2
    作为一个单独的案例进行特殊处理。使用正常大小一半的数组,其中偏移量
    i
    处的数组条目表示奇数
    ao+2*i
    ,其中
    ao=a | 1
    是不低于
    a
    的最小奇数。这意味着2p的增量值对应于增量在数组中的偏移量中的p

  • 偏移筛阵列中素数
    p
    的起始奇数倍等于或大于
    p*p
    ,为
    m=p*p>=ao?p*p:((ao+p-1)/p)*p、 m=m&1?m:m+p;
    ,前提是
    p问题在于fd\u p函数太慢,增加a直到找到一个合适的值来启动筛选肯定会超时,因为a可能在10亿范围内

    不过你的想法是对的

    请参阅本博客文章,了解更易于理解的工作代码解释:


    请参见>.plz查看编辑的代码:[concept]让n=a+x为所需的数字..因此我们希望n%p=0或(a+x)%p=0,所以[ans=(-a%p)+a]终于让它工作了..谢谢..嘿,谢谢,但是我通过使fd_p函数在恒定时间内运行得到了代码的接受..:).不需要将2作为一个单独的案例来处理..但是我也会尝试实现你的方法。
     program prime1;
      Var
       t:longint;
       m,n:longint;
       i,j,k:longint;
       prime:array of longint;
       bool:boolean;
    begin
     SetLength(prime,1);
     prime[0]:=2;
     for i:=3 to 40000
      do begin
       j:=0; bool:=true;
       while (prime[j]*prime[j]<= i ) do begin
         if (i mod prime[j] = 0) then begin
          bool:=false;
          break;
         end;
         inc(j);
       end;
       if (bool) then begin
        SetLength(prime,length(prime)+1);
        prime[length(prime)-1]:=i;
       end;
     end;
     readln(t);
     for k:=1 to t do begin
      readln(m,n);
      for i:=m to n do begin
       if (i=1) then continue;
       j:=0; bool:=true;
       while (prime[j]*prime[j]<= i ) do begin
         if (i mod prime[j] = 0) then begin
          bool:=false;
          break;
         end;
         inc(j);
       end;
       if (bool) then
         writeln(i);
      end;
      writeln;
     end;
    end.