Problem Statement:
Chef has a coin with 1 printed on one side and 2 printed on the other. Chef wants to determine how many different ways he can achieve a sum of S
by flipping the coin any number of times.
Approach:
This problem can be approached using dynamic programming or recursion, where the goal is to find all possible sequences of coin flips that sum up to S
. The recursive nature of the problem can be observed by noting that if we know the number of ways to achieve a sum S-1
and S-2
, we can easily compute the number of ways to achieve S
.
Recursive Approach:
-
Base Cases:
- If
S < 0
, there is no valid sequence of flips that can sum toS
, so we return0
. - If
S == 0
, there is exactly one way to achieve the sum0
—by not flipping the coin at all. So, we return1
.
- If
-
Recursive Case:
- To achieve a sum
S
, the last coin flip must either be1
or2
. - If the last flip is
1
, the problem reduces to finding the number of ways to achieve a sum ofS-1
. - If the last flip is
2
, the problem reduces to finding the number of ways to achieve a sum ofS-2
. - Therefore, the total number of ways to achieve
S
is the sum of the ways to achieveS-1
andS-2
.
- To achieve a sum
Note : For the given constraint, recursive approach is enough to pass the tests.
Complexity:
- Time Complexity: The time complexity of this recursive solution is
O(2^S)
, which is exponential. This is because each call tocountWays(S)
makes two additional calls to smaller subproblems. While simple, this approach can be highly inefficient for large values ofS
.
Space Complexity:
- Space Complexity: The space complexity is
O(S)
due to the depth of the recursive call stack.
Optimization with Dynamic Programming:
To optimize the solution, we can use dynamic programming to avoid redundant calculations by storing the results of subproblems:
#include<bits/stdc++.h>
using namespace std;
// Memoization table to store results of subproblems
unordered_map<int, int> dp;
int countWays(int S) {
// Base cases
if (S < 0) return 0; // No way to achieve a negative sum
if (S == 0) return 1; // One way to achieve sum 0 (by not flipping any coins)
// Check if the result is already in the memoization table
if (dp.find(S) != dp.end()) return dp[S];
// Recursively calculate the number of ways to achieve sum S
dp[S] = countWays(S - 1) + countWays(S - 2);
return dp[S];
}
int main() {
int S;
cin >> S;
cout << countWays(S) << endl; // Output the result
return 0;
}
- This top-down approach with memoization is much more efficient than a naive recursive solution. It ensures that each subproblem is solved only once, reducing the time complexity to
O(S)
.