Finding how many turns are in a grid of AxB - c++

So, basically, check the picture below:
This is a grid of 4x5 explained, however the actual challenge requires you to input the grid dimensions. So, my job is to write a program that calculates the amount of turns you make (red dots in this case). The starting position is always in the bottom left corner. The guy is moving by the arrows of the clock ("right").
The program input / output is:
you input the grid dimensions:
4 5 (for example)
you output the amount of changes of direction.
7
So, I have absolutely no idea how it's done. The solution I have seen only is the following:
#include <iostream>
#include <cmath>
using namespace std;
int main() {
long long n, i,pom,m;
int k,br=0;
cin>>n>>m;
if(n>m) {
int pom=n;
n=m;
m=n;
}
if(n+1>=m)
cout<<(n-1)+(m-1);
else
cout<<(n-1) +(n-1)+1;
return 0;
}
But I don't understand the following example... could anyone explain what's going? Or any other way of solving this problem is always welcome.

int res = 0;
if(height == width)
res = height * 2 - 2;//when height is odd than you will have 2 rows with single red dot
//when height is even you will have one row without red dot (all the rest have 2 red dots.
else if (width > height)
res = height * 2 - 1;//one rows with 1 red dot the rest with 2 red dots.
else //height > width
res = width * 2 - 2// 2 columns with one red dot and the rest with 2 red dots.

I am not a C++ guy so can't help in understanding the code. But can surely help understanding the situation here.
The situation is that the number of turns will depend only on one of the two dimensions. Which ever is less. So the number of turns depends on the smaller dimension and number of boxes on that side. Because here in picture when you take a 4X5 array, no matter how many you increase the width to. as long as the height is 4, the number of turns will remain 7 only.
But if you decrease the width from 4 to 3, number of turns depends on width now.
Now about the number of dots. If both dimensions are same and odd, then assume dimension to be 2A+1, then the number of turns will be 4*A.
If one dimension is smaller, then if the dimensions are same and even, then assume dimension to be 2*A ,then the number of turns will be 4A-2.
If the smaller dimension is even, then assume the dimension to be 2*A, then the number of turns will be 4A-1.
If the smaller dimension is odd, then assume the dimension to be 2A+1, then the number of turns will be 4A+1.
See if this works with your own new code.

This code conditionally swaps n and m to make n <= m:
if(n>m) {
int pom=n;
n=m;
m=n;
}
Given that, the condition n+1>=m is equivalent to n == m || n + 1 == m.
Note that both formulas (n-1)+(m-1) and (n-1) +(n-1)+1 give the same result for n + 1 == m.
So it is not really necessary to check whether n + 1 == m; it's only the special case n == m that matters. If n == m, then you can use the formula (n-1)+(m-1), or just 2 * n - 2. Otherwise, use the formula (n-1) +(n-1)+1, or just 2 * n - 1.
To rewrite the code:
int calculate_number_of_turns(int m, int n)
{
if (m == n)
return 2 * n - 2;
else
return 2 * std::min(m, n) - 1;
}
Edit:
If you want to write your code from scratch, without knowing the math in advance, you can write a recursive function at first.
If n = 2, it's easy to see that the answer is 3 (3 turns). If m = 2, then the answer is 2. Otherwise (assuming n > 2 and m > 2), the calculation involves invoking the same function for different arguments.
int calculate_number_of_turns(int m, int n)
{
if (n == 2)
return 3;
else if (m == 2)
return 2;
else
return calculate_number_of_turns(???, ???);
}
Imagine starting the path in your picture, and stopping right after you do the second turn. If you turn the picture upside-down, it's as if you reduced with and height by 1. So calling the same function for m - 1, n - 1 will calculate the number of turns left to do, in addition to the first 2 turns.
int calculate_number_of_turns(int m, int n)
{
if (n == 2)
return 3;
else if (m == 2)
return 2;
else
return 2 + calculate_number_of_turns(m - 1, n - 1);
}
Now, converting this recursive function to any simpler form is not too complicated (just calculate the number of times the function is going to call itself, until a termination condition holds).

Related

How to make the computation faster?

