How does this Codechef Factorial Solution in C work? - c

I'm trying to understand how this code:
#include<stdio.h>
int main()
{
int j,p,k;
long long int n,i;
scanf("%lld",&n);
for(k=n;k>=1;k--)
{
p=0;
scanf("%lld",&i);
for (j=5;j<=i;j*=5)
{
p=p+i/j;
}
printf("%d\n",p);
}
return 0;
}
solves this Codechef problem: http://www.codechef.com/problems/FCTRL
What I'm having troubles understanding is how this loop works:
for (j=5;j<=i;j*=5)
{
p=p+i/j;
}
Why is the j variable set to 5 and could someone walk me trough this loop if I would give the value of 60 to the i variable?
Thanks so much!

In short the problem is to find the number of zeroes of a factorial of number between 1 to 1000000000.
Now take a pencil and a paper. Start with 1. From 1 to 4 there is no 0. First 0 occurs at 5!. The next is at 10! and then at 15!, 20!, ...... This means that number of zeroes increases at the interval of 5.
Coming to the loop
for (j=5;j<=i;j*=5)
{
p=p+i/j;
}
See the i is stand for N here (see the question). Since number of zeroes increases at the interval of 5, j is initialized to 5 and j will be incremented as a multiple of 5 .
Now the simple rule is that the number of trailing zeros in the decimal representation of N! is simply the multiplicity of the prime factor 5 in N!.
In the statement p=p+i/j;, same rule is followed. The author of the program incremented j by 5 till N/j >= 5 leaving N (i.e i) here as it is.
N = i = 30
p = 30/5 + 30/(5*5) = 6 // 30/25 is 1 and does not satisfying the condition N/j >= 5

This algorithm makes more sense if you understand the method they are using to find the number of trailing zeros of a factorial which is outlined in Trailing zero Factorial and in Factorials and Trailing Zeroes. Basically relies on the insight that you need to account for all the products of 5 and 2 in the factorial expansion to discover how many zeros there will be in the end.
The algorithm to finding the number of trailing zeros in x! boils down to to:
Finding successive powers of 5
Dividing x by the result add the truncated result to the total
Stop when the result of division is less than 1 or in this specific case we know this will happen when the result is greater than x
So if go back to the code we can find the following steps:
step 3
| step 1
V V
for (j=5;j<=i;j*=5)
{
p=p+i/j; // step 2
}

This piece of code:
p=0;
scanf("%lld",&i);
for (j=5;j<=i;j*=5)
{
p=p+i/j;
}
counts the number of factor 5 in all the integers in [1, i] and stores the result in p.
Loop 1: j=5, p+=i/5 counts numbers that are divisible by 5 in the range [1, i]
Loop 2: j=25, p+=i/25 counts numbers that are divisible by 25 in the range [1, i] (notice that such numbers have been already counted once in loop 1)
Loop 3: j=125, p+=i/125 counts numbers that are divisible by 125 in the range [1, i] (notice that such numbers have been already counted twice in loop 1 and 2)
....

Related

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)

Prime numbers in C

