Construction of Iterative( Bottom up ) solution from Recursive( Top down ) solution
Tetrahedron
You are given a tetrahedron. Let's mark its vertices with letters A, B, C and D correspondingly.
An ant is standing in the vertex D of the tetrahedron. The ant is quite active and he wouldn't stay idle. At each moment of time he makes a step from one vertex to another one along some edge of the tetrahedron. The ant just can't stand on one place.
You do not have to do much to solve the problem: your task is to count the number of ways in which the ant can go from the initial vertex D to itself in exactly n steps. In other words, you are asked to find out the number of different cyclic paths with the length of n from vertex D to itself. As the number can be quite large, you should print it modulo 1000000007 (109 + 7).
Input
The first line contains the only integer n (1 ≤ n ≤ 107) — the required length of the cyclic path.
Output
Print the only integer — the required number of ways modulo 1000000007 (109 + 7).
Examples
input
2
output
3
input
4
output
21
Note
The required paths in the first sample are:
- D - A - D
- D - B - D
- D - C - D
vertex D and also end his journey at vertex D after n steps.
Solution
Case1:
If Ant is at vertex D and remaining steps are X , from this position ant only go to vertex A , B , C
so the Paths( D , X ) = Path( A , X - 1 ) + Path( B , X - 1 ) + Path( C , X - 1 ).
But wait and think little more 🤔
The vertex A , B , C they all are equal for D because it take only 1 steps from D to any of vertex
(A , B , C ).
Now , Let denote Vertex D = 1 and other vertices = 0.
So Path(1 , X) = 3 * Path( 0 , X -1 )
Case 2:
If ant is on any vertex other than D then Path( 0 , X ) = Paths from D + Paths from remaining
two vertices.
So Path( 0 , X ) = Path(1 , X -1) + 2 * Path( 0 , X - 1)
Recursive
Recurrence
if( Ant is at 1(means at D) and remaining steps = X )
then ans = 3 * Path( 0 , X -1 )
else i.e not at D
then ans = Path(1 , X -1) + 2 * Path( 0 , X - 1)
Base Case
if remaining steps is 0 then ,
- if current vertex == 1 (i.e D) then return 1 ( i.e one path found )
- else return 0 ( i.e. wrong path )
Memoize each steps
- int Path( int left , int c , int dp[][2]){
- if( left == 0 ){ // Base case
- if( c == 1 )return 1;
- else return 0;
- }
- if( dp[left][c] != -1 )return dp[left][c];
- if( c == 1 ){// case 1
- dp[left][c] = (3LL % Mod * Path( left - 1 , 0 , dp) % Mod) % Mod;
- }
- else{ // case 2
- dp[left][c] = (2LL % Mod * Path(left - 1 , 0 , dp) % Mod
- + Path(left - 1 ,1 , dp) % Mod) % Mod;
- }
- return dp[left][c];
- }
Iterative
We will construct the iterative solution from the memoization solution in two simple steps:
1. Filling the base case entries
Base case entries are the ones where we can directly compute the answer, without further recursive calls.
- (Easy step) Fill the base case entries in the array.
- (Hard step) Fill the recursive case entries in the array.
1. Filling the base case entries
Base case entries are the ones where we can directly compute the answer, without further recursive calls.
Looking at the memoization solution , there left and c values , where left == 0 and
c == 1 or c == 0
The code to fill base case entries will look like this:
- dp[0][1] = 1; // left = 0 , c = 1
- dp[0][0] = 0; // left = 0 , c = 0
2.Filling the Recursive case entries
Filling the Recursive case entries are the ones where we need recursive calls to compute the answer.
Once we rewrite the solution into iterative one, there will be no recursive calls. Instead, where the recursive call was before, we will directly use the values stored in the array:
Once we rewrite the solution into iterative one, there will be no recursive calls. Instead, where the recursive call was before, we will directly use the values stored in the array:
- for( int i = 1; i <= n; i++ ){
- // Note how we change Path(left - 1 , 0) to dp[i-1][0] and
- // path( left - 1 , 1 ) to dp[i-1][1]
- dp[i][1] = (3LL * dp[i-1][0]) % Mod;
- dp[i][0] = (2LL * dp[i-1][0] + dp[i-1][1]) % Mod;
- }
What this means for us is that when we calculating the value of dp[i][1] and dp[i][0] , all the values of dp[j][1] and dp[j][0] ( for all j < i ) has been already calculated.
Full Solution
- int dp[10000001][2];
- int main(){
- int n;
- cin >> n;
- // fill base case entries :
- dp[0][1] = 1;
- dp[0][0] = 1;
- // fill recursive case entries:
- // Iterate in the direction of increasing steps
- for( int i = 1; i <= n; i++ ){
- dp[i][1] = (3LL * dp[i-1][0]) % Mod;
- dp[i][0] = (2LL * dp[i-1][0] + dp[i-1][1]) % Mod;
- }
- cout << dp[n][1];
- }
Leave a Comment