Segmented sieve is used to generate prime numbers between two ranges.
Conventional method would use time - O(nsqrt(n)),
however sieve uses O(nlogn))
Range where we want to generate prime numbers (a, b):
We first generate prime numbers upto sqrt(b) numbers.
We then use these primes to generate the prime numbers from a to b.

 


#include <iostream>
#include <math.h>
#include <stdio.h>
#include <queue>
#include <stack>
#include <vector>
using namespace std;

// these two arrays are used to generate all primes till sqrt(b)
// we take these arrays as global variables

bool primeCheckTillSqrt[500000];
int primeTillSqrt[100000];

//function to generate the prime numbers till sqrt of the larger numbers of the two

void seive(int n, int &top){

    //we first assume that all numbers are primes
    // and then go on to prune the numbers that are multiples of the primes
    for(int i=1;i<=n;i++){
        primeCheckTillSqrt[i]=1;
    }
    
    primeCheckTillSqrt[1]=0;
    //you might think that these two arrays should make the
    //running time equal to c*n*sqrt(n)
    //but amortized analysis gives the required time.
    for(int i=2;i<=sqrt(n)+1;i++){
        if(primeCheckTillSqrt[i]==1){
            for(int j=i+i ; j<=n; j= j+i){
                primeCheckTillSqrt[j]=0;
            }
        }
    }
    
    top=0;
    for(int i=2;i<=n;i++){
        if(primeCheckTillSqrt[i]==1){
            primeTillSqrt[top++]=i;
        }
    }
    top--;
}

//function to generate primes between a and b.
// we have generated primes till sqrt(b)
// and we use those primes to prune numbers between a and b.

int segmentCheck(int prime[], int a, int b){

    int top1=0;
    int primeCheck[b-a+1];
    int top;
    if(a==2) a=1;
    if(a%2 != 0 && a!= 1) a--;
    seive((int)sqrt(b), top);
    //set all numbers as primes
    for(int i=1;i<=b-a;i++){
        primeCheck[i]=1;
    }
    // go till sqrt of the second number and prune the corresponding entry from the segment
    for(int i=0;i<=top && primeTillSqrt[i]*primeTillSqrt[i]<=b;i++){
        int val= primeTillSqrt[i];
        int j= (a+val-1)/val;
        j=j*val;
        for(j;j<=b;j=j+val){
            if(j>val){
            primeCheck[j-a]=0;}
         //   cout<<j-a<<endl;
        }
    }
    //store prime numbers in array[prime]
    for(int i=0;i<=b-a;i++){
        if(primeCheck[i]==1){
            prime[top1++]=i+a;
        }
    }
    top1--;
    return top1;
}


//test run

int main(){

    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        int a, b;
        cin>>a>>b;
        int primes[200000];
        int number = segmentCheck(primes, a, b);
        for(int i=0;i<=number;i++){
            cout<<primes[i]<<endl;
        }
        cout<<endl;
    }
    return 0;
}