user3129609
user3129609

Reputation: 57

Prime Generator Algorithm

I've been trying to solve the SPOJ problem of Prime number Generator Algorithm.

Here is the question

Peter wants to generate some prime numbers for his cryptosystem. Help him! Your task is to generate all prime numbers between two given numbers!

Input

The input begins with the number t of test cases in a single line (t<=10). In each of the next t lines there are two numbers m and n (1 <= m <= n <= 1000000000, n-m<=100000) separated by a space.

Output

For every test case print all prime numbers p such that m <= p <= n, one number per line, test cases separated by an empty line.

It is very easy, but the online judge is showing error, I didn't get what the problem meant by 'test cases' and why that 1000000 range is necessary to use.

Here is my code.

#include<stdio.h>

main()
{
int i, num1, num2, j;
int div = 0;
scanf("%d %d", &num1, &num2);
for(i=num1; i<=num2; i++)
  {
    for(j=1; j<=i; j++)
    {
      if(i%j == 0)
      {
        div++;
      }
    }
    if(div == 2)
    {
     printf("%d\n", i);
    }
    div = 0;
  }
  return 0;
}

Upvotes: 3

Views: 10118

Answers (8)

Chris
Chris

Reputation: 27609

I can't comment on the alogirthm and whether the 100000 number range allows optimisations but the reason that your code is invalid is because it doesn't seem to be parsing the input properly. The input will be something like:

2
123123123 123173123 
987654321 987653321

That is the first line will give the number of sets of input you will get with each line then being a set of inputs. Your program, at a glance, looks like it is just reading the first line looking for two numbers.

I assume the online judge is just looking for the correct output (and possibly reasonable running time?) so if you correct for the right input it should work no matter what inefficiencies are in your algorithm (as others have started commenting on).

Upvotes: 4

Uddalak Bhaduri
Uddalak Bhaduri

Reputation: 83

#include <stdio.h>
#include <math.h>
int main()
{
    int test;
    scanf("%d",&test);
    while(test--)
    {
        unsigned int low,high,i=0,j=2,k,x=0,y=0,z;
        unsigned long int a[200000],b[200000];
        scanf("%d",&low);
        scanf("%d",&high);
        for(i=low;i<=high;i++)
            a[x++]=i;
        for(i=2;i<=32000;i++)
            b[y++]=i;
        i=0;
        while(b[i]*b[i]<=high)
        {
            if(b[i]!=0)
            {
                k=i;
                for(;k<y;k+=j)
                {
                    if(k!=i)
                    {
                        b[k]=0;
                    }
                }
            }
            i+=1;j+=1;
        }
            for(i=0;i<y;i++)
            {
                if(b[i]!=0 && (b[i]>=low && b[i]<=sqrt(high)))
                    printf("%d\n",b[i]);
            }
            int c=0;
            for(i=0;i<y;i++)
            {
                if(b[i]!=0 && (b[i]>=1 && b[i]<=sqrt(high)))
                    b[c++]=b[i];
            }
            int m=a[0];
            for(i=0;i<c;i++)
            {
                z=(m/b[i])*b[i];k=z-m;
                if(k!=0)
                    k += b[i];
                for(;k<x;)
                {
                    if(a[k]!=0)
                    {
                        a[k]=0;
                    }
                    k+=b[i];
                }
            }
            for(i=0;i<x;i++)
            {
                if(a[i]!=0 && (a[i]>=2 && a[i]<=(high)))
                    printf("%d\n",a[i]);
            }
        printf("\n");
    }
    return 0;
}

Upvotes: 2

Moriarity
Moriarity

Reputation: 1

#include <iostream>
using namespace std;

int main() {

    // your code here
unsigned long int m,n,i,j;int N;
cin>>N;
for(;N>0;N--)
{
    cin>>m>>n;
    if(m<3)
        switch (n)
        {
            case 1: cout<<endl;continue;
            case 2: cout<<2<<endl;
                    continue;
            default:cout<<2<<endl;m=3;
        }
    if(m%2==0) m++;        
    for(i=m;i<=n;i+=2)
    {  
        for(j=3;j<=i/j;j+=2)
            if(i%j==0)
                {j=0;break;}
        if(j)
        cout<<i<<endl;
    }
        cout<<endl;

}return 0;}

Upvotes: 0

user5450071
user5450071

Reputation: 31

The input begins with the number t of test cases in a single line (t<=10) you haven't got test cases in your programm. Its wrong And sorry for my English

2 - //the number of test cases
1 10 - // numbers n,m
3 5 - // numbers

