I have a doubt in how did the author reach the intuition behind the formula to calculate the (m + n -2)C n-1 in this problem - https://www.geeksforgeeks.org/count-possible-paths-top-left-bottom-right-nxm-matrix/
Please scroll down to solution by using combinatorics.
Particularly talking, I don't understand how the below code was developed for what is basically a nCr
for (int i = n; i < (m + n - 1); i++) {
path *= i;
path /= (i - n + 1);
}
I mean, if I put values into it, I get it. But, if you understand my pain, how will I reach this had I not known. Searching for how to calculate nCr gives different solutions.
And this is some observation put into practice. Even if anyone can point me to a different straightforward formula for calculating the same thing will be great. It is not that easy to consume this after all without the observation put behind it which may have taken time. Just curious at the same time why is this not solved using standard way to solve nCr. Like the one here - https://www.geeksforgeeks.org/program-to-calculate-the-value-of-ncr-efficiently/
The formula for
nCr(n,k)is:The problem is that the factorials will get very big soon and overflow standard variables even for small inputs. To avoid that we just eliminate redundant operations... I can rewrite to this:
Now we can see that first
n-rork(depends on which is bigger) multiplications are the same on both sides of the division so we can skip them so (in casek>=n-r):Also if we do this in loop and divide after each multiplication the sub result will keep small:
And yes there is the same number of therms on both sides of the division. If I understood it correctly your code should do
nCr(m+n-2,n-1)so the substitution to match formula will be:rewriting to:
so your loop is doing a
PIofi/(i-n+1)wherei={ n,n+1,...,m+n-1 }which matches the equation above...Beware this is not exact
nCras it needs to be computed on floating point so rounding errors occurs on each iteration !!! So the output can be off a small bit !!! However this can be computed on Integers in similar manner (without any precision loss) but instead of dividing at each iterations you divide both dividents with common divisors to keep them "small". Ideally by first few primes. Here a small C++ example of this (both float and int versions) I just bustled together:Where
DWORDis 32 bit unsigned integer (but any integer variable type can be used)... This works correctly (on 32 bit ) up tonCr(32,15)Here comparison between the two:Yes you can use
doubleinstead but always take in mind the result might be slightly off !!!