# 837. New 21 Game

## Description

Alice plays the following game, loosely based on the card game "21".

Alice starts with 0 points and draws numbers while she has less than k points. During each draw, she gains an integer number of points randomly from the range [1, maxPts], where maxPts is an integer. Each draw is independent and the outcomes have equal probabilities.

Alice stops drawing numbers when she gets k or more points.

Return the probability that Alice has n or fewer points.

Answers within 10-5 of the actual answer are considered accepted.

Example 1:

Input: n = 10, k = 1, maxPts = 10
Output: 1.00000
Explanation: Alice gets a single card, then stops.


Example 2:

Input: n = 6, k = 1, maxPts = 10
Output: 0.60000
Explanation: Alice gets a single card, then stops.
In 6 out of 10 possibilities, she is at or below 6 points.


Example 3:

Input: n = 21, k = 17, maxPts = 10
Output: 0.73278


Constraints:

• 0 <= k <= n <= 104
• 1 <= maxPts <= 104

## Solutions

• class Solution {
private double[] f;
private int n, k, maxPts;

public double new21Game(int n, int k, int maxPts) {
f = new double[k];
this.n = n;
this.k = k;
this.maxPts = maxPts;
return dfs(0);
}

private double dfs(int i) {
if (i >= k) {
return i <= n ? 1 : 0;
}
if (i == k - 1) {
return Math.min(n - k + 1, maxPts) * 1.0 / maxPts;
}
if (f[i] != 0) {
return f[i];
}
return f[i] = dfs(i + 1) + (dfs(i + 1) - dfs(i + maxPts + 1)) / maxPts;
}
}

• class Solution {
public:
double new21Game(int n, int k, int maxPts) {
vector<double> f(k);
function<double(int)> dfs = [&](int i) -> double {
if (i >= k) {
return i <= n ? 1 : 0;
}
if (i == k - 1) {
return min(n - k + 1, maxPts) * 1.0 / maxPts;
}
if (f[i]) {
return f[i];
}
return f[i] = dfs(i + 1) + (dfs(i + 1) - dfs(i + maxPts + 1)) / maxPts;
};
return dfs(0);
}
};

• class Solution:
def new21Game(self, n: int, k: int, maxPts: int) -> float:
@cache
def dfs(i: int) -> float:
if i >= k:
return int(i <= n)
if i == k - 1:
return min(n - k + 1, maxPts) / maxPts
return dfs(i + 1) + (dfs(i + 1) - dfs(i + maxPts + 1)) / maxPts

return dfs(0)


• func new21Game(n int, k int, maxPts int) float64 {
f := make([]float64, k)
var dfs func(int) float64
dfs = func(i int) float64 {
if i >= k {
if i <= n {
return 1
}
return 0
}
if i == k-1 {
return float64(min(n-k+1, maxPts)) / float64(maxPts)
}
if f[i] > 0 {
return f[i]
}
f[i] = dfs(i+1) + (dfs(i+1)-dfs(i+maxPts+1))/float64(maxPts)
return f[i]
}
return dfs(0)
}

• function new21Game(n: number, k: number, maxPts: number): number {
const f = new Array(k).fill(0);
const dfs = (i: number): number => {
if (i >= k) {
return i <= n ? 1 : 0;
}
if (i === k - 1) {
return Math.min(n - k + 1, maxPts) / maxPts;
}
if (f[i] !== 0) {
return f[i];
}
return (f[i] = dfs(i + 1) + (dfs(i + 1) - dfs(i + maxPts + 1)) / maxPts);
};
return dfs(0);
}