<p>You are given two numeric strings <code>num1</code> and <code>num2</code> and two integers <code>max_sum</code> and <code>min_sum</code>. We denote an integer <code>x</code> to be <em>good</em> if:</p>

<ul>
	<li><code>num1 &lt;= x &lt;= num2</code></li>
	<li><code>min_sum &lt;= digit_sum(x) &lt;= max_sum</code>.</li>
</ul>

<p>Return <em>the number of good integers</em>. Since the answer may be large, return it modulo <code>10<sup>9</sup> + 7</code>.</p>

<p>Note that <code>digit_sum(x)</code> denotes the sum of the digits of <code>x</code>.</p>

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

<pre>
<strong>Input:</strong> num1 = &quot;1&quot;, num2 = &quot;12&quot;, <code>min_sum</code> = 1, max_sum = 8
<strong>Output:</strong> 11
<strong>Explanation:</strong> There are 11 integers whose sum of digits lies between 1 and 8 are 1,2,3,4,5,6,7,8,10,11, and 12. Thus, we return 11.
</pre>

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

<pre>
<strong>Input:</strong> num1 = &quot;1&quot;, num2 = &quot;5&quot;, <code>min_sum</code> = 1, max_sum = 5
<strong>Output:</strong> 5
<strong>Explanation:</strong> The 5 integers whose sum of digits lies between 1 and 5 are 1,2,3,4, and 5. Thus, we return 5.
</pre>

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

<ul>
	<li><code>1 &lt;= num1 &lt;= num2 &lt;= 10<sup>22</sup></code></li>
	<li><code>1 &lt;= min_sum &lt;= max_sum &lt;= 400</code></li>
</ul>

class Solution:
    def solve(self,num,mn,mx,n,sm,flag,dp):
        
        #base
        if n==1:
            upper_bound=9
            if flag==1:
                upper_bound=int(num[len(num)-n])
            val=0
            for i in range(0,upper_bound+1):
                if sm+i>=mn and sm+i<=mx:
                    val+=1
            return val
        
        if dp[n][sm][flag]!=-1:
            return dp[n][sm][flag]
        
#setting upperbound till where we can run our loop without crossing the num2 number
        upper_bound=9
        if flag==1:
            upper_bound=int(num[len(num)-n])
        
        ans=0
        for i in range(upper_bound+1):
            f=flag
            flag=flag&(upper_bound==i)
            ans+=self.solve(num,mn,mx,n-1,sm+i,flag,dp)
            flag=f
        dp[n][sm][flag]=ans
        return dp[n][sm][flag]
        
    def count(self, num1: str, num2: str, min_sum: int, max_sum: int) -> int:
    #3d dp for digits , sum and flag(it will tell up whether we have reached upperbound like in 56 upperbound for first digit is 5 after taking 5 at first place we have to be careful regarding second place that is we can't take greater than 6 otherwise we will exceed our range)
        dp=[[[-1 for _ in range(2)] for _ in range(401)] for _ in range(24)]
    #First computing answer from 1 to num2
        val=self.solve(num2,min_sum,max_sum,len(num2),0,1,dp)
        dp=[[[-1 for _ in range(2)] for _ in range(401)] for _ in range(24)]
    #second computing answer from 1 to num1
        val2=self.solve(num1,min_sum,max_sum,len(num1),0,1,dp)
        
        digi_sum=0
        for i in num1:
            digi_sum+=int(i)
    #we have to include num1 as well if it satifies the good number criteria
        if digi_sum >= min_sum and digi_sum<=max_sum:
            val+=1
        return (val-val2)%1000000007
1228