Consider a pyramid made up of blocks. Each layer of the pyramid is a rectangle of blocks, and the dimensions of these rectangles increment as you descend the pyramid. So, if a layer is a `3x6` rectangle of blocks, then the next layer will be a `4x7` rectangle of blocks. A `1x10` layer will be on top of a `2x11` layer on top of a `3x12` layer, and so on.

## Task

Given the dimensions of a pyramid's topmost layer `w,l`, and its height `h` (aka the number of layers), return the total number of blocks in the pyramid.

## Examples

`num_blocks(1, 1, 2)` will return `5`. This pyramid starts with a `1x1` layer and has 2 layers total. So, there is 1 block in the first layer, and `2x2=4` blocks in the second. Thus, 5 is the total number of blocks.

`num_blocks(2, 4, 3)` will return `47`. This pyramid has 3 layers: `2x4`, `3x5`, and `4x6`. So, there are `47` blocks total.

## Notes

All parameters will always be postive nonzero integers.

Efficiency is important. There will be:

* 100 'small' cases with `w`, `l`, and `h` below `20`.
* 100 'big' cases with `w`, `l`, and `h` between `1e9` and `1e10`.

Difficulty: introductory

Starter code:

def num_blocks(w, l, h):
	

Solutions:
def num_blocks(w, l, h):
    return w*l*h + (w+l)*h*(h-1)/2 + h*(h-1)*(2*h-1)/6

def num_blocks(w, l, h):
    return w*l*h + (w+l) * (h-1)*h//2 + (h-1)*h*(2*h-1)//6
    
"""
For those who wonder:

first layer being of size w*l, the total number of blocks, SB, is:

       SB = w*l + (w+1)*(l+1) + (w+2)*(l+2) + ... + (w+h-1)*(l+h-1)

So:    SB = " Sum from i=0 to h-1 of (w+i)*(l+i) "

Let's use the following notation for this:  SB = S(i)[ (w+i)*(l+i) ]

Then:
       SB = S(i)[ w*l + i(w+l) + i**2 ]
          
          = S(i)[ w*l ] + S(i)[ i(w+l) ] + S(i)[ i**2 ]
          
          =    w*l*h    + (w+l) * S(i)[ i ] + S(i)[ i**2 ]


Here, you find two classic sums of sequences (see wiki or equivalent for the demonstrations):

    S(i)[ i ]    = sum of all integers from 1 to x = x*(x+1) // 2
    S(i)[ i**2 ] = sum of all squares of integers from 1 to x = x*(x+1)*(2*x+1) // 6

Since on our side we do the sum from 0 (which doesn't affect at all the result)
to h-1 in place of x, we get:

        SB = w*l*h + (w+l) * (h-1)*h//2 + (h-1)*h*(2*h-1)//6

"""

def num_blocks (width, length, height):
    
    def linsum (n):
        return n * (n+1) // 2
        
    def sqrsum (n):
        return n * (n+1) * (2*n+1) // 6
        
    cube = width * length * height
    stairs = (width+length) * linsum(height-1)
    corner = sqrsum(height-1)
    
    return cube + stairs + corner
    


def num_blocks(w, l, h):
    return w*l*h + (h-1)*h*(w+l+1)//2 + (h-2)*(h-1)*h//3

from fractions import Fraction

def num_blocks(w,l,h):

    a = h*w*l
    b = Fraction((h-1)*(h)*(w+l),2)
    print(b)
    c = Fraction((h-1)*h*(2*h-1),6)
    print(c)
    return int(a+b+c) 


def num_blocks(w, l, h):
    h -= 1
    return ((h*(h+1)*((2*h)+1))//6)+(((w+l)*h*(h+1))//2 + w*l*h) + w*l


def num_blocks(w, l, h):
    return h*(1-3*h+2*h*h-3*l+3*h*l-3*w+3*h*w+6*l*w)//6

def num_blocks(w, l, h):
    res= w*l*h 
    h-=1
    A = h*(h+1)//2
    B = (h+1)*(2*h+1)*h//6
    res+= (w+l)*A+B
    return res


def num_blocks(w, l, h):
    return h*w*l + (w+l)*h*(h-1)//2 + h*(h-1)*(2*h-1)//6

num_blocks=lambda w,l,h:(2*h*h+3*h*(l+w-1)+3*(2*l*w-l-w)+1)*h//6