Last non-zero digits of a very large factorial - algorithm

How can one calculate the last few non-zero digits of a factorial of a large number?
By large, i mean like n=10^100 or something
(EDIT : 10^100 is the magnitude of 'n' in n! )
By few, i mean till 7-8...
I tried googling it and found this -
Last non-zero digit of a factorial
I tried to expand this to last 2 non-zero digits or more, but failed...
I found other websites on google that showed how to calculate last x number of digits but it wasn't clear and i wasn't able to understand it...
Can anyone help me with this?
Also, am not able to get this, the last two non-zero digits of 99! are 64, so i figured that the last two non-zero digits of (199! / 99!) should also be 64, but they turn out to be 24, i know i am making an extremely big logical mistake in this one, am just not able to put my finger on it!

The trick to do your calculations is that you want to find 3 numbers.
The number of factors of 5 in the answer.
The number of factors of 2 in the answer.
The last few digits of all of the products of all of the other primes in the answer.
The number of factors of 5 give you the number of factors of 10. Then subtract the number of factors of 2 from the number of factors of 5. Figure out the last few digits of 2 to that power. Multiply that by the last few digits found in step 3, and you're done.
The number of factors of 5 can be worked out as follows. Take n/5 (round down). That's how many have a first factor of 5. Then n/25 (round down). That how many have a second factor of 5. Continue until you're done.
The number of factors of 2 can be worked out similarly only with the sequence 2, 4, 8, 16 instead.
The third part is tricky.
But what is easier is to do is figure out the product of all of the numbers up to and including n which are relatively prime to 2 and 5. Call that function f(n). You can calculating it by multiplying the relatively prime numbers mod 10^k. And take advantage of the fact that f(i * 10^k + j) = f(j) mod(10^k).
Then you want the last few digits of f(n)*f(n/2)*f(n/4)*f(n/5)*f(n/8)*f(n/10)*f(n/16)*.... Producing that sequence efficiently is a version of the Hamming Numbers problem. See https://rosettacode.org/wiki/Hamming_numbers for how to do that. For 10^100 there will still only be tens of thousands in this sequence - it is well under control.
For your second question about ratios, you'll need to take advantage of the following two facts. Fact 1 is that you know the right number of factors of 2 and 5 just through subtraction. The second is that if m is relatively prime to 10 then m * m^(4 * 10^(k-1) - 1) is 1 mod 10^k. So you can now "divide" mod 10^k, and figure out the last few terms of every factor of the answer that doesn't involve a 2 or a 5, then figure out the number of 0s, and the number of leftover factors of 2 or 5 that you have.
Here is a significant optimization. If you know f(n) mod 2^8 and 5^8, it isn't hard to figure it out mod 10^8. But its value mod those two can be reduced to a lookup table of modest size. The larger one you only need to store it for odd n up to 4*390625, but there are less than 800k of those. (At that point you've multiplied by all elements of the group of things not divisible by 5 mod 5^8, and that product is 1. Then the pattern repeats.) If you're using 4 byte integers, that's few MB lookup table that can be precalculated fairly easily.
I should probably explain why this trick works, because it isn't obvious and I got it wrong a couple of times. The trick is that the numbers relatively prime to 5^k form a group. Meaning each has an inverse. So if you multiply them all out, and rearrange, each has an inverse EXCEPT 5^k-1. So multiply by another copy and they pair up again including that pesky one and the product comes out to 1. Now for our f we are only interested in odd numbers not divisible by 5, but the odd ones not divisible by 5 out to 2*5^k are, mod 5^k, just a rearrangement of the ones divisible by 5 out to 5^k. We need 2 copies, hence out to 4*5^k. But we only need the odds because the even right after always has the same value as the previous odd.
Per request, here is how this works for a single example. I'll do the last 3 digits of 15!
15! = 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15
= (1*3*7*9*11*13) * (2*6*14) * (4*12) * (5*15) * (8) * (10)
= (1*3*7*9*11*13) * 2^3*(1*3*7) * 2^4*(1*3) * 5^2*(1*3) * 2^3*(1) * 10*(1)
= 2^11 * 5^3 * f(15) * f(15/2) * f(15/4) * f(15/5) * f(15/8) * f(15/10)
= 2^11 * 5^3 * f(15) * f(15/2) * f(15/4) * f(15/5) * f(15/8) * f(15/10)
= 10^3 * 2^8 * f(15) * f(7) * f(3) * f(3) * f(1) * f(1)
Which leads to the calculation...
256 * 27 * 21 * 3 * 3 * 1 * 1 (mod 1000)
= 368 (mod 1000)
This is correct because 15! = 1307674368000.

