I came across a question online - to find the Z function of the factorial of t nos (no of zeroes at the lsb end of the factorial)
#include<stdio.h>
int fact(int x)
{
if(x==1)
return 1;
else
return (x*fact(x-1));
}
int main()
{
int t,n,k,c;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
k=fact(n);
c=0;
while(k%10==0)
{
k/=10;
c++;
}
printf("%d\n",c);
}
return 0;
}
This is the program I made, but it's too slow. How can I do this faster?
Looking at your code I can think of two possible solutions at the first glance.
change the recursive loop into an iterative loop
use memoization to speed up calculation of already known function values (basically it works like a cache)
Memoization technique can speed up the calculation significantly, though at the cost of usage of memory.
If I were you I'd do the memoization. I am very confident your code will run faster, since it is a simple factorial function (actually a classic example for memoization, like the Fibonacci numbers).
Related
I want to print sum of the first 1000 prime numbers. I don't know if the following implementation is right and where it is wrong. Moreover, how can I optimize this implementation, which is required for extra off course?
#include<stdio.h>
#include<math.h>
int prime(int no,int lim)
{
int i=2,flag=0;
for(;i<=lim;i++)
{
if(no%i==0)
{
flag=1;
}
}
return flag ;
}
int main()
{
int i=4,count=2,j,k,l,n=4;
double sum=5.0;
for(;count<=1000;)
{
j=sqrt(i);
k=prime(i,j);
if(k==0)
{
//printf("\n%d",i);
sum+=(double)i;
//for(l=0;l<100000;l++);//just to reduce speed of the program
count++;
}
i++;
}
printf("\n%f",sum);
return 0;
}
I don't know if the following implementation is right and where it is wrong.
The implementation is correct except for an off-by-one error: Since count is the number of primes that were already taken into account, the loop condition count<=1000 causes the loop to be run one more time when 1000 primes have already been summed, adding the 1001. prime. Correct is: count<1000.
To optimize your code you better use Sieve of Eratosthenes to generate prime up to your limit, then add these primes. To know how sieve works, read this article.
Actually this is one of the challenges from hackerearth. Here is the link to the problem : https://www.hackerrank.com/challenges/antipalindromic-strings
I somehow figured a way to find the answer. But the problem my code doesn't get accepted due to timeout. Please help me which part makes my code slower.
This is my code :
int anti_palindrome(long int n,long int m,int mod)
{
int prod;
prod=m;
if(n>1)
prod=prod*(m-1);
if(n>2)
{
n=n-2;
while(n)
{
prod=prod*(m-2);
n--;
}
}
return prod%mod;
}
int main()
{
char scanned[1000];
int input = 0;
int T=0;
int T_cur=0;
long int N,M;
char str[1000];
int mod=1000000007;
while(fgets(scanned,1000,stdin))
{
switch(input)
{
case 0: {
T=atoi(scanned);
input=1;
}
break;
case 1: {
T_cur++;
strcpy(str,scanned);
sscanf(str,"%d %d",&N,&M);
//printf("%lf %lf\n",N,M);
printf("%d\n",anti_palindrome(N,M,mod));
}
break;
}
if(T_cur==T)
break;
}
return 0;
}
Any one run of the program may need to process up to 105 N, M pairs, with N and M each between 1 and 109.
Please help me which part makes my code slower.
There aren't many parts to consider. Generally speaking, I/O is much slower than computation, but you haven't any more I/O than is needed, so let's disregard that for the moment.
Consider, then, your anti_palindrome() function. In the general case, it loops N times, performing three arithmetic operations and two assignments in each iteration. That's not expensive on a per-iteration basis, but you may have a billion iterations per test case, and ten thousand test cases, for a total of around 5x1014 mixed operations. That number of operations is going to take more than a few seconds.
While I'm at it, I observe that your algorithm is wrong anyway. You are supposed to report the answer modulo 109 + 7, but long before you get to the end of the computation, you will have overflowed the prod variable. The resulting behavior is undefined. If prod had an unsigned type then the behavior would be defined, but still wrong. Switching to pow() instead of a loop would improve the performance enormously, but would not solve this problem. You need something cleverer.
As m-2 is constant, write m= m-2; before the loop. Now, what remains is that n times prod=prod*m; is executed. This is equivalent to prod= prod*pow(m,n); The math library may have an efficient implementation of pow() that will prevent your timing issue.
In C you may have to cast the parameters to double, and the return value to long int.
int anti_palindrome(long int n,long int m,int mod)
{
int prod;
prod=m;
if(prod>1)
prod=prod*(m-1);
if(prod>2)
{
n=n-2;
m=m-2;
prod= prod*pow(m,n);
}
return prod%mod;
}
What is the benefit to use recursion then loop(for,while,do-while)?
Using Recursion(Here i am getting the sum of a given number, suppose number is 5 then 5 + 4 + 3 + 2 + 1:
#include<stdio.h>
int sum(int n);
void main()
{
int sums =0, n;
scanf("%d",&n);
sums = sum(n);
printf("%d",sums);
while (1)
{
}
}
int sum(int n)
{
if (n==1)
return 1;
return n + sum(n-1);
}
Without recursion(Here i am getting the sum of a given number suppose number is 5 then 5 + 4 + 3 + 2 + 1:
#include<stdio.h>
void main()
{
int sum =0, n;
scanf("%d",&n);
for(int i=n;i>=1;i--)
{
sum = sum + i;
}
printf("%d",sum);
while (1)
{
}
}
You can always make a recursive function an iterative one, and vice versa (Turing said).
In some cases, it's better to use recursion (e.g. traveling on a tree), it's more natural to "think recursively" in such cases. However, if using loops isn't more complicated and much more difficult than a recursion, I prefer them.
Recursion is more costly in memory, but sometimes it clearer and a more readable, using loops increases the performance, but recursion can sometimes be better for the programmer (and his performance).
Deciding what to use - recursion or iteration, depends on what you want to implement, and what's more important for you (readability? performance?), asking recursion or iteration is somehow like asking elegance or performance.
recursion can solve all those problems which can be solved by for loop. But it is difficult or quite impossible to solve some problems by for loop. For example 'json' parsing, 'xml' parsing etc. For this kind of problems you should use recursion. Some dynamic problems can be solved easily by recursion instead of for loop. For a hard problem you do not have to think much solving by recursion instead of for loop. You just form the Recurrence_relation.
I prefer loop over recursive functions. See if this helps : Read it
I have written a small program to calculate the factorial of a number using Dynamic Programming Technique.
#include<stdio.h>
int fact(int n)
{
int f[n],i;
f[0] = 1;
for(i=1;i<=n;i++)
f[i] = i * f[i-1];
return f[n];
}
int main(void)
{
printf("\n Factorial of %d is %d ",5,fact(5));
return 0;
}
Is the approach of memorization correct? Because, dynamic programming involves recursion. But I have not included it here. So I am not sure of my approach.
Yes, your approach of solving the problem is a very simple case of Dynamic Programming, where you store previously solved sub-problems to help you solve the actual problem. While the example you provided would be considered Dynamic Programming, it usually isn't called Memoization
When someone says Memoization, it usually involves in a top-down approach of solving problems, where you assume you have already solved the sub-problems by structuring your program in a way that will solve sub-problems recursively.
You store, or memoize, the results of these sub-problems so that they will not be computed multiple times.
Let me illustrate Memoization through an example:
Here is a simple example of computing the nth Fibonacci of a number:
int fib(int n)
{
if (n <= 1)
return n;
return fib(n-1) + fib(n-2);
}
The above code uses recursion to solve sub-problems (fib(n-1) and fib(n-2)) so that fib(n) can be solved in the end. It assumes that fib(n-1) and fib(n-2) are already solved in the way that it is structured.
Though this code looks elegant, the running time is exponential, because you can solve fib(i), where i is a number less than n, multiple times. You can look at the diagram presented here to see the tree generated by this problem: http://www.geeksforgeeks.org/program-for-nth-fibonacci-number.
To avoid the unnecessary re-computation, Memoization is used to optimizes run-time by using memory.
Here is an optimized example of computing the nth Fibonacci number using Memoization:
/*Global array initialized to 0*/
int a[100];
int fib(int n)
{
/*base case*/
if (n <= 1)
return n;
/*if fib(n) has not been computed, compute it*/
if (a[n] == 0) {
a[n] = fib(n - 1) + fib(n - 2);
}
*/Otherwise, simply get a[n] and return it*/
return a[n];
}
As you can see, the overall structure is not that much different from the recursive solution, but it runs linear time instead of exponential time because fib(i) will only be computed only if we have not computed already.
If I were to use your approach, Dynamic Programming, for the Fibonacci problem, it would look something like this:
int fib(int n)
{
/* just like the array you declared in your solution */
int f[n+1];
int i;
/* set up the base cases, just like how you set f[0] to 1*/
f[0] = 0;
f[1] = 1;
for (i = 2; i <= n; i++)
{
/* using previously solved problem to solve further problems*/
f[i] = f[i-1] + f[i-2];
}
/*return the final result*/
return f[n];
}
There are more subtle differences, trade offs, and implications between Dynamic Programming and Memoization. Some consider Memoization a subset of Dynamic Programming. You can read more about the difference here:
Dynamic programming and memoization: bottom-up vs top-down approaches
Yes this is dynamic programming : going from base cases up to final case. Of course your example (factorial) is too simple so you have been able to simplify many things by yourself : you eliminated the recursion and never use a test in the memoization. But anyway that's it.
For the general scheme of memoization see http://en.wikipedia.org/wiki/Memoization.
For explanation about Dynamic programming see http://en.wikipedia.org/wiki/Dynamic_programming, you will be able to read the section about Fibonacci sequence and its computation using a bottom-up approach.
How do i make this code more efficient for larger numbers of the size 10^9. I don't think i can reduce the number of for loops in this.
#include <stdio.h>
int main(void) {
int e;
int t;
scanf("%d",&t);
for(e=0;e<t;e++){
int x,y;
scanf("%d",&x);
scanf("%d",&y);
int sum=0;
int j,k,i;
for(j=x;j<y;j++){
for(k=j+1;k<=y;k++){
int max=1;
for(i=2;i<=j;i++)
if((j%i==0)&&(k%i==0))
max=i;
sum+=max;
}
}
printf("%d",sum);
}
}
Euclid greatest common divisor algorithm is the most historical and probably the most efficient algorithm for calculating gcd, it may help you for reducing the number of for loops.
If the input size is very huge as you said and you can do some checks for some numbers manually before entering the loop and that may reduce the number loops by 10 times or so before entering.
(Even if in range checking for small numbers will be useful as 2*x == x*2)
Also may be multiples of 10's 5's and so on can be negated in the first loop.
Lot of better algorithm are available on net search a bit more if you cant come with your own
Try adding few comments in your code so it could be more understandable by lesser effort from the people helping you.
NOTE:- I didn't go through your code completely nor most off the people would do.ADD COMMENTS