Your programm will work only in first line.

Upvotes: 2

user5450071
user5450071

Reputation: 31

int num; 
bool singleArray[100000]; 
static unsigned long allArray[1000000]; 
unsigned long nums[10][2]; 

unsigned long s;       
long n1, n2;
int count = 0; 
long intermediate; 


scanf("%d", &num);

for(int i = 0; i < num; ++i) 
{
    scanf("%lu", &n1);  
    scanf("%lu", &n2); 
    nums[i][0] = n1;   
    nums[i][1] = n2;   
}


for(int i = 0; i < 100000; ++i)  
{
    singleArray[i] = true;
}

for(int i = 0; i < num; ++i) 
{
    s = sqrt(nums[i][1]);
    for(unsigned long k = 2; k <= s; ++k)  
    {
        for (unsigned long j = nums[i][0]; j <= nums[i][1]; ++j) 
        {
            intermediate = j - nums[i][0];
            if(!singleArray[intermediate]) 
            {
                continue;
            }
            if((j % k == 0 && k != j) || (j == 1))      
            {
                singleArray[intermediate] = false;
            }
        }
    }


    for(unsigned long m = nums[i][0]; m <= nums[i][1]; ++m) 
    {
        intermediate = m - nums[i][0];
        if(singleArray[intermediate])  
        {
            allArray[count++] = m;
        }
    }

    for(int p = 0; p < (nums[i][1] - nums[i][0]); ++p)
    {
        singleArray[p] = true;
    }
 }


for(int n = 0; n < count; ++n)
{
    printf("%lu\n", allArray[n]);
}

}

Upvotes: 1

MrSmith42
MrSmith42

Reputation: 10151

For such small numbers you can simply search for all primes between 1 and 1000000000.

Take 62.5 mByte of RAM to create a binary array (one bit for each odd number, because we already know that no even number (except of 2) is a prime).

Set all bits to 0 to indicate that they are primes, than use a Sieve of Eratosthenes to set bits to 1 of all number that are not primes.

Do the sieve once, store the resulting list of numbers.

Upvotes: 1

Will Ness
Will Ness

Reputation: 71065

To find primes between m,n where 1 <= m <= n <= 1000000000, n-m<=100000, you need first to prepare the core primes from 2 to sqrt(1000000000) < 32000. Simple contiguous sieve of Eratosthenes is more than adequate for this. (Having sieved the core bool sieve[] array (a related C code is here), do make a separate array int core_primes[] containing the core primes, condensed from the sieve array, in an easy to use form, since you have more than one offset segment to sieve by them.)

Then, for each given separate segment, just sieve it using the prepared core primes. 100,000 is short enough, and without evens it's only 50,000 odds. You can use one pre-allocated array and adjust the addressing scheme for each new pair m,n. The i-th entry in the array will represent the number o + 2i where o is an odd start of a given segment.

See also:

A word about terminology: this is not a "segmented sieve". That refers to the sieving of successive segments, one after another, updating the core primes list as we go. Here the top limit is known in advance and its square root is very small.

The same core primes are used to sieve each separate offset segment, so this may be better described as an "offset" sieve of Eratosthenes. For each segment being sieved, only the core primes not greater than its top limit's square root need be used of course; but the core primes are not updated while each such offset segment is sieved (updating the core primes is the signature feature of the "segmented" sieve).

Upvotes: 1

sebii
sebii

Reputation: 516

Your upper bound is 10^9. The Sieve of Eratosthenes is O(N loglogN) which is too much for that bound.

Here are a few ideas:

Faster primality tests

The problem with a naive solution where you loop over the range [i, j] and check whether each number is prime is that it takes O(sqrt(N)) to test whether a number is prime which is too much if you deal with several cases.

However, you could try a smarter primality testing algorithm. Miller-Rabin is polynomial in the number of bits of N, and for N <= 10^9, you only need to check a = 2, 7 and 61.

Note that I haven't actually tried this, so I can't guarantee it would work.

Segmented sieve

As @KaustavRay mentioned, you could use a segmented sieve. The underlying idea is that if a number N is composite, then it has a prime divisor that is at most sqrt(N).

We use the Sieve of Eratosthenes algorithm to find the prime numbers below 32,000 (roughly sqrt(10^9)), and then for each number in the range [i, j] check whether there is any prime below 32,000 that divides it.

By the prime number theorem about one in log(N) numbers are prime which is small enough to squeeze in the time limit.

Upvotes: 0

Related Questions