<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;
    int solve(int n, int k, int target,vector<vector<int>>&dp){
        if(target<0){
            return 0;
        }
       if(n==0 ){
        return target == 0 ? 1 : 0;
       }

       if(dp[n][target]!= -1){
        return dp[n][target];
       }
      long long ans=0;
      for(int i=1;i<=k;i++){
        if(target-i>=0){
        ans=ans+ solve(n-1,k,target-i,dp);
        ans%=mod;
        }
      }
      dp[n][target]=(int)ans;
      return dp[n][target];

    }
    int spaceoptimazition(int n, int k, int target,vector<int>&dp){
        dp[0]=1;
        for(int i=1;i<=n;i++){
             vector<int>newdp(target+1,0);
            for(int sum=1;sum<=target;sum++){
                for(int face=1;face<=k && face<=sum;face++){
                   newdp[sum]=(newdp[sum]+dp[sum-face]) % mod;
                }
            }
           dp.swap(newdp);
        }
        return dp[target];
    }
public:
    int numRollsToTarget(int n, int k, int target) {
        //rec+memo
        // vector<vector<int>>dp(n+1,vector<int>(target+1,-1));
        // return solve(n,k,target,dp);
        // tabulation with space-optimization
        vector<int>dp(target+1,0);
        return spaceoptimazition(n,k,target,dp);
    }
};


// tab
// class Solution {
// public:
    
//     int numRollsToTarget(int n, int k, int target) {
//         if (n * k < target) return 0;
//         long dp[31][1001] = {0};
//         dp[0][0] = 1;
//         int mod = 1e9 +7;
//         for (int i = 1; i <= n; i++) {
//             for (int t = 1; t <= target; t++) {
//                 for (int j = 1; j <= k; j++) {
//                     if (t < j) break;
//                     dp[i][t] += dp[i - 1][t - j];
//                     dp[i][t] %= mod;
//                 }
//             }
//         }
//         return dp[n][target];  
//     }
// };
9680