Segmented Sieve of eratosthenes algorithm - c

I am trying to solve "PRIME1"(http://www.spoj.com/problems/PRIME1/) on spoj.
A lot of people are saying that I should solve it using Segmented Sieve of eratosthenes. I understood Sieve of eratosthenes but How I can implement Segmented one? I've seen all most all the resources and couldn't understand properly.
This is the code I've written for Sieve of eratosthenes :
#include<stdio.h>
#include<math.h>
int main()
{
long long int i,n,j,m;
_Bool a[10000];
scanf(" %lld",&n);
for(i=2;i<=n;i++)
{
a[i]=1;
}
for(i=2;i<=sqrt(n);i++)
{
for(j=2;i*j<=n;j++)
{
a[i*j]=0;
}
}
for(i=1;i<=n;i++)
{
if(a[i]==1)
printf("%lld\n",i);
}
return 0;
}
From this, How can I implemet Segmented Sieve of eratosthenes. Please explain it in a beginner's perspective.

The idea is very simple:
Start from k=2
Compute where you would fall in after entering the interval; this is simply x=((m + k - 1)/k)*k. For example for m=12345 and k=7 you get 12348 and that's the smallest multiple of 7 greater than or equal to m.
Mark the spot associated to x as "taken" and keep adding k to x until you get past n
Increment k and repeat until you get past sqrt(n)
You don't need to test all values for k but only prime numbers. For that you can use a normal sieve to compute all primes not bigger than sqrt(n) (note that sqrt(1000000000) < 31623 is not a really big number and there are only 3401 primes in that range).
Pay attention to not "marking" x at the start of the inner loop if it happens to be equal to k; the minimum value to consider for x is 2*k.
You can stop at sqrt(n) instead of n because if you have a composite number t<n with t=p*q with p>1 and q>1 then it must be either p<sqrt(n) or q<sqrt(n) and therefore the spot for t has already been marked when you stop at k=sqrt(n).

Related

How to check Big O notation of a sorting algorithm?

I don't know how to solve it's complexity and such. How to know if it is faster than other sorting algorithms?
I find difficulty finding it because I'm a little bit bad at math.
#include <stdio.h>
int func(int arr[])
{
int temp;
int numofarrays=9999;
for(int runtime=1; runtime<=numofarrays/2; runtime++)
{
for(int i=0; i<=numofarrays; i++)
{
if(arr[i] > arr[i+1])
{
temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
}
if(arr[numofarrays-i-1] > arr[numofarrays-i])
{
temp=arr[numofarrays-i-1];
arr[numofarrays-i-1]=arr[numofarrays-i];
arr[numofarrays-i]=temp;
}
}
}
for(int i=0; i<=9999; i++)
{
printf("%i\n",arr[i]);
}
}
int main()
{
int arr[10000];
for(int i=0; i<=9999; i++)
{
arr[i]=rand() % 10;
}
func(arr);
}
The big o notation is where the limit of steps of the code you write goes to infinity. Since the limit goes to infinity, we neglect the coefficients and look at the largest term.
for(int runtime=1; runtime<=numofarrays/2; runtime++)
{
for(int i=0; i<=numofarrays; i++)
{
Here, the largest term of the first loop is n, and the largest term of the second is n. But since loop 2 makes n turns for each turn of the first loop, we're multiplying n by n.
Result is O(n^2).
Here:
for(int runtime=1; runtime<=numofarrays/2; runtime++)
{
for(int i=0; i<=numofarrays; i++)
{
you have two nested for loops that both depends of the array size. So the complexity is O(N^2).
Further you ask:
How to know if it is faster than other sorting algorithms?
Well big-O does not directly tell you about execution time. For some values of N an O(N) implementation may be slower than an O(N^2) implementation.
Big-O tells you how the execution time increases as N increase. So you know that an O(N^2) will be slower than an O(N) when N gets above a apecific value but you can't know what that value is! It could be 1, 5, 10, 100, 1000, ...
Example:
The empirical approach is to time (t) your algorithm for a given input of n. Then do that experiment for larger and large n, say, 2^n for n = 0 to 20. Plot (2^n, t) on a graph. If you get a straight line, it's a linear algorithm. If you get something that grows faster, try graph ln(t) and see if you get a line, that would be an exponential algorithm, etc.
The analytical approach looks scary and sometimes math heavy, but it's doesn't really have to be. You decide what your expensive operation is, then you count how of many of those you do. Anything that runs in loops including recursive functions are the main candidates the run-time of that goes up as the loop runs more times:
Let's say we want count the number of swaps.
The inner loop swap numofarrays times which is O(n).
The outer loop runs numofarrays/2 times which is also O(n) as we drop the factor 1/2 as it's doesn't matter when n gets large.
This mean we do O(n) * O(n) = O(n^2) number of swaps.
Your print loop, is not doing any swaps so we consider them "free", but if determine that they are as expensive as swaps then we want to count those too. Your algorithm does numofarrays print operations which is O(n).
O(n^2) + O(n) is just O(n^2) as the larger O(n^2) dominates O(n) for sufficiently large n.

Find Prime Number 10001 Optimization Questions

So I have created a program that finds the 10,001st prime number. Here is the main for that program:
int main(){
int i;
int j;
int count=0;
int currnumber=0;
for(i=1; count < 10002; i++){
if(isPrime(i)){
count++;
currnumber = i;
if(count == 10002)
printf("%i",currnumber);
}
}
}
And here is the code for the IsPrime function I built in a custom library:
long long isPrime(long long number){
long long i = 2;
if(number == 2)
return 1;
for(i=2;i<number;i++){
if(number % i == 0)
return 0;
}
if(i >= number && ((number % 1 == 0) && (number % number == 0)))
return 1;
}
When I run the program, it works and gives me the correct answer(It's an Euler problem so I know i did it right :D), but it takes at least 6 seconds to process. So my questions are:
Why is it taking that long? Is it something to do with how i've set my algorithm?
How can I potentially improve my code to make it run faster?
Thanks in advance!
Probably the first thing you can do is cache the prime number values you do create, and use the sieve of eratosthenes algorithm in order to not have to constantly recalculate prime number values once you've found them.
You are using two for loops
A faster way which comes to my mind and is also a great exercise is the algorithm called: Sieve of Eratosthenes
There's a lot of optimisations that can be done. A few people have mentioned the sieve of Eratosthenes, which is right, but let me give you some additional pointers.
Improving your code without changing algorithm: As Michael Parker mentioned, you do not need to deal with the even numbers because only one of them is prime (the number 2, which makes it the 'oddest' prime of all -- that's a pun). You can do a similar trick by avoiding multiples of three, which boils down to only dealing with integers i which are either 1 or 5 more than a multiple of 6. To turn that into code, first set count to 3 to account for primes 2, 3, and 5. Then start i at 6 and test both i+1 and i+5 (both within the for loop), and then increment i by 6 every time.
For isPrime() you could add similar improvements but you can also stop trial dividing once you reach the square root of the number. This is because a number has a divisor >= sqrt(number) if and only if it has a divisor <= sqrt(number). To prove this, the key is that if a divides number, then number/a is another divisor (you can fill in remaining details because you are smart).
Improving your code by using Sieve of Eratosthenes: As many have mentioned, the sieve of Eratosthenes is much better for solving this. In fact, it is super-duper fast. But the one issue often overlooked is how big to make your sieve length to be sure that you captured the prime you are after, without making it outrageously large? The Prime Number Theorem gives an estimate to how big it should be. But you will need an upper bound. Suggest using n * (ln n * ln ln n).
If I understand correctly, you are taking every number less than 1001 and checking if it has a common denominator. This is extremely slow. The complexity is actually increasing exponentially. What you should do is combine this method with a sieve. Take any primes you find with the common denominator method and and multiply them from from 1 to n until you have all their multiple between 1 and 10001. That way you will skip testing the common denominator method on multiples of all the prime numbers you have already found. For example, try this:
ArrayList<Integer> List = new ArrayList<Integer>();
ArrayList<Integer> Primes = new ArrayList<Integer>();
Primes.add(2);
Integer p=2;
Integer n=105000;
Integer i=1;
while(p < n) {
i=1;
while((p*i)<=n){
List.add(p*i);
i++;
}
while (p < n){
p++;
if(List.contains(p)){}
else {Primes.add(p); break;}
}
}
System.out.println(Primes.get(10000));

Can I make this C program any faster?

I need to make a program which prints all the prime numbers, here is that I have done:
#include <stdio.h>
int main(void) {
long long t,m,n,i,i2,i3,found;
float p;
scanf ("%lld" , &t);
for (i=1;i<=t;i++) {
scanf ("%lld%lld" , &m ,&n);
for (i2=m;i2<=n;i2++) {
found=0;
for (i3=2;i3<=i2/2;i3++) {
p=(float)i2/i3;
p=p-i2/i3;
if (p==0) {
found=1;
}
}
if ((found==0) && (i2!=1)) {
printf ("%lld\n" , i2);
}
}
printf ("\n");
}
return 0;
}
my time limit is 6 seconds, and with this code it's impossible, also the difference between m and n is 100000 maximum, and 1<=n<=m<=1000000000
There are complicated mathematical algorithms, like the Sieve of Atkin, that can find primes very quickly, but for your purposes, consider:
Every non-prime number is factorable by primes, if factored far enough.
If you've reached the sqrt(n) and still haven't found it to be factorable, then it won't be factorable, because any number larger than sqrt(n) must be factored alongside a number smaller than sqrt(n) to achieve the number you're looking for.
So test every prime number from 2 to sqrt(n) to see if your n is a prime. If none of the primes between 2 and sqrt(n) are factors of n, then n must be prime.
This should meet with the speed requirements of your assignment.
For this problem the constraints (ranges) are very large so better to use Miller–Rabin primality test method.
I changed my mind. You can use Sieve of Eratosthenes algorithm.
Here are the steps to find all prime numbers less than or equal to a given integer n by Sieve of Eratosthenes method:
First create an array of consecutive integers from 2 to n: (2, 3, 4, ..., n).
let p be an integer variable, initialize it with 2, the first prime number.
Starting from p, count up in increments of p and cross out all the multiples of p less than or equal to n (2p, 3p, 4p .... kp <= n).
Take the first number greater than p in the array that is uncrossed. If there is no such number <= n,then stop. Otherwise, assign this new number in p (which is the next prime), and start from step 3.

How to find out how many times the prime number occurs?

I need to write a program to input a number and output it's factorial in the form in C
4!=(2^3)*(3^1)
5!=(2^3)*(3^1)*(5^1)
I am able to find the prime numbers 2, 3 and 5 but how do i figure out how many times they occur? (^3, ^1, ^1)
Code:
int main() {
int num,i,count,n;
printf("Enter to find prime numbers: ");
scanf("%d",&n);
for(num = 2; num<=n;num++) {
count = 0;
for(i=2;i<=num/2;i++) {
if(num%i==0)
{
count++;
break;
}
}
if(count==0 && num!= 1)
printf("%d ",num);
}
return 0;
}
Without going into any code, Ill explain what the problem in the way you are doing things ...
Let us say you want to find the prime factors of the factorial of 5. So you do:
5! = 2 x 3 x 4 x 5 (this is your outer loop (for(num = ...)
Let us say that for a particular iteration, num = 4. Then, you have another iteration in i that checks of each number upto that num/2 is a factor. Now for a small value of 5! this is not a problem. Consider a bigger number like 25!. In this case, your outer loop will be:
25! = 1 x 2 x 3 x ... 22 x 23 x 24 x 25
Now your outer iteration num goes much further. Consider now the number 24. 24/2 = 12. Your program is going to print all factors that divide 24 upto 12, which happen to be 2, 3, 4, 6, and 12. I am sure, that is not what you want.
First, do not attempt to find the factorial for large numbers. You will run into overflow issues. Next, Ill give you some pointers and hope you can solve the problem on your own. Its a very cool problem, so I really hope you are able to solve it:
Study the prime sieve algorithm (http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes). You will not be using this directly, but only the ideas mentioned here.
Create two arrays. The first one will contain the prime factors, while the next one will contain the total count of the factors occuring in the factorial.
For a particular num u need to be iterating not using the i that you have used but using the values in your prime array.
3.1. Use the method explained by Barmar to find the number of times this num is divisible by the factors, and update the corresponding counts in the count array.
Print out the factors and counts that you have obtained.
Finally, I think its a pretty good question. It teaches you how to not run into overflow errors and still be able to solve problem using the computer. It can teach you dynamic memory allocation and memory management skills, if that is the way you want to go. It also helps you to think critically about a problem. You dont deserve a -1. I have increased your rating.
Have fun programming, and keep thinking critically about each setp in your program.
Cheers!
for(num = 2; num<=n; ++num){
count = 0;
while(n % num == 0){
n /= num;
++count;
}
if(count!=0)
printf("(%d^%d)", num, count);
}

i can't figure out the bug in my program for calculating permutations

#include<stdio.h>
#include<conio.h>
main()
{
int i,j,k,x,y,n=4,a[]={1,2,3,4}; //n is the length of the array
for(i=0;i<n;i++)
{
for(k=0;k<(n-2);k++)
{
for(j=(n-1-k);j>=1;j--)
{
y=a[j];
a[j]=a[j-1];
a[j-1]=y;
for(x=0;x<n;x++)
{
printf("%d",a[x]);
}
printf("\t");
}
}
}
getch();
}
Some additional material (I'm a bit drunk, I will probably have to re-edit this tomorrow, so take it with a grain of salt):
Knuth and Sedgewick both covered permutations aeons ago.
Have a look at: http://www.princeton.edu/~rblee/ELE572Papers/p137-sedgewick.pdf
For n items you have n! permutations, so for 13 items you already have 6 227 020 800 permutations. So creating all permutations for a large set of items will become impossible pretty fast.
There are basically two sets of algorithms to create permutations, ranking/unranking and incremental change methods.
With ranking/unranking you have two methods rank and unrank.
Rank will give you the position of a permutation in the genereration order.
Unrank will give you the permutation that lies at integer m, with 0 >= m <= n! and n the amount of items you want to create permutations for.
This is useful for a variety of cases such as:
Creating a random permutation (you just create a random number from 0 to n! and call unrank(randomNumber)) and get the permutation at position randomNumber.
Creating sequences, getting the next permutation: You have a permutation p and call Rank(p) then Unrank(rank+1).
Incremental change methods:
These basically work through swapping and are more efficient than ranking/unranking:
From wikipedia, unordered generation:
function permutation(k, s) {
for j = 2 to length(s) {
swap s[(k mod j) + 1] with s[j]; // note that our array is indexed starting at 1
k := k / j; // integer division cuts off the remainder
}
return s;
}
Change this:
for(k=0;k<(n-2);k++)
to this:
for(k=0;k<(n-1);k++)
Also, try using more descriptive variable names...
I don't know the point of your program, but you may try to read the implementation of std::next_permutation. Generating all permutations with loops is somewhat tricky and I prefer using recursion.

Resources