Here is short code which computes sum of all square numbers(not actually sum of squares) till n,where n can be upto 10 pow 20.
long long res=0;
long long sm=0;
for (long long i = 1; res <=n; i=i+2)
{
res = (res+i);
sm = sm+(res*(n/res));
}
How do we make the above code work faster? Here, the computation of sm is taking time for very large n like 10 pow 20.
Is there any way that the computation of sm can be made faster?
Here res computes all the square numbers like 1,4,9,16,25....
Lets say n=10, then the squares are 1,4,9 and then by the above code the sm is (1)(10/4)+(4)(10/4)+(9)(10/9)=27.
1*10+4*2+9*1=27.
Here the division is integer division.
edit1:
i need to compute sm mentioned in above code.
here sm is summation ( i2 * floor(n/(i2)) ) where i=1 to sqrt(n)
we can find the sum of all square number till n using the formaula :
n * (n + 1) * (2*n + 1) / 6
long summation(long n)
{
return (n * (n + 1) *
(2 * n + 1)) / 6;
}
Is there any way that the computation of sm can be made faster?
If you notice the pattern plus apply some mathematics, yes.
The next perfect square after your very first perfect square (1 in all cases except for n==0) will be the square of ceil(sqrt(first number)).
In other words, the square root of say the nth number, in correspondence to your first number will be given by pow(ceil(sqrt(L)), n).
Now, notice the pattern between squares: 0 1 4 9 16 25...
Difference between 0 and 1 is 1
Difference between 1 and 4 is 3
Difference between 4 and 9 is 5
Difference between 9 and 16 is 7
Difference between 16 and 25 is 9, and so on.
This makes it clear that the difference between two perfect squares is always an odd number.
Proceeding with this knowledge, you'll need to know what must be added to get the next number, the answer to which is (sqrt(square) * 2) + 1).
i.e., current_square + (sqrt(current_square)*2+1) = next_square.
For instance and to prove this equation, consider the perfect square 25. Applying this logic, the next perfect square will be 25 + (sqrt(25) * 2 + 1) = 36, which is correct. Here 11 is added to 25, which is an odd number.
Similarly if you follow this trend, you'll observe all these numbers are odd, with a difference of +2. For finding the next square of 2, you'll need to add (sqrt(22)+1) = 5 to it (4+5=9); for finding the next square (i.e. for 3) you'll need to add (sqrt(32+1) = 7 to it (9+7=16). The difference is always +2.
Moreover, summing the odd number or applying addition is computationally less expensive than performing multiplication or finding square roots of every number, so your complexity should be fine.
Following that, do this:
Collect the first square. (which ideally should be 1, but if n>0 condition is not mentioned, apply the condition if(n!=0) to my logic)
Assign the next term's difference as first_square*2+1. You'll need to add the first square though, as this is not the next square, but the difference between next square and current square. Add the term in a loop like I did below.
Run a loop upto your required number. Collect your required sum given by (square*floor(n/square) in a variable within the loop.
Follow the approach I mentioned above, i.e. add the current square to the next term (difference between current and next square) and increment next square by 2.
A working example for the above logic:
#include <iostream>
#include <cmath>
#define ll long long
int main()
{
ll int n;
std::cin>>n;
// Start from 1: (add case for 0 if input is not >0)
// you can also start from any other square or define a range.
ll int first = 1;
// Square it:
ll int first_square = first * first;
// Find next square:
ll int next = (first_square * 2) + 1;
// Initialize variable to collect your required sum:
ll int sum = 0;
ll int square = first_square;
while ((square >= 0 && square <= n))
{
sum += (square *floor(n/square));
// Add the perfect square:
square += next;
// Next odd number to be added:
next += 2;
}
std::cout<<sum;
return 0;
}

Given an integer n, return the number of ways it can be represented as a sum of 1s and 2s

For example:
5 = 1+1+1+1+1
5 = 1+1+1+2
5 = 1+1+2+1
5 = 1+2+1+1
5 = 2+1+1+1
5 = 1+2+2
5 = 2+2+1
5 = 2+1+2
Can anyone give a hint for a pseudo code on how this can be done please.
Honestly have no clue how to even start.
Also this looks like an exponential problem can it be done in linear time?
Thank you.
In the example you have provided order of addends is important. (See the last two lines in your example). With this in mind, the answer seems to be related to Fibonacci numbers. Let's F(n) be the ways n can be written as 1s and 2s. Then the last addened is either 1 or 2. So F(n) = F(n-1) + F(n-2). These are the initial values:
F(1) = 1 (1 = 1)
F(2) = 2 (2 = 1 + 1, 2 = 2)
This is actually the (n+1)th Fibonacci number. Here's why:
Let's call f(n) the number of ways to represent n. If you have n, then you can represent it as (n-1)+1 or (n-2)+2. Thus the ways to represent it are the number of ways to represent it is f(n-1) + f(n-2). This is the same recurrence as the Fibonacci numbers. Furthermore, we see if n=1 then we have 1 way, and if n=2 then we have 2 ways. Thus the (n+1)th Fibonacci number is your answer. There are algorithms out there to compute enormous Fibonacci numbers very quickly.
Permutations
If we want to know how many possible orderings there are in some set of size n without repetition (i.e., elements selected are removed from the available pool), the factorial of n (or n!) gives the answer:
double factorial(int n)
{
if (n <= 0)
return 1;
else
return n * factorial(n - 1);
}
Note: This also has an iterative solution and can even be approximated using the gamma function:
std::round(std::tgamma(n + 1)); // where n >= 0
The problem set starts with all 1s. Each time the set changes, two 1s are replaced by one 2. We want to find the number of ways k items (the 2s) can be arranged in a set of size n. We can query the number of possible permutations by computing:
double permutation(int n, int k)
{
return factorial(n) / factorial(n - k);
}
However, this is not quite the result we want. The problem is, permutations consider ordering, e.g., the sequence 2,2,2 would count as six distinct variations.
Combinations
These are essentially permutations which ignore ordering. Since the order no longer matters, many permutations are redundant. Redundancy per permutation can be found by computing k!. Dividing the number of permutations by this value gives the number of combinations:
Note: This is known as the binomial coefficient and should be read as "n choose k."
double combination(int n, int k)
{
return permutation(n, k) / factorial(k);
}
int solve(int n)
{
double result = 0;
if (n > 0) {
for ( int k = 0; k <= n; k += 1, n -= 1 )
result += combination(n, k);
}
return std::round(result);
}
This is a general solution. For example, if the problem were instead to find the number of ways an integer can be represented as a sum of 1s and 3s, we would only need to adjust the decrement of the set size (n-2) at each iteration.
Fibonacci numbers
The reason the solution using Fibonacci numbers works, has to do with their relation to the binomial coefficients. The binomial coefficients can be arranged to form Pascal's triangle, which when stored as a lower-triangular matrix, can be accessed using n and k as row/column indices to locate the element equal to combination(n,k).
The pattern of n and k as they change over the lifetime of solve, plot a diagonal when viewed as coordinates on a 2-D grid. The result of summing values along a diagonal of Pascal's triangle is a Fibonacci number. If the pattern changes (e.g., when finding sums of 1s and 3s), this will no longer be the case and this solution will fail.
Interestingly, Fibonacci numbers can be computed in constant time. Which means we can solve this problem in constant time simply by finding the (n+1)th Fibonacci number.
int fibonacci(int n)
{
constexpr double SQRT_5 = std::sqrt(5.0);
constexpr double GOLDEN_RATIO = (SQRT_5 + 1.0) / 2.0;
return std::round(std::pow(GOLDEN_RATIO, n) / SQRT_5);
}
int solve(int n)
{
if (n > 0)
return fibonacci(n + 1);
return 0;
}
As a final note, the numbers generated by both the factorial and fibonacci functions can be extremely large. Therefore, a large-maths library may be needed if n will be large.
Here is the code using backtracking which solves your problem. At each step, while remembering the numbers used to get the sum so far(using vectors here), first make a copy of them, first subtract 1 from n and add it to the copy then recur with n-1 and the copy of the vector with 1 added to it and print when n==0. then return and repeat the same for 2, which essentially is backtracking.
#include <stdio.h>
#include <vector>
#include <iostream>
using namespace std;
int n;
void print(vector<int> vect){
cout << n <<" = ";
for(int i=0;i<vect.size(); ++i){
if(i>0)
cout <<"+" <<vect[i];
else cout << vect[i];
}
cout << endl;
}
void gen(int n, vector<int> vect){
if(!n)
print(vect);
else{
for(int i=1;i<=2;++i){
if(n-i>=0){
std::vector<int> vect2(vect);
vect2.push_back(i);
gen(n-i,vect2);
}
}
}
}
int main(){
scanf("%d",&n);
vector<int> vect;
gen(n,vect);
}
This problem can be easily visualized as follows:
Consider a frog, that is present in front of a stairway. It needs to reach the n-th stair, but he can only jump 1 or 2 steps on the stairway at a time. Find the number of ways in which he can reach the n-th stair?
Let T(n) denote the number of ways to reach the n-th stair.
So, T(1) = 1 and T(2) = 2(2 one-step jumps or 1 two-step jump, so 2 ways)
In order to reach the n-th stair, we already know the number of ways to reach the (n-1)th stair and the (n-2)th stair.
So, once can simple reach the n-th stair by a 1-step jump from (n-1)th stair or a 2-step jump from (n-2)th step...
Hence, T(n) = T(n-1) + T(n-2)
Hope it helps!!!

Finding a all the combination of a number for a specific sum

Array
A ={1,2,3}
For Sum value = 5
Possible Combination
{3,2} , {1,1,1,1,1} , {2,2,1} and all possiable one
here is my approach:
int count( int S[], int m, int n )
{
// m is the size of the array and n is required sum
// If n is 0 then there is 1 solution (do not include any coin)
if (n == 0)
return 1;
// If n is less than 0 then no solution exists
if (n < 0)
return 0;
// If there are no coins and n is greater than 0, then no solution exist
if (m <=0 && n >= 1)
return 0;
// count is sum of solutions (i) including S[m-1] (ii) excluding S[m-1]
return count( S, m - 1, n ) + count( S, m, n-S[m-1] );
}
My approach Disadvantage: : It have to recalculate the many combination again and again. So it the value of sum is very high so it is very slow. I want to implement this using dynamic programming please provide me an explaination how can i store the calculated value so i can reuse it and reduce time of my program
A very simple change to your solution would be to just add "memoization".
Considering the array S fixed the result of your function just depends on m and n. Therefore you can do the following small change:
int count( int S[], int m, int n ) {
...
if (cache[m][n] == -1) {
cache[m][n] = count( S, m - 1, n ) + count( S, m, n-S[m-1] );
}
return cache[m][n];
}
This way you're only compute the result once for each distinct pair of values m and n.
The idea is to keep a 2d array indexed by (m,n) all initialized to -1 (meaning "not yet computed"). When you're about to compute a value in count you first check if the value has not been computed yet and if this is the case you also store the result in the 2d matrix so you will not recompute the same number again in the future.
I would do it differently:
generate coin array to match sum
genere one coin type
start with the biggest one
add them as much as you can
but the sum must be <= then the target sum
if target sum is achieved store result
recursively call step 1 for next lower coin
but remember last coin array state
if there is no coin=1 then sometimes the result will be invalid
move to next combination
restore last coin array state
remove last coin from it
if there is none to remove then stop
else repeat step 2
count permutations/combinantions if also the order matters
so take valid result and permute it by rules of your problem
to get more solutions from it
it is faster then try every possibility in 1.
example (for 1.):
coins = { 5,2,1 }
sum=7
5 | 2
5 | - | 1 1
- | 2 2 2 | 1
- | 2 2 | 1 1 1
- | 2 | 1 1 1 1 1
| separates recursion layer
there is one recursion level per each coin type
so you need memory for 3 array states in this case (the lengths depends on target sum)
this is acceptable (I saw solutions with much worse space complexity for this problem)
for very big Sums I would use RLE for memory conservations and speedup the process
[edit1] C++ source code
//---------------------------------------------------------------------------
void prn_coins(int *count,int *value,int coins) // just to output solution somewhere
{
int i;
AnsiString s="";
for (i=0;i<coins;i++)
s+=AnsiString().sprintf("%ix%i ",count[i],value[i]);
Form1->mm_log->Lines->Add(s);
}
//---------------------------------------------------------------------------
void get_coins(int *count,int *value,int coins,int sum,int ix=0,int si=0)
{
if (ix>=coins) return; // exit
if (ix==0) // init:
{
ix=0; // first layer
si=0; // no sum in solution for now
for (int i=0;i<coins;i++) count[i]=0; // no coins in solution for now
}
//1. genere actal coint type value[]
count[ix]=(sum-si)/value[ix]; // as close to sum as can
si+=value[ix]*count[ix]; // update actual sum
for(;;)
{
//2. recursion call
if (si==sum) prn_coins(count,value,coins);
else get_coins(count,value,coins,sum,ix+1,si);
//3. next combination
if (count[ix]) { count[ix]--; si-=value[ix]; }
else break;
}
}
//---------------------------------------------------------------------------
void main()
{
const int _coins=3; // coin types
int value[_coins]={5,2,1}; // coin values (must be in descending order !!!)
int count[_coins]={0,0,0}; // coin count in actual solution (RLE)
get_coins(count,value,_coins,7);
}
//-------------------------------------------------------------------------
this code took ~3ms on mine HW setup
just change the prn_coins function to your form of print (I used VCL memo and AnsiSring)
in this code the solution state is automaticly rewriten back to previous state
so no need to further memoize (else it would be necessary to copy the count array before and after recursion)
Now the permutation step would be necessary if:
each coin is unique? (1 1 2 5) != (1 1 2 5)
or just coin type? (1 1 2 5) != (1 2 1 5)
in that case just add the permutation code to prn_coins function ...
but that is different question ...
For dynamic programming you need to generalise your problem. Let S(a, x) be all possible sums of value x, only using values from A starting at index a. Your original problem is S(0, X).
Since you have a discrete function with two parameters you can store its outcomes in a 2d array.
There are some simple cases: there is no solution for a = A.length and X > 0.
There is the set only containing an empty sum for X = 0.
Now, you should find a recursive formula for the other cases and fill the table in such a way that the indices you depend on have already been calculated (hint: consider looping backwards).

Finding all paths down stairs?

I was given the following problem in an interview:
Given a staircase with N steps, you can go up with 1 or 2 steps each time. Output all possible way you go from bottom to top.
For example:
N = 3
Output :
1 1 1
1 2
2 1
When interviewing, I just said to use dynamic programming.
S(n) = S(n-1) +1 or S(n) = S(n-1) +2
However, during the interview, I didn't write very good code for this. How would you code up a solution to this problem?
Thanks indeed!
I won't write the code for you (since it's a great exercise), but this is a classic dynamic programming problem. You're on the right track with the recurrence; it's true that
S(0) = 1
Since if you're at the bottom of the stairs there's exactly one way to do this. We also have that
S(1) = 1
Because if you're one step high, your only option is to take a single step down, at which point you're at the bottom.
From there, the recurrence for the number of solutions is easy to find. If you think about it, any sequence of steps you take either ends with taking one small step as your last step or one large step as your last step. In the first case, each of the S(n - 1) solutions for n - 1 stairs can be extended into a solution by taking one more step, while in the second case each of the S(n - 2) solutions to the n - 2 stairs case can be extended into a solution by taking two steps. This gives the recurrence
S(n) = S(n - 2) + S(n - 1)
Notice that to evaluate S(n), you only need access to S(n - 2) and S(n - 1). This means that you could solve this with dynamic programming using the following logic:
Create an array S with n + 1 elements in it, indexed by 0, 1, 2, ..., n.
Set S[0] = S[1] = 1
For i from 2 to n, inclusive, set S[i] = S[i - 1] + S[i - 2].
Return S[n].
The runtime for this algorithm is a beautiful O(n) with O(n) memory usage.
However, it's possible to do much better than this. In particular, let's take a look at the first few terms of the sequence, which are
S(0) = 1
S(1) = 1
S(2) = 2
S(3) = 3
S(4) = 5
This looks a lot like the Fibonacci sequence, and in fact you might be able to see that
S(0) = F(1)
S(1) = F(2)
S(2) = F(3)
S(3) = F(4)
S(4) = F(5)
This suggests that, in general, S(n) = F(n + 1). We can actually prove this by induction on n as follows.
As our base cases, we have that
S(0) = 1 = F(1) = F(0 + 1)
and
S(1) = 1 = F(2) = F(1 + 1)
For the inductive step, we get that
S(n) = S(n - 2) + S(n - 1) = F(n - 1) + F(n) = F(n + 1)
And voila! We've gotten this series written in terms of Fibonacci numbers. This is great, because it's possible to compute the Fibonacci numbers in O(1) space and O(lg n) time. There are many ways to do this. One uses the fact that
F(n) = (1 / √(5)) (Φn + φn)
Here, Φ is the golden ratio, (1 + √5) / 2 (about 1.6), and φ is 1 - Φ, about -0.6. Because this second term drops to zero very quickly, you can get a the nth Fibonacci number by computing
(1 / √(5)) Φn
And rounding down. Moreover, you can compute Φn in O(lg n) time by repeated squaring. The idea is that we can use this cool recurrence:
x0 = 1
x2n = xn * xn
x2n + 1 = x * xn * xn
You can show using a quick inductive argument that this terminates in O(lg n) time, which means that you can solve this problem using O(1) space and O(lg n) time, which is substantially better than the DP solution.
Hope this helps!
You can generalize your recursive function to also take already made moves.
void steps(n, alreadyTakenSteps) {
if (n == 0) {
print already taken steps
}
if (n >= 1) {
steps(n - 1, alreadyTakenSteps.append(1));
}
if (n >= 2) {
steps(n - 2, alreadyTakenSteps.append(2));
}
}
It's not really the code, more of a pseudocode, but it should give you an idea.
Your solution sounds right.
S(n):
If n = 1 return {1}
If n = 2 return {2, (1,1)}
Return S(n-1)x{1} U S(n-2)x{2}
(U is Union, x is Cartesian Product)
Memoizing this is trivial, and would make it O(Fib(n)).
Great answer by #templatetypedef - I did this problem as an exercise and arrived at the Fibonacci numbers on a different route:
The problem can basically be reduced to an application of Binomial coefficients which are handy for Combination problems: The number of combinations of n things taken k at a time (called n choose k) can be found by the equation
Given that and the problem at hand you can calculate a solution brute force (just doing the combination count). The number of "take 2 steps" must be zero at least and may be 50 at most, so the number of combinations is the sum of C(n,k) for 0 <= k <= 50 ( n= number of decisions to be made, k = number of 2's taken out of those n)
BigInteger combinationCount = 0;
for (int k = 0; k <= 50; k++)
{
int n = 100 - k;
BigInteger result = Fact(n) / (Fact(k) * Fact(n - k));
combinationCount += result;
}
The sum of these binomial coefficients just happens to also have a different formula:
Actually, you can prove that the number of ways to climb is just the fibonacci sequence. Good explanation here: http://theory.cs.uvic.ca/amof/e_fiboI.htm
Solving the problem, and solving it using a dynamic programming solution are potentially two different things.
http://en.wikipedia.org/wiki/Dynamic_programming
In general, to solve a given problem, we need to solve different parts of the problem (subproblems), then combine the solutions of the subproblems to reach an overall solution. Often, many of these subproblems are really the same. The dynamic programming approach seeks to solve each subproblem only once, thus reducing the number of computations
This leads me to believe you want to look for a solution that is both Recursive, and uses the Memo Design Pattern. Recursion solves a problem by breaking it into sub-problems, and the Memo design pattern allows you to cache answers, thus avoiding re-calculation. (Note that there are probably cache implementations that aren't the Memo design pattern, and you could use one of those as well).
Solving:
The first step I would take would be to solve some set of problems by hand, with varying or increasing sizes of N. This will give you a pattern to help you figure out a solution. Start with N = 1, through N = 5. (as others have stated, it may be a form of the fibbonacci sequence, but I would determine this for myself before calling the problem solved and understood).
From there, I would try to make a generalized solution that used recursion. Recursion solves a problem by breaking it into sub-problems.
From there, I would try to make a cache of previous problem inputs to the corresponding output, hence memoizing it, and making a solution that involved "Dynamic Programming".
I.e., maybe the inputs to one of your functions are 2, 5, and the correct result was 7. Make some function that looks this up from an existing list or dictionary (based on the input). It will look for a call that was made with the inputs 2, 5. If it doesn't find it, call the function to calculate it, then store it and return the answer (7). If it does find it, don't bother calculating it, and return the previously calculated answer.
Here is a simple solution to this question in very simple CSharp (I believe you can port this with almost no change to Java/C++).
I have added a little bit more of complexity to it (adding the possibility that you can also walk 3 steps). You can even generalize this code to "from 1 to k-steps" if desired with a while loop in the addition of steps (last if statement).
I have used a combination of both dynamic programming and recursion. The use of dynamic programming avoid the recalculation of each previous step; reducing the space and time complexity related to the call stack. It however adds some space complexity (O(maxSteps)) which I think is negligible compare to the gain.
/// <summary>
/// Given a staircase with N steps, you can go up with 1 or 2 or 3 steps each time.
/// Output all possible way you go from bottom to top
/// </summary>
public class NStepsHop
{
const int maxSteps = 500; // this is arbitrary
static long[] HistorySumSteps = new long[maxSteps];
public static long CountWays(int n)
{
if (n >= 0 && HistorySumSteps[n] != 0)
{
return HistorySumSteps[n];
}
long currentSteps = 0;
if (n < 0)
{
return 0;
}
else if (n == 0)
{
currentSteps = 1;
}
else
{
currentSteps = CountWays(n - 1) +
CountWays(n - 2) +
CountWays(n - 3);
}
HistorySumSteps[n] = currentSteps;
return currentSteps;
}
}
You can call it in the following manner
long result;
result = NStepsHop.CountWays(0); // result = 1
result = NStepsHop.CountWays(1); // result = 1
result = NStepsHop.CountWays(5); // result = 13
result = NStepsHop.CountWays(10); // result = 274
result = NStepsHop.CountWays(25); // result = 2555757
You can argue that the initial case when n = 0, it could 0, instead of 1. I decided to go for 1, however modifying this assumption is trivial.
the problem can be solved quite nicely using recursion:
void printSteps(int n)
{
char* output = new char[n+1];
generatePath(n, output, 0);
printf("\n");
}
void generatePath(int n, char* out, int recLvl)
{
if (n==0)
{
out[recLvl] = '\0';
printf("%s\n",out);
}
if(n>=1)
{
out[recLvl] = '1';
generatePath(n-1,out,recLvl+1);
}
if(n>=2)
{
out[recLvl] = '2';
generatePath(n-2,out,recLvl+1);
}
}
and in main:
void main()
{
printSteps(0);
printSteps(3);
printSteps(4);
return 0;
}
It's a weighted graph problem.
From 0 you can get to 1 only 1 way (0-1).
You can get to 2 two ways, from 0 and from 1 (0-2, 1-1).
You can get to 3 three ways, from 1 and from 2 (2 has two ways).
You can get to 4 five ways, from 2 and from 3 (2 has two ways and 3 has three ways).
You can get to 5 eight ways, ...
A recursive function should be able to handle this, working backwards from N.
Complete C-Sharp code for this
void PrintAllWays(int n, string str)
{
string str1 = str;
StringBuilder sb = new StringBuilder(str1);
if (n == 0)
{
Console.WriteLine(str1);
return;
}
if (n >= 1)
{
sb = new StringBuilder(str1);
PrintAllWays(n - 1, sb.Append("1").ToString());
}
if (n >= 2)
{
sb = new StringBuilder(str1);
PrintAllWays(n - 2, sb.Append("2").ToString());
}
}
Late C-based answer
#include <stdio.h>
#include <stdlib.h>
#define steps 60
static long long unsigned int MAP[steps + 1] = {1 , 1 , 2 , 0,};
static long long unsigned int countPossibilities(unsigned int n) {
if (!MAP[n]) {
MAP[n] = countPossibilities(n-1) + countPossibilities(n-2);
}
return MAP[n];
}
int main() {
printf("%llu",countPossibilities(steps));
}
Here is a C++ solution. This prints all possible paths for a given number of stairs.
// Utility function to print a Vector of Vectors
void printVecOfVec(vector< vector<unsigned int> > vecOfVec)
{
for (unsigned int i = 0; i < vecOfVec.size(); i++)
{
for (unsigned int j = 0; j < vecOfVec[i].size(); j++)
{
cout << vecOfVec[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
// Given a source vector and a number, it appends the number to each source vectors
// and puts the final values in the destination vector
void appendElementToVector(vector< vector <unsigned int> > src,
unsigned int num,
vector< vector <unsigned int> > &dest)
{
for (int i = 0; i < src.size(); i++)
{
src[i].push_back(num);
dest.push_back(src[i]);
}
}
// Ladder Problem
void ladderDynamic(int number)
{
vector< vector<unsigned int> > vecNminusTwo = {{}};
vector< vector<unsigned int> > vecNminusOne = {{1}};
vector< vector<unsigned int> > vecResult;
for (int i = 2; i <= number; i++)
{
// Empty the result vector to hold fresh set
vecResult.clear();
// Append '2' to all N-2 ladder positions
appendElementToVector(vecNminusTwo, 2, vecResult);
// Append '1' to all N-1 ladder positions
appendElementToVector(vecNminusOne, 1, vecResult);
vecNminusTwo = vecNminusOne;
vecNminusOne = vecResult;
}
printVecOfVec(vecResult);
}
int main()
{
ladderDynamic(6);
return 0;
}
may be I am wrong.. but it should be :
S(1) =0
S(2) =1
Here We are considering permutations so in that way
S(3) =3
S(4) =7

Calculating Binomial Coefficient (nCk) for large n & k

I just saw this question and have no idea how to solve it. can you please provide me with algorithms , C++ codes or ideas?
This is a very simple problem. Given the value of N and K, you need to tell us the value of the binomial coefficient C(N,K). You may rest assured that K <= N and the maximum value of N is 1,000,000,000,000,000. Since the value may be very large, you need to compute the result modulo 1009.
Input
The first line of the input contains the number of test cases T, at most 1000. Each of the next T lines consists of two space separated integers N and K, where 0 <= K <= N and 1 <= N <= 1,000,000,000,000,000.
Output
For each test case, print on a new line, the value of the binomial coefficient C(N,K) modulo 1009.
Example
Input:
3
3 1
5 2
10 3
Output:
3
10
120
Notice that 1009 is a prime.
Now you can use Lucas' Theorem.
Which states:
Let p be a prime.
If n = a1a2...ar when written in base p and
if k = b1b2...br when written in base p
(pad with zeroes if required)
Then
(n choose k) modulo p = (a1 choose b1) * (a2 choose b2) * ... * (ar choose br) modulo p.
i.e. remainder of n choose k when divided by p is same as the remainder of
the product (a1 choose b1) * .... * (ar choose br) when divided by p.
Note: if bi > ai then ai choose bi is 0.
Thus your problem is reduced to finding the product modulo 1009 of at most log N/log 1009 numbers (number of digits of N in base 1009) of the form a choose b where a <= 1009 and b <= 1009.
This should make it easier even when N is close to 10^15.
Note:
For N=10^15, N choose N/2 is more than
2^(100000000000000) which is way
beyond an unsigned long long.
Also, the algorithm suggested by
Lucas' theorem is O(log N) which is
exponentially faster than trying to
compute the binomial coefficient
directly (even if you did a mod 1009
to take care of the overflow issue).
Here is some code for Binomial I had written long back, all you need to do is to modify it to do the operations modulo 1009 (there might be bugs and not necessarily recommended coding style):
class Binomial
{
public:
Binomial(int Max)
{
max = Max+1;
table = new unsigned int * [max]();
for (int i=0; i < max; i++)
{
table[i] = new unsigned int[max]();
for (int j = 0; j < max; j++)
{
table[i][j] = 0;
}
}
}
~Binomial()
{
for (int i =0; i < max; i++)
{
delete table[i];
}
delete table;
}
unsigned int Choose(unsigned int n, unsigned int k);
private:
bool Contains(unsigned int n, unsigned int k);
int max;
unsigned int **table;
};
unsigned int Binomial::Choose(unsigned int n, unsigned int k)
{
if (n < k) return 0;
if (k == 0 || n==1 ) return 1;
if (n==2 && k==1) return 2;
if (n==2 && k==2) return 1;
if (n==k) return 1;
if (Contains(n,k))
{
return table[n][k];
}
table[n][k] = Choose(n-1,k) + Choose(n-1,k-1);
return table[n][k];
}
bool Binomial::Contains(unsigned int n, unsigned int k)
{
if (table[n][k] == 0)
{
return false;
}
return true;
}
Binomial coefficient is one factorial divided by two others, although the k! term on the bottom cancels in an obvious way.
Observe that if 1009, (including multiples of it), appears more times in the numerator than the denominator, then the answer mod 1009 is 0. It can't appear more times in the denominator than the numerator (since binomial coefficients are integers), hence the only cases where you have to do anything are when it appears the same number of times in both. Don't forget to count multiples of (1009)^2 as two, and so on.
After that, I think you're just mopping up small cases (meaning small numbers of values to multiply/divide), although I'm not sure without a few tests. On the plus side 1009 is prime, so arithmetic modulo 1009 takes place in a field, which means that after casting out multiples of 1009 from both top and bottom, you can do the rest of the multiplication and division mod 1009 in any order.
Where there are non-small cases left, they will still involve multiplying together long runs of consecutive integers. This can be simplified by knowing 1008! (mod 1009). It's -1 (1008 if you prefer), since 1 ... 1008 are the p-1 non-zero elements of the prime field over p. Therefore they consist of 1, -1, and then (p-3)/2 pairs of multiplicative inverses.
So for example consider the case of C((1009^3), 200).
Imagine that the number of 1009s are equal (don't know if they are, because I haven't coded a formula to find out), so that this is a case requiring work.
On the top we have 201 ... 1008, which we'll have to calculate or look up in a precomputed table, then 1009, then 1010 ... 2017, 2018, 2019 ... 3026, 3027, etc. The ... ranges are all -1, so we just need to know how many such ranges there are.
That leaves 1009, 2018, 3027, which once we've cancelled them with 1009's from the bottom will just be 1, 2, 3, ... 1008, 1010, ..., plus some multiples of 1009^2, which again we'll cancel and leave ourselves with consecutive integers to multiply.
We can do something very similar with the bottom to compute the product mod 1009 of "1 ... 1009^3 - 200 with all the powers of 1009 divided out". That leaves us with a division in a prime field. IIRC that's tricky in principle, but 1009 is a small enough number that we can manage 1000 of them (the upper limit on the number of test cases).
Of course with k=200, there's an enormous overlap which could be cancelled more directly. That's what I meant by small cases and non-small cases: I've treated it like a non-small case, when in fact we could get away with just "brute-forcing" this one, by calculating ((1009^3-199) * ... * 1009^3) / 200!
I don't think you want to calculate C(n,k) and then reduce mod 1009. The biggest one, C(1e15,5e14) will require something like 1e16 bits ~ 1000 terabytes
Moreover executing the loop in snakiles answer 1e15 times seems like it might take a while.
What you might use is, if
n = n0 + n1*p + n2*p^2 ... + nd*p^d
m = m0 + m1*p + m2*p^2 ... + md*p^d
(where 0<=mi,ni < p)
then
C(n,m) = C(n0,m0) * C(n1,m1) *... * C(nd, nd) mod p
see, eg http://www.cecm.sfu.ca/organics/papers/granville/paper/binomial/html/binomial.html
One way would be to use pascal's triangle to build a table of all C(m,n) for 0<=m<=n<=1009.
psudo code for calculating nCk:
result = 1
for i=1 to min{K,N-K}:
result *= N-i+1
result /= i
return result
Time Complexity: O(min{K,N-K})
The loop goes from i=1 to min{K,N-K} instead of from i=1 to K, and that's ok because
C(k,n) = C(k, n-k)
And you can calculate the thing even more efficiently if you use the GammaLn function.
nCk = exp(GammaLn(n+1)-GammaLn(k+1)-GammaLn(n-k+1))
The GammaLn function is the natural logarithm of the Gamma function. I know there's an efficient algorithm to calculate the GammaLn function but that algorithm isn't trivial at all.
The following code shows how to obtain all the binomial coefficients for a given size 'n'. You could easily modify it to stop at a given k in order to determine nCk. It is computationally very efficient, it's simple to code, and works for very large n and k.
binomial_coefficient = 1
output(binomial_coefficient)
col = 0
n = 5
do while col < n
binomial_coefficient = binomial_coefficient * (n + 1 - (col + 1)) / (col + 1)
output(binomial_coefficient)
col = col + 1
loop
The output of binomial coefficients is therefore:
1
1 * (5 + 1 - (0 + 1)) / (0 + 1) = 5
5 * (5 + 1 - (1 + 1)) / (1 + 1) = 15
15 * (5 + 1 - (2 + 1)) / (2 + 1) = 15
15 * (5 + 1 - (3 + 1)) / (3 + 1) = 5
5 * (5 + 1 - (4 + 1)) / (4 + 1) = 1
I had found the formula once upon a time on Wikipedia but for some reason it's no longer there :(