ok i have a very easy problem.we must find all the prime numbers that have at least 2 digits (11 is the first prime number).We must define the maxnumb.what the professor did .
#include <stdio.h>
#define MAXNUMB 100
int main (void)
{
int i,j;
for (i=11 ; i<MAXNUMB; i+=2)
{
for (j=3;j*j<=i;j+=2)
{
if (i%j==0)
{
break;
}
}
if (j*j>i)
printf(''%d is prime\n'',i);
}
}`
so I have 3 questions
we use "i=11" because we want only the two digits primes but why j=3 and not j=11
8th line "j*j<=i; why he did that?what we gain?
why we have this if (j*j>i) and not something (j==i)
why j=3 and not j=11
Because j is your candidate divisor. You need to try all divisors up to square root except 2, which has been eliminated by construction of the algorithm (you start with 11 and go up by 2, so you see only odd numbers; no need to check divisibility by 2).
8th line j*j<=i; Why he did that? What we gain?
If you tried all numbers up to and including the square root of the candidate prime, and found no divisors, then there would be no divisors above the square root as well. This saves you a lot of unnecessary iteration.
why we have this if (j*j>i) and not something (j==i)
The loop terminates under two conditions: (a) you reach a break, or (b) j goes past the square root of i. If you reached break, it means you found a divisor; if you reached past the square root, you didn't.
First of all, the theory behind it:
is a prime number if there is no other factor like in , which .
In your code, you are following the same path. The inner loop is trying all possible less than or equal to .
we use "i=11" because we want only the two digits primes but why j=3 and not j=11
Based on what I just said, you should ask why ! not ? The answer is simple! j is a factor in i (e.g. 3 a factor in 12=3*2*2) In this code in order to make it even faster, you just skipped all even numbers (i+=2), then you don't need j=2 to check if 'i' is dividable by j.
8th line "j*j<=i" why he did that?what we gain?
why we have this if (j*j>i) and not something (j==i)
Both questions are related to this part: .
Trial Division Theorem:
The most basic method of checking the primality of a given integer n is called trial division. This routine consists of dividing n by each integer m that is greater than 1 and less than or equal to the square root of n.
Hence, lets check primality of 37.
floor(sqrt(37)) = 6
So, check from 2 to 6, weather 37 is divisible by any of number in between. If 37 is not divisible by any number, then number is prime.
So, in your example:
floor(sqrt(11)) = 3 that's why started j = 3,
Also, instead of performing sqrt on i, we have considered square of j i.e. j*j <= i;
And, for last question answer by #dasblinkenlight is best.
we use "i=11" because we want only the two digits primes but why j=3 and not j=11
i is the number which is to be checked whether it is prime or not (since you need 2 digit numbers only so initially i=11) and your code is doing that by checking divisibility of i with j. So j should start from 2 but as your code neglects all even number due to i+=2 (initially i=11 so due to i+=2 increment in loop we have values of i=11, 13, 15,.. only odd numbers) so there is no need to check divisibility of i with 2. Therefore initial value of j is 3.
8th line "j*j<=i; why he did that?what we gain?
It could be written as j<=sqrt(i) also. Assume i=N^2 so if N is divisible by j then N^2 is also divisible by j. So instead of checking divisibility of i or N^2 with j till j<i or j<N^2 we are limiting it to j<=sqrt(i) or j<=N which decrease the number of operations of divisibility check and hence decrease the execution time of program.
Assume i=21 then is j=sqrt(i) evaluates j to be 4 (note j is int value so sqrt(21) result to be 4 instead of a float value 4.58). So program will check divisibility of i=21 with j<=sqrt(i) that is j=3(initial value) and 4(4<=sqrt(21)) instead with j<i that is j=3(initial value), 4, 5,... 20(20<21) which results in fasting the program.
We can also use j<=pow(i,(1/3 or 1/4 or 1/n)) but this would be better after extremely high values of i (like >10^6) and would not work for smaller values.
why we have this if (j*j>i) and not something (j==i)
It is because of the previous point.
Instead of checking divisibility of i or N^2 with j till j<=i or j<=N^2 we are limiting it to j<=sqrt(i) or j<=N which decrease the number of operations of divisibility check and hence decrease the execution time of program.
Hence if divisibility checking crosses the value j*j>i or j>sqrt(i) without having remainder equals to 0 or i%j==0 to be false then i is proved to be prime and gets printed.

Interesting Powers Of 2 - algorithm/ Math (from Hackerrank ACM APC)

I came across a problem from a recent competition.
I was unable to figure out a solution, and no editorial for the question is yet available.
Question Link
I am quoting the problem statement here also in case the link doesn't work.
Find the number of integers n which are greater than or equal to A and less than or equal to B (A<= n <=B) and the decimal representation of 2^n ends in n.
Ex: 2^36 = 68719476736 which ends in “36”.
INPUT
The first line contains an integer T i.e. number of test cases. T lines follow, each containing two integers A and B.
Constraints
1 <= T <= 10^5
A<=B
A,B <= 10^150
OUTPUT
Print T lines each containing the answer to the corresponding testcase.
Sample Input
2
36 36
100 500
Sample Output
1
0
As often happens on programming competitions I have come up with an heuristics I have not proven, but seems plausible. I have written a short program to find the numbers up to 1000000 and they are:
36
736
8736
48736
948736
Thus my theory is the following - each consecutive number is suffixed with the previous one and only adds one digit. Hope this will set you on the right track for the problem. Note that if my assumption is right than you only need to find 150 numbers and finding each consecutive number requires checking 9 digits that may be added.
A general advice for similar problems - always try to find the first few numbers and think of some relation.
Also often it happens on a competition that you come up with a theory like the one I propose above, but have no time to prove it. You can't afford the time to prove it. Simply hope you are right and code.
EDIT: I believe I was able to prove my conjecture above(in fact I have missed some numbers -see end of the post). First let me point out that as v3ga states in a comment the algorithm above works up until 75353432948736 as no digit can be prepended to make the new number "interesting" as per the definition you give. However I completely missed another option - you may prepend some number of 0 and then add a non-zero digit.
I will now proof a lemma:
Lemma: if a1a2...an is an interesting number and n is more than 3, then a2...an also is interesting.
Proof:
2a1a2...an = 2a1*10n - 1*2a2a2...an
Now I will prove that 2a1*10n - 1*2a2a2...an is comparable to 2a2a2...an modulo 10n-1.
To do that lets prove that 2a1*10n - 1*2a2a2...an - 2a2a2...an is divisible by 10n-1.
2a1*10n - 1*2a2a2...an - 2a2a2...an =
2a2a2...an * (2a1*10n - 1 - 1)
a2a2...an is more than n-1 for the values we consider.
Thus all that's left to prove to have 10n-1 dividing the difference is that 5n-1 divides 2a1*10n - 1 - 1.
For this I will use Euler's theorem:
2phi(5n-1) = 1 (modulo 5n-1).
Now phi(5n-1) = 4*(5n-2) and for n >= 3 4*(5n-2) will divide a1*10n - 1(actually even solely 10n - 1).
Thus 2a1*10n - 1 gives remainder 1 modulo 5n-1 and so 5n-1 divides 2a1*10n - 1 - 1.
Consequently 10n-1 divides 2a2a2...an * (2a1*10n - 1 - 1) and so the last n - 1 digits of 2a1a2a2...an and 2a2a3a4...an are the same.
Now as a1a2a2...an is interesting the last n digits of 2a1a2a2...an are a1a2a2...an and so the last n-1 digits of 2a2a3a4...an are a2a3a4...an and consequently a2a3a4...an is also interesting. QED.
Use this lemma and you will be able to solve the problem. Please note that you may also prepend some zeros and then add a non-zero number.
In general, you can try solving these problems by finding some pattern in the output. Our team got this problem accepted at the contest. Our approach was to find a general pattern in the values that satisfy the criteria. If you print the first few such digits, then you will find the following pattern
36
736
8736
48736
948736
Thus the next number after 948736 should be of 7 digits and can be any one of 1948736, 2948736, 3948736, 4948736, 5948736, 6948736, 7948736, 8948736, 9948736. Thus check which value is valid and you have the next number. Continuing in this fashion you can back yourself to get all the 150 numbers.
But there is a problem here. There will be some numbers that do not immediately follow from the previous number by appending '1' to '9'. To counter this you can now start appending values from 10 to 99 and now check if there is a valid number or not. If there is still no valid number, then again try appending numbers from 100 to 999.
Now employing this hack, you will get all the 137 values that satisfy the criterion given in the question and easily answer all the queries. For example, working java code that implements this is shown here. It prints all the 137 values.
import java.io.*;
import java.math.*;
import java.util.*;
class Solution
{
public static void main(String[] args)throws java.lang.Exception{
new Solution().run();
}
void run()throws java.lang.Exception{
BigInteger[] powers = new BigInteger[152];
powers[0] = one;
for(int i=1; i<=150; i++){
powers[i] = powers[i-1].multiply(ten);
}
BigInteger[] answers = new BigInteger[152];
answers[2] = BigInteger.valueOf(36);
answers[3] = BigInteger.valueOf(736);
int last = 3;
for(int i=4; i<=150; i++){
int dif = i-last;
BigInteger start = ten.pow(dif-1);
BigInteger end = start.multiply(ten);
while(start.compareTo(end) < 0){
BigInteger newVal = powers[last].multiply(start);
newVal = newVal.add(answers[last]);
BigInteger modPow = pow(two, newVal, powers[i]);
if(modPow.equals(newVal)){
answers[i] = newVal;
System.out.println(answers[i]);
last = i;
break;
}
start = start.add(one);
}
}
}
BigInteger pow(BigInteger b, BigInteger e, BigInteger mod){
if(e.equals(zero)){
return one;
}
if(e.mod(two).equals(zero)){
BigInteger x = pow(b, e.divide(two), mod);
x = x.multiply(x).mod(mod);
return x;
}else{
BigInteger x = pow(b, e.divide(two), mod);
x = x.multiply(x).mod(mod);
x = x.multiply(two).mod(mod);
return x;
}
}
BigInteger ten = BigInteger.valueOf(10);
BigInteger zero = BigInteger.ZERO;
BigInteger one = BigInteger.ONE;
BigInteger two = BigInteger.valueOf(2);
}
This is very interesting property. During the contest, I found that 36 was the only number under 500 checking with python...
The property is : 2^36 last two digits are 36, last three digits are 736, so next number is 736. 2^736 has last three digits as 736, and next number is 8376...
And the series is : 36 , 736 , 8736 , 48736 , 948736 ...
And then started with BigInt class in C++.
But alas there was no time, and 4th problem wasn't solved. But after the contest, we did it in python.
here's link : Ideone it!
def powm(i):
j = 10
a = 1
while i:
if i % 2:
a = a * j
i /= 2
j *= j
return a
def power(n, i):
m = powm(i)
y = 1
x = 2
while n:
if n % 2 == 1:
y = y * x % m
x = x * x % m
n /= 2
return y
mylist = []
mylist.append(power(36, 2))
n = mylist[0]
print(n)
for i in range(3, 170):
p = power(n, i)
print p
if p != n:
mylist.append(p)
n = p
t = input()
while t:
x = raw_input().split(" ")
a = int(x[0])
b = int(x[1])
i = 0
#while i <= 150:
#print mylist[i]
#i += 1
#print power(8719476736,14)
while mylist[i] < a:
i += 1
ans = 0
while mylist[i] <= b:
i += 1
ans += 1
print ans
t -= 1
The final digits start to repeat after 20 increments. So for any n with the final digit 1, the final digit of the answer will be 2. So most values of n can be eliminated immediately.
2^1 = 2
2^21 = 2097152
2^101 = 2535301200456458802993406410752
2^2 = 4
2^22 = 4194304
2^42 = 4398046511104
In fact only two possibilities share a final digit:
2^14 = 16384
2^16 = 65536
2^34 = 17179869184
2^36 = 68719476736
If n is 14+20x or 16+20x, then it might work, so you'll need to check it. Otherwise, it cannot work.
I am not very good with such problems. But modular exponentiation appears to be key in your case.
Repeat for all n in the range A to B:
1. Find k, the no of digits in n. This can be done in O(logn)
2. Find 2^n (mod 10^k) using modular exponentiation and check if it is equal to n. This'll take O(n) time. (actually, O(n) multiplications)
EDIT
Actually, don't repeat the whole process for each n. Given 2^n (mod 10^k), we can find 2^(n+1) (mod 10^k) in constant time. Use this fact to speed it up further
EDIT - 2
This doesn't work for such large range.

undefined behaviour of srand and rand

I am trying to generate random number using srand and rand. Here I want to generate specific number of digit. When I am executing my program at some time if I ask to generate 5 digit number number it is not giving me desired output.
My code is
for(k=0;k<n;k++)
{
temp = temp*10;
}
srand(time(NULL));
i = rand()%temp;
printf("%d\n",i);
k = 0;
temp = n;
while(i != 0)
{
arr1[n+k] = i%10;
i = i/10;
n--;
}
Output
Number of digits you want : 5
2031
while loop 1
while loop 3
while loop 0
while loop 2
N is 1
arr1[1] = 10651312
arr1[2] = 2
arr1[3] = 0
arr1[4] = 3
arr1[5] = 1
tell me where is the problem for getting desired number of digits.
Edit
I run that code around 100 times and out of those four time it is not working, rest is fine...
The problem is you're looping on the size of the random number you've generated and not the size of the array. In your example you want five digits but your code has generated a four digit number, 2031. This means that in the iteration of your bottom loop
... n = 2, i = 2: store a[2] = 2, i = 0
... n = 1, i = 0: loop condition failed, a[1] never set
which leaves random garbage in a[1]. If your random number did in fact contain 5 digits, not 4, then it would have completed the loop correctly.
Instead you want to loop over n
for(int j = n; j > 0; --j)
{
arr1[n+j] = i%10;
i = i/10;
}
Note that this is still using the array as 1-based, whereas in c arrays are 0-based, i.e. they start at element 0, i.e. in order to use arr1[5] you need to have malloced or declared 6 array elements or 6*sizeof(int) bytes. Also note that you should use better variable names than temp, and there's no benefit to reusing the variable: your compiler will automatically reuse registers and sort that out for you.
There are several problems here.
First, call srand() once before actually producing random numbers.
Second, your method taking the returned number modulo some power of 10 will, of course, also return numbers that are lower. For example, n%100000 could be anything from 0 to 99999.
n = rand() % (largest - smallest + 1) + smallest;
If you want a 5 digit number, what is the smallest 5 digit number? Do the same for the largest number. That can be used for any number range with no need to fill an array or anything.
Now you just need to figure out how to generate the largest and smallest values for the number of digits specified.
Happy coding!

How to find number of Multiples of 3

This was a contest Q:
There are N numbers a[0],a[1]..a[N - 1]. Initally all are 0. You have to perform two types of operations :
Increase the numbers between indices A and B by 1. This is represented by the command "0 A B"
Answer how many numbers between indices A and B are divisible by 3. This is represented by the command "1 A B".
Input : The first line contains two integers, N and Q.
Each of the next Q lines are either of the form "0 A B" or "1 A B" as mentioned above.
Output : Output 1 line for each of the queries of the form "1 A B" containing the required answer for the corresponding query.
Sample Input :
4 7 1 0 3 0 1 2 0 1 3 1
0 0 0 0 3 1 3 3 1 0 3
Sample Output :
4 1 0 2
Constraints :
1 <= N <= 100000 1 <= Q <= 100000 0 <= A <= B <= N - 1
I have no idea how to solve this. can you help please?
The time limit is 1 second. I tried brute force and i also tried saving number of divisors of 3 coming before ith element for each i.
here's my C code:
#include <stdio.h>
int nums[100*1000+20];
int d[100*1000+20];
int e[100*1000+20];
int dah[100*1000+20];
int main()
{
int n,q;
scanf("%d%d",&n,&q);
int h;
for(h=0;h<n;h++)
{d[h/100]++; e[h/1000]++; dah[h/10]++;}
int test;
for(test=0;test<q;test++)
{
int op,start,end;
scanf("%d%d%d",&op,&start,&end);
if(0==op)
{
int x;
for(x=start;x<=end;x++)
{
nums[x]++;
nums[x]%=3;
if(nums[x]==0)
{
d[x/100]++;
e[x/1000]++;
dah[x/10]++;
}
else if(nums[x]==1)
{
d[x/100]--;
e[x/1000]--;
dah[x/10]--;
}
}
}
else if(1==op)
{
int f;
int ans=0;
for(f=start;f<=end;)
{
if(f%1000==0&&f+1000<end)
{
ans+=e[f/1000];
f+=1000;
}
else if(f%100==0&&f+100<end)
{
ans+=d[f/100];
f+=100;
}
else if(f%10==0&&f+10<end)
{
ans+=dah[f/10];
f+=10;
}
else
{
ans+=(nums[f]==0);
f++;
}
}
printf("%d\n",ans);
}
}
return 0;
}
In this approach I save number of multiples of 3 between k*1000 and (k+1)*1000 and also the same thing for k*100 and (k+1)*100 and also for 10. this helps me query faster. but this yet gives me time limit exceed.
Hint #1:
Think about how you might use the MODULUS operator to help you. Initially, you have N numbers, let's say N is 5.
So we can store the remainders for each number (i.e. store 0 MOD 3, 1 MOD 3, 2 MOD 3, and so on):
a[0] = 0
a[1] = 1
a[2] = 2
a[3] = 0
a[4] = 1
a[5] = 2
Each time you increment a range of numbers between A and B, you really only need to store a 0, 1, or 2 in the array. For example, if we are incrementing 2, then the new number will be 3. That is now divisible by 3, so we store 0 in the array. So in cases where we have 0 and we increment, we store 1, if we have 1 we store 2, and if we have 2 we store 0.
This optimization eliminates the need to do any division except for the initial step. Division is a very expensive operation, which is why we want to eliminate it where we can.
So after incrementing 0 through 5, the array would look like this:
a[0] = 1
a[1] = 2
a[2] = 0
a[3] = 1
a[4] = 2
a[5] = 0
The amount of numbers between A and B that are divisible by 3 is just the number of elements that have 0 (2 in this case).
Now you have to think about how to query a range A through B efficiently to find the amount of numbers divisible by 3.
Hint #2:
To find out how many numbers over the interval [A,B] are divisible by 3, one algorithm/data structure you can consider using is a segment tree. Read about it here. What this buys you is that now you can compute the amount of numbers divisible by 3 for any such interval [A,B] very quickly, instead of looping over the array and having to count them.
Hint #3:
Good suggestion by dcp. Though it doesn't reveal how to solve the problem. It's not necessary to store all numbers MOD 3 in the array. If the numbers are updated every time in the array the complexity is O(Q * N) which is obviously too much for given N, Q and 1 sec. in the worst case. That is the point of Ali in the comment to dcp suggestion.
The number of integers with MOD%0, MOD%1, MOD%2 can be stored in each node of the segment tree. Hence the updates can be done in O(log N), which results in O(Q log N) for updates only. For each query the same complexity O(log N) applies. Since you know the number of integers MOD%3 for each residue, it's not necessary to go down to all leaves (each leave in segment tree corresponds to array element) to figure how many numbers are divisible by 3. Once you understand how segment tree works that should be obvious why it is necessary to store residues in each node of the segment tree. Overall complexity of the algorithm is O(Q log N) which will fit nicely in 1 sec. time limit.
When going down the segment tree be sure to accumulate number of integers per residue, for each segment that you visit on the way down the tree.
what's the upper bound for your array? first, figure that out. Then, plan on reading lines of input in one of those two forms. The lines in format 0 A B are easy to handle, can you code at least that much? If so, post it and then worry about the lines in format 1 A B.
If, as your title suggests, you aren't sure how to tell if a number is divisible by three then I suggest you have a look into the modulus operation, in the languages I'm most familiar with it is represented using a %.

Resources