Can I make this C program any faster? - c

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.

Related

I wonder what's the explanation of the for loop for(i=2; i<=Number/2; i++)

Hi I have a code for getting prime numbers from a specific range, I'm analyzing it since its from the internet, I just wonder what the for loop for(i=2; i<=number/2; i++);. Why does it start with two and what's the reason behind why i<=number/2 is the condition. Here is the full code below, I hope you can help me.
#include <stdio.h>
int main()
{
int i, Number, count, Minimum, Maximum;
printf("\n Please Enter the Minimum & Maximum Values\n");
scanf("%d %d", &Minimum, &Maximum);
printf("Prime Numbers Between %d and %d are:\n", Minimum, Maximum);
for(Number = Minimum; Number <= Maximum; Number++)
{
count = 0;
for (i = 2; i <= Number/2; i++)
{
if(Number%i == 0)
{
count++;
break;
}
}
if(count == 0 && Number != 1 )
{
printf(" %d ", Number);
}
}
return 0;
}
2 is the lowest possible factor of a composite (1 is a factor of primes, remember).
Number/2 is an upper bound for the smallest factor. I say an upper bound, because a better bound would be sqrt(Number). Reasoning: any factor p that's greater than √N must have a corresponding factor q = N/p which must be less than √N.
Why does it start with two and what's the reason behind why
i<=number/2
That lower and upper bound is about performance i.e., reducing the number of iterations that you need to compute.
It starts in 2 because:
A prime number (or a prime) is a natural number greater than 1
It ends in Number/2 because if Number is a prime number until Number/2 then after that will still be a prime number.
The reason is as follows, "If a number n is not a prime, it can be factored into two factors" so that Number = a * b. So either a or b has to be at least 2 or larger. Therefore, you can set the upper bound to Number/2.
From prime number theory we know that actually if Number is a prime number until sqrt(Number) then it will still be a prime number after. From source one can read:
If a number n is not a prime, it can be factored into two factors
a and b:
n = a * b
Now a and b can't be both greater than the square root of n,
since then the product a * b would be greater than sqrt(n) * sqrt(n) = n. So in any factorization of n, at least one of the
factors must be smaller than the square root of n, and if we can't
find any factors less than or equal to the square root, n must be a
prime.
for (Number = Minimum; Number <= Maximum; Number++)
# This for loop is traversing all numbers in the range of the minimum and maximum number
for (i = 2; i <= Number / 2; i++)
# This for loop is checking if the number is divisible by any number starting from 2
For example, this can be used checking if number is prime number.
Take i <= Number / 2 as the loop condition.
If Number = 11 then this for loop will begin diving the number starting from 2. So the value of i will go from 2 to Number / 2, which is 5.
This improves the performance of the loop by reducing the amount of required iterations.
for loops must follow a specific structure.
The first statement (i=2) states that the counter must start at 2. The second statement (i <= Number/2) means the loop will continue whilst that statement is true. The final statement (i++) increments the variables i by 1 each time the loop runs.
So in this example, i starts at 2, then will increase by 1 each time until i is greater than Number before continuing to the remainder of the program.
First, 2 is the lowest factor of a composite while Number/2 is the highest limit in the condition starting from 2 to Number/2. We can stop at Number/2 because if Number is prime until then it will still remain prime after Number/2 to Number as well.
The point of using such limits is to improve performance by reducing loop count.

Find the worst case running time of this algorithm for checking if a number is divisible by 3

I wrote this algorithm for checking a number's divisibility by 3. It works by first checking if the input N is a single digit number. If N is not a single digit number, the sum of its digits is calculated and assigned to N. The outer while loop iterates until the number of digits n is equal to 1. Then the program checks if the final value of N is equal to 0, 3, 6 or 9, in which case N is divisible by 3.
e.g. When N=5432157 and n=7, then N=5+4+3+2+1+5+7=27 and n=2, then N=2+7=9 and n=1. Thus, the outer while loop iterates 3 times.
#include <stdio.h>
main(){
int N,n=0,rN,sum=0;
printf("Enter the number: ");
scanf("%d",&N);
rN=N;
while(n!=1){
n=0;
sum=0;
while(N>0){
sum+=N%10;
N/=10;
n++;
}
N=sum;
}
if(N==0||N==3||N==6||N==9){
printf("\n%d is divisible by 3.",rN);
}
else{
printf("\n%d is not divisible by 3.",rN);
}
}
For the worst case analysis, I have assumed that all the digits of N are equal to 9. What I have observed is that for number of digits n less than 11, the outer while loop iterates a maximum of 3 times. For n greater than or equal to 11 but less than 10^11, the loop iterates a maximum of 4 times. I tried out a few cases for n greater than or equal to 10^11, and saw that outer loop iterates 5 times. I have not been able to find a general formula for this case. Also, for the inner while loop, which iterates n(number of digits in current value of N) times for each iteration of the outer while loop, how does n decrease with each iteration of the outer while loop?
If you observe carefully, each of your (outer) iteration takes log(N_current) steps. With each step your number also becomes log(N) (or 9*log(N) to be precise).
The outer iterations will go on till the N_current has 1 digit.
So your total complexity will be -
log(N) + log(log(N)) + log(log(log(N))) + ... + 1 ; (1)
The number of iterations would be log*N.
Now, I do not know how to reduce (1) but if you over approximate and consider each step to be log(N), you can write the complexity as
O(log(N) * log*(N))
(Mind the capital O)

Program to disintegrate a number into fibonacci numbers

I am struggling to write a program in C.
I want to disintegrate a number (only if it can be disintegrated) into a smaller numbers which can only be fibonacci numbers.
For example :
If I have a number n = 20 then my output should be 1,1,2,3,5,8 so when I add these smaller fibonacci numbers it gives me number 20.
Every integer has a representation as a sum of unique Fibonacci numbers. This is easy to prove by induction: if such a representation exists for all numbers up to Fib(n), then Fib(n)+k for k in 1, 2, ..., Fib(n-1) has the representation of Fib(n) + (representation for k). The proof suggests a simple recursive algorithm for finding the presentation for N: pick the greatest Fibonacci number that is less than N, say it's Fib(k). Then find the representation for N-Fib(k).
It can be reduced to subset-sum problem, where the set is the fibonacci numbers smaller/equals the given number.
First generate all numbers smaller/equals the given number n. C-like pseudo code:
int i = 1;
int* arr = //sufficiently large array
arr[0] = arr[1] = 1;
while (arr[i] <= n) {
i++;
arr[i] = arr[i-1] + arr[i-2];
}
After this, you have arr that contains all "candidates", and need to invoke subset-sum algorithm to solve it, using the following recursive calls
D(x,i) = false x<0
D(0,i) = true
D(x,0) = false x != 0
D(x,i) = D(x,i-1) OR D(x-arr[i]-1,i)
You later, just need to retrace your steps and find out the actual number used by the DP:
Pseudo code:
x = n;
i = number_of_candidates;
while (i>0) {
if (x >= arr[i] && DP[i][x-arr[i]]) {
//arr[i] is in the solution, add it
x = x-arr[i];
}
i--; //do it for both cases, successful 'if' or not.
}
Total complexity of the answer is O(nlogn), and the bottleneck is the DP solution.
Note that the number of "candidates" is in O(logn), since the ith fibonacci number is in O(phi^i).

Segmented Sieve of eratosthenes algorithm

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).

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));

Resources