<p>You have <code>n</code> dice, and each dice has <code>k</code> faces numbered from <code>1</code> to <code>k</code>.</p>

<p>Given three integers <code>n</code>, <code>k</code>, and <code>target</code>, return <em>the number of possible ways (out of the </em><code>k<sup>n</sup></code><em> total ways) </em><em>to roll the dice, so the sum of the face-up numbers equals </em><code>target</code>. Since the answer may be too large, return it <strong>modulo</strong> <code>10<sup>9</sup> + 7</code>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> n = 1, k = 6, target = 3
<strong>Output:</strong> 1
<strong>Explanation:</strong> You throw one die with 6 faces.
There is only one way to get a sum of 3.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> n = 2, k = 6, target = 7
<strong>Output:</strong> 6
<strong>Explanation:</strong> You throw two dice, each with 6 faces.
There are 6 ways to get a sum of 7: 1+6, 2+5, 3+4, 4+3, 5+2, 6+1.
</pre>

<p><strong class="example">Example 3:</strong></p>

<pre>
<strong>Input:</strong> n = 30, k = 30, target = 500
<strong>Output:</strong> 222616187
<strong>Explanation:</strong> The answer must be returned modulo 10<sup>9</sup> + 7.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= n, k &lt;= 30</code></li>
	<li><code>1 &lt;= target &lt;= 1000</code></li>
</ul>

class Solution {
    int mod = 1e9+7;

    unordered_map<int, unordered_map<int, long long>> cache;      // cache[n][target] = number of possible ways

    long long doDFS(int n, int k, int target)
    {
        if (n == 0)
            return (target == 0) ? 1 : 0;

        if (target == 0)
            return 0;

        if (cache.find(n) != cache.end() && cache[n].find(target) != cache[n].end())
            return cache[n][target];

        long long sum = 0;
        for (int i=1; i <= min(target, k); i++)
        {
            sum += doDFS(n-1, k, target-i);
            sum %= mod;
        }

        return cache[n][target] = sum;
    }
public: // Complexity: O(n*k*target)
    int numRollsToTarget(int n, int k, int target) {
        return doDFS(n, k, target);
    }


/*  // Complexity: O(N*T*K)     Space: O(N*T)
    int numRollsToTarget(int n, int k, int target) {
        vector<long long> dp_1(target+1, 0);
        for (int i=1; i <= min(k, target); i++)
            dp_1[i] = 1;

        dp_1[0] = 1;    // Note:

        for (int i=1; i<n; i++)
        {
            vector<long long> dp(target+1, 0);
            dp[0] = 1;

            for (int j=1; j <= target; j++)
            {
                for (int _k=1; _k <= min(j, k); _k++)
                {
                    dp[j] += dp_1[j - _k];
                    dp[j] %= mod;
                }
            }

            dp_1 = dp;
        }

        return dp_1[target];
    }                                                   */
};
16720