Related

Simple math task: 2 numbers given, we have to find the third. I just need a formula for it

I need a formula for counting the number of combinations within a given limit of numbers. There must only be 2 numbers given, we have to find the third.
For example, for 2(number of repetitions) and 3(limit number), the result would be 3, because there are 3 combinations for the digits: 1 and 2, 1 and 3, 2 and 3.
For 2 and 4 the result is 6,
For 3 and 5 the result is 10,
For 6 and 7 the result is 7, etc.
The first number has to be smaller than the second.
A formula is needed for figuring out the result, if the first number is A, the second is B, what would C is going to be?
You're describing combination. The formula is going to be C = B! / (A!*(B-A)!) (where ! is the factorial operation). It's also worth noting that the first number can be equal to the second -- there should only be one repetition in that case. By convention 0! == 1 and it is OK where both numbers are equal because C(n, n) = 1 and this means n!/(n! * 0!).
Unfortunately, since factorial grows very quickly (21! is too large for a 64-bit unsigned integer), you probably can't compute this directly. Wikipedia has a few algorithms you can use here.

How to find if the number is a multiple of 7 efficiently?

There are multiple ways to find out the same and I tried using bitwise operation as -
if(((n<<3) - n)%7 == 0 ) {
print "divide by 7";
}
Is there any other more efficient way?
As we can find if number is multiple of 3 using below algorithm -
If difference between count of odd set bits (Bits set at odd positions) and even set bits is multiple of 3 then so is the number.
Can we generalize the above algorithm for other numbers too?
So if your number is representable by a hardware-supported integer, and the hardware has a division or modulo operations, you should just use those. It is simpler, and probably faster than anything you will write. To even compete with the hardware, you must use an assembler and use other faster instructions better than the hardware manufacturers did, and without the advantage of undocumented tricks they could use but you can not.
Where this question becomes interesting is where arbitrarily large integers are involved. Modulo has some tricks for that. For instance, I can tell you that 100000000010000010000 is divisible by 3, even though my brain is a horribly slow math processor compared to a computer, because of these properties of the % modulo operator:
(a+b+c) % d = ( (a%d) + (b%d) + (c%d) ) %d
(n*a) % d = ( (a%d) + (a%d) + (a%d) +... (n times) ) %d = (n*(a%d)) %d
Now note that:
10 % 3 = 1
100 % 3 = (10 * (10%3)) % 3 = 10%3 = 1
1000 % 3 = (10 * (100%3)) %3 = 1
etc...
So that to tell if a base-10 number is divisible by 3, we simply sum the digits and see if the sum is divisible by 3
Now using the same trick with a large binary number expressed in octal or base-8 (also pointed out by #hropyatr above in comments), and using divisibility by 7, we have the special case:
8 % 7 = 1
and from that we can deduce that:
(8**N) % 7 = (8 * (8 * ( ... *( 8 * (8%7) % 7 ) % 7 ) ... %7 = 1
so that to "quickly" test divisibility by 7 of an arbitrarily large octal number, all we need to do is add up its octal base-8 digits and try dividing that by 7.
Finally, the bad news.
The code posted:
if ( (n<<3 - n) % 7 ==0 ) ... is not a good test for divisibility by 7.
because it is always yields true for any n (as pointed out by #Johnathan Leffler)
n<<3 is multiplication by 8, and will equal 8n
So for instance 6 is not divisible by 7,
but 6<<3 = 48 and 48 - 6 = 42, which is divisible by 7.
If you meant right shift if ( (n>>3 - n ) % 7 == 0 ) that doesn't work either. Test it with 49, 49//8 is 6, 6-49 is -43 and although 49 is divisible by 7, -43 is not.
The simplest test, if (n % 7 ) == 0 is your best shot until n overflows hardware, and at that point you can find a routine to represent n in octal, and sum the octal digits modulo 7.
I think if(n%7 == 0) is more efficient way to check divisibility by 7.
But if you are dealing with large numbers and can't directly do modulus operation then this might help:
A number of the form 10x + y is divisible by 7 if and only if x − 2y is divisible by 7. In other words, subtract twice the last digit from the number formed by the remaining digits. Continue to do this until a number known to be divisible by 7 is obtained. The original number is divisible by 7 if and only if the number obtained using this procedure is divisible by 7.
For example, the number 371: 37 − (2×1) = 37 − 2 = 35; 3 − (2 × 5) = 3 − 10 = −7; thus, since −7is divisible by 7, 371 is divisible by 7.
Another method is multiplication by 3. A number of the form 10x + y has the same remainder when divided by 7 as 3x + y. One must multiply the leftmost digit of the original number by 3, add the next digit, take the remainder when divided by 7, and continue from the beginning: multiply by 3, add the next digit, etc.
For example, the number 371: 3×3 + 7 = 16 remainder 2, and 2×3 + 1 = 7.
This method can be used to find the remainder of division by 7.
P.S: reference

Algorithm to report products of integers

Disclosure This question is based on a question from a CS class. Looking to expand on it though.
The initial question is simply, given a set of n integers, report n products of n-1 integers (each time missing a different n_i). It is to run in linear time.
For example, a set of {1, 2, 3, 4} would report 2 * 3 * 4, 1 * 3 * 4, 1 * 2 * 4, and 1 * 2 * 3.
The easiest solution (that I can think of) is to simply step through all n integers and calculate the product of them all (1 * 2 * 3 * 4). Then step through them a second time and, using division, divide the total product by each integer. Reporting the solution each time (24 / 1, 24 / 2, 24 / 3, 24 / 4).
The above works and runs in linear time. The professor though suggested we also come up with a way to do it without division. Still no space restriction, just the linear time restriction. I've thought about it but am drawing a blank. Any suggestions?
You could calculate an array containing all the leading products first--linear time:
1
1 * 2
1 * 2 * 3
1 * 2 * 3 * 4
Then the trailing ones second--this is also linear time:
4
3 * 4
2 * 3 * 4
1 * 2 * 3 * 4
Any answer can be found directly, or calculated as a product of one item from the first list and one item from the second list:
(2 * 3 * 4)
(1) * (3 * 4)
(1 * 2) * (4)
(1 * 2 * 3)
So what exactly do they want for these products? For example could we have the product 1 * 1 in our solution? If so couldn't you just multiply each number in the array by the first then be done?
Or you can multiply by pairs, for example:
1 * 2, 2 * 3, 3 * 1
This could be done using a mod operator adding two elements through your array.
Sudo code:
for i = 0 to array.length
print array[i] * array [i+1 % array.length]

Most efficient way to add individual digits of a number

I am working on an algorithm to determine whether a given number is prime and came across this website. But then I though of trying my own logic. I can easily eliminate numbers ending in 2,4,5,6,8 (and 0 for numbers above 5), so I am left with 1,3,7 and 9 as the possible last digit. Now, if the last digit is 3, I can add up the individual digits to check if it is divisible by 3. I don't want to perform modulus(%) operation and add them. Is there a much more efficient way to sum the digits in a decimal number? Maybe using bitwise operations... ?
% or modulus operator would be faster than adding individul digits. But if you really want to do this, you can unroll your loop partly in such a way that multiples of 3 are escaped automatically.
For ex:
2 is prime
3 is prime
candidate = 5
while(candidate <= limit - 2 * 3) // Unrolling loop for next 2 * 3 number
{
if ( CheckPrime(candidate) ) candidate is prime;
candidate += 2;
if ( CheckPrime(candidate) ) candidate is prime;
candidate += 4; // candidate + 2 is multiple of 3 (9, 15, 21 etc)
}
if(candidate < limit) CheckPrime(candidate);
In above method we are eliminating multiples of 3 instead of checking the divisibility of 3 by adding the digits.
You had a good observation. Incidentally it is called wheel factorization to find prime. I have done for wheel size = 6 (2*3), but you can do the same for larger wheel size also, for ex: 30(2*3*5). The snippet above is also called as all prime number are of type 6N±1.
(because 6N+3 is multiple of 3)
p.s. Not all numbers ending at 2 and 5 are composite. Number 2 and 5 are exceptions.
You might consider the following but i think modulus is fastest way :-
1. 2^n mod 3 = 1 if n is even and = 2 if n is odd
2. odd bits and even bits cancel each out as their sum is zero modulo 3
4. so the absolute difference of odd and even bits is the remainder
5. As difference might be again greater than 3 you need to again calculate modulo 3
6. step 5 can be done recursively
Pseudo code :-
int modulo3(int num) {
if(num<3)
return num;
int odd_bits = cal_odd(num);
int even_bits = cal_even(num);
return module3(abs(even_bits-odd_bits));
}

Fastest algorithm of getting precise answer (not approximated) when square-rooting

Sorry for unclear title, but I don't know how to state it properly (feel free to edit), so I will give example:
sqrt(108) ~ 10.39... BUT I want it to be like this sqrt(108)=6*sqrt(3) so it means expanding into two numbers
So that's my algorithm
i = floor(sqrt(number)) //just in case, floor returns lowest integer value :)
while (i > 0) //in given example number 108
if (number mod (i*i) == 0)
first = i //in given example first is 6
second = number / (i*i) //in given example second is 3
i = 0
i--
Maybe you know better algorithm?
If it matters I will use PHP and of course I will use appropriate syntax
There is no fast algorithm for this. It requires you to find all the square factors. This requires at least some factorizing.
But you can speed up your approach by quite a bit. For a start, you only need to find prime factors up to the cube root of n, and then test whether n itself is a perfect square using the advice from Fastest way to determine if an integer's square root is an integer.
Next speed up, work from the bottom factors up. Every time you find a prime factor, divide n by it repeatedly, accumulating out the squares. As you reduce the size of n, reduce your limit that you'll go to. This lets you take advantage of the fact that most numbers will be divisible by some small numbers, which quickly reduces the size of the number you have left to factor, and lets you cut off your search sooner.
Next performance improvement, start to become smarter about which numbers you do trial divisions by. For instance special case 2, then only test odd numbers. You've just doubled the speed of your algorithm again.
But be aware that, even with all of these speedups, you're just getting more efficient brute force. It is still brute force, and still won't be fast. (Though it will generally be much, much faster than your current idea.)
Here is some pseudocode to make this clear.
integer_sqrt = 1
remainder = 1
# First we special case 2.
while 0 == number % 4:
integer_sqrt *= 2
number /= 4
if 0 == number / 2:
number /= 2
remainder *= 2
# Now we run through the odd numbers up to the cube root.
# Note that beyond the cube root there is no way to factor this into
# prime * prime * product_of_bigger_factors
limit = floor(cube_root(number + 1))
i = 3
while i <= limit:
if 0 == number % i:
while 0 == number % (i*i):
integer_sqrt *= i
number /= i*i
if 0 == number % (i*i):
number /= i
remainder *= i
limit = floor(cube_root(number + 1))
i += 2
# And finally check whether we landed on the square of a prime.
possible_sqrt = floor(sqrt(number + 1))
if number == possible_sqrt * possible_sqrt:
integer_sqrt *= possible_sqrt
else:
remainder *= number
# And the answer is now integer_sqrt * sqrt(remainder)
Note that the various +1s are to avoid problems with the imprecision of floating point numbers.
Running through all of the steps of the algorithm for 2700, here is what happens:
number = 2700
integer_sqrt = 1
remainder = 1
enter while loop
number is divisible by 4
integer_sqrt *= 2 # now 2
number /= 4 # now 675
number is not divisible by 4
exit while loop
number is not divisible by 2
limit = floor(cube_root(number + 1)) # now 8
i = 3
enter while loop
i < =limit # 3 < 8
enter while loop
number is divisible by i*i # 9 divides 675
integer_sqrt *= 3 # now 6
number /= 9 # now 75
number is not divisible by i*i # 9 does not divide 75
exit while loop
i divides number # 3 divides 75
number /= 3 # now 25
remainder *= 3 # now 3
limit = floor(cube_root(number + 1)) # now 2
i += 2 # now 5
i is not <= limit # 5 > 2
exit while loop
possible_sqrt = floor(sqrt(number + 1)) # 5
number == possible_sqrt * possible_sqrt # 25 = 5 * 5
integer_sqrt *= possible_sqrt # now 30
# and now answer is integer_sqrt * sqrt(remainder) ie 30 * sqrt(3)
It's unlikely that there is a fast algorithm for this. See https://mathoverflow.net/questions/16098/complexity-of-testing-integer-square-freeness especially https://mathoverflow.net/questions/16098/complexity-of-testing-integer-square-freeness/16100#16100
List all prime divisors in increasing order e.g. 2700 = 2*2*3*3*3*5*5. This is the slowest step and requires sqrt(N) operations.
Create an accumulator (start with 1). Scan this list. For every pair of numbers, multiply the accumulator by (one of) them. So after scanning the list above, you get 2*3*5.
Accumulator is your multiplier. The rest remains under square root.

Resources