<p>You are given an array of <strong>positive</strong> integers <code>nums</code> of length <code>n</code>.</p>

<p>We call a pair of <strong>non-negative</strong> integer arrays <code>(arr1, arr2)</code> <strong>monotonic</strong> if:</p>

<ul>
	<li>The lengths of both arrays are <code>n</code>.</li>
	<li><code>arr1</code> is monotonically <strong>non-decreasing</strong>, in other words, <code>arr1[0] &lt;= arr1[1] &lt;= ... &lt;= arr1[n - 1]</code>.</li>
	<li><code>arr2</code> is monotonically <strong>non-increasing</strong>, in other words, <code>arr2[0] &gt;= arr2[1] &gt;= ... &gt;= arr2[n - 1]</code>.</li>
	<li><code>arr1[i] + arr2[i] == nums[i]</code> for all <code>0 &lt;= i &lt;= n - 1</code>.</li>
</ul>

<p>Return the count of <strong>monotonic</strong> pairs.</p>

<p>Since the answer may be very 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>

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">nums = [2,3,2]</span></p>

<p><strong>Output:</strong> <span class="example-io">4</span></p>

<p><strong>Explanation:</strong></p>

<p>The good pairs are:</p>

<ol>
	<li><code>([0, 1, 1], [2, 2, 1])</code></li>
	<li><code>([0, 1, 2], [2, 2, 0])</code></li>
	<li><code>([0, 2, 2], [2, 1, 0])</code></li>
	<li><code>([1, 2, 2], [1, 1, 0])</code></li>
</ol>
</div>

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

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">nums = [5,5,5,5]</span></p>

<p><strong>Output:</strong> <span class="example-io">126</span></p>
</div>

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

<ul>
	<li><code>1 &lt;= n == nums.length &lt;= 2000</code></li>
	<li><code>1 &lt;= nums[i] &lt;= 1000</code></li>
</ul>

class Solution:
    def countOfPairs(self, nums: List[int]) -> int:
        
        mod = 10**9 + 7

        N = len(nums)


        """
            index 0 to 2000
            last_up  0 to max(nums[index])  (MX ) -> upto 50

            time complexity  = (number of inputs)*(time for each element)
                             = (totalElements*(MX))*(MX)
        """
        # cache ={}
        # # @cache
        # def go(index,last_up):
        #     if index == N:
        #         return 1
        #     last_down = nums[index-1] - last_up
            
        #     if (index,last_up) in cache :
        #         return cache[(index,last_up)]
        #     total = 0
        #     for i in range(nums[index]+1):
        #         if i>= last_up and nums[index] - i <= last_down:
        #             total += go(index+1,i)
        #     total %= mod

        #     cache[(index,last_up)] = total
        #     return total
        
        # total = 0
        # for i in range(nums[0]+1):
        #     total += go(1,i)
        
        # total %= mod


        """ DP 

        """

        MAX = max(nums)

        dp = [[0]*(MAX +1) for _ in range(N+1)]

        prefix_sum = [[0]*(MAX+5) for _ in range(N+1)]

        for up in range(nums[0]+1):
            dp[0][up] = 1
            prefix_sum[0][up+1] = dp[0][up] +  prefix_sum[0][up]
        
        for last_up in range(nums[0]+1):
            dp[0][last_up]  = 1
        
        for index in range(1,N):
            for up in range(nums[index] +1):

                down = nums[index] -up

                right = min(nums[index-1]-down,nums[index -1 ], up )

                """for i in range(right +1 ):
                    dp[index][up] += dp[index -1 ][i]
                    dp[index][up] %= mod

                dp[index][up] = dp[index-1][0] + dp[index-1][1]+ ... dp[index -1 ][right]
                prefix sum O(maxi)"""

                dp[index][up] =  ( prefix_sum[index-1][right+1] )%mod

                prefix_sum[index][up+1] = dp[index][up] + prefix_sum[index][up]
                prefix_sum[index][up+1] %= mod 




        total = 0

        for i in range(nums[N-1]+1):
            total += dp[N-1][i]
        
        return total % mod
157902