Skip to content

3154. Find Number of Ways to Reach the K-th Stair

Description

You are given a non-negative integer k. There exists a staircase with an infinite number of stairs, with the lowest stair numbered 0.

Alice has an integer jump, with an initial value of 0. She starts on stair 1 and wants to reach stair k using any number of operations. If she is on stair i, in one operation she can:

  • Go down to stair i - 1. This operation cannot be used consecutively or on stair 0.
  • Go up to stair i + 2jump. And then, jump becomes jump + 1.

Return the total number of ways Alice can reach stair k.

Note that it is possible that Alice reaches the stair k, and performs some operations to reach the stair k again.

 

Example 1:

Input: k = 0

Output: 2

Explanation:

The 2 possible ways of reaching stair 0 are:

  • Alice starts at stair 1.
    • Using an operation of the first type, she goes down 1 stair to reach stair 0.
  • Alice starts at stair 1.
    • Using an operation of the first type, she goes down 1 stair to reach stair 0.
    • Using an operation of the second type, she goes up 20 stairs to reach stair 1.
    • Using an operation of the first type, she goes down 1 stair to reach stair 0.

Example 2:

Input: k = 1

Output: 4

Explanation:

The 4 possible ways of reaching stair 1 are:

  • Alice starts at stair 1. Alice is at stair 1.
  • Alice starts at stair 1.
    • Using an operation of the first type, she goes down 1 stair to reach stair 0.
    • Using an operation of the second type, she goes up 20 stairs to reach stair 1.
  • Alice starts at stair 1.
    • Using an operation of the second type, she goes up 20 stairs to reach stair 2.
    • Using an operation of the first type, she goes down 1 stair to reach stair 1.
  • Alice starts at stair 1.
    • Using an operation of the first type, she goes down 1 stair to reach stair 0.
    • Using an operation of the second type, she goes up 20 stairs to reach stair 1.
    • Using an operation of the first type, she goes down 1 stair to reach stair 0.
    • Using an operation of the second type, she goes up 21 stairs to reach stair 2.
    • Using an operation of the first type, she goes down 1 stair to reach stair 1.

 

Constraints:

  • 0 <= k <= 109

Solutions

We design a function dfs(i, j, jump), which represents the number of ways to reach the $k$th step when currently at the $i$th step, having performed $j$ operation 1's and jump operation 2's. The answer is dfs(1, 0, 0).

The calculation process of the function dfs(i, j, jump) is as follows:

  • If $i > k + 1$, since we cannot go down twice in a row, we cannot reach the $k$th step again, so return $0$;
  • If $i = k$, it means that we have reached the $k$th step. The answer is initialized to $1$, and then continue to calculate;
  • If $i > 0$ and $j = 0$, it means that we can go down, recursively calculate dfs(i - 1, 1, jump);
  • Recursively calculate dfs(i + 2^{jump}, 0, jump + 1), and add it to the answer.

To avoid repeated calculations, we use memoization search to save the calculated states.

The time complexity is $O(\log^2 k)$, and the space complexity is $O(\log^2 k)$.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class Solution:
    def waysToReachStair(self, k: int) -> int:
        @cache
        def dfs(i: int, j: int, jump: int) -> int:
            if i > k + 1:
                return 0
            ans = int(i == k)
            if i > 0 and j == 0:
                ans += dfs(i - 1, 1, jump)
            ans += dfs(i + (1 << jump), 0, jump + 1)
            return ans

        return dfs(1, 0, 0)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
    private Map<Long, Integer> f = new HashMap<>();
    private int k;

    public int waysToReachStair(int k) {
        this.k = k;
        return dfs(1, 0, 0);
    }

    private int dfs(int i, int j, int jump) {
        if (i > k + 1) {
            return 0;
        }
        long key = ((long) i << 32) | jump << 1 | j;
        if (f.containsKey(key)) {
            return f.get(key);
        }
        int ans = i == k ? 1 : 0;
        if (i > 0 && j == 0) {
            ans += dfs(i - 1, 1, jump);
        }
        ans += dfs(i + (1 << jump), 0, jump + 1);
        f.put(key, ans);
        return ans;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public:
    int waysToReachStair(int k) {
        unordered_map<long long, int> f;
        auto dfs = [&](auto&& dfs, int i, int j, int jump) -> int {
            if (i > k + 1) {
                return 0;
            }
            long long key = ((long long) i << 32) | jump << 1 | j;
            if (f.contains(key)) {
                return f[key];
            }
            int ans = i == k ? 1 : 0;
            if (i > 0 && j == 0) {
                ans += dfs(dfs, i - 1, 1, jump);
            }
            ans += dfs(dfs, i + (1 << jump), 0, jump + 1);
            f[key] = ans;
            return ans;
        };
        return dfs(dfs, 1, 0, 0);
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func waysToReachStair(k int) int {
    f := map[int]int{}
    var dfs func(i, j, jump int) int
    dfs = func(i, j, jump int) int {
        if i > k+1 {
            return 0
        }
        key := (i << 32) | jump<<1 | j
        if v, has := f[key]; has {
            return v
        }
        ans := 0
        if i == k {
            ans++
        }
        if i > 0 && j == 0 {
            ans += dfs(i-1, 1, jump)
        }
        ans += dfs(i+(1<<jump), 0, jump+1)
        f[key] = ans
        return ans
    }
    return dfs(1, 0, 0)
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function waysToReachStair(k: number): number {
    const f: Map<bigint, number> = new Map();

    const dfs = (i: number, j: number, jump: number): number => {
        if (i > k + 1) {
            return 0;
        }

        const key: bigint = (BigInt(i) << BigInt(32)) | BigInt(jump << 1) | BigInt(j);
        if (f.has(key)) {
            return f.get(key)!;
        }

        let ans: number = 0;
        if (i === k) {
            ans++;
        }

        if (i > 0 && j === 0) {
            ans += dfs(i - 1, 1, jump);
        }

        ans += dfs(i + (1 << jump), 0, jump + 1);
        f.set(key, ans);
        return ans;
    };

    return dfs(1, 0, 0);
}

Comments