You can optimize this from the inside out to compute the result.
cnt = 0
for i in range(1, 10):
for j in range(i, 20):
for k in range(j, 30):
for l in range(k, 40):
cnt += 1
print(cnt)
The inner loop is simple: for l in range(k, 40)
adds one to cnt
40-k
times. Note: it's not quite clear whether you intend ranges to be inclusive or not; in Python they don't include their end point, but 1..10 suggests you intend them to be inclusive.
Taking an extra loop, we have sum(40-k for k in range(j, 30))
. It's feasible to compute this (using sum(1+2+3...+n) = n(n+1)/2
), but it quickly becomes messy. Instead, we can cheat and use Wolfram Alpha or similar to compute that it's (j^2 - 81j + 1530)/2
.
Adding in another loop: sum((j^2 - 81j + 1530)/2 for j in range(i, 20))
. Again, we could solve this using the additional formula of sums of squares of a range of numbers, but we can cheat again to get: 8075 - (i-1)(i^2 - 122i + 5490)/6
.
With the final loop included, we get 49725.
That was for fixed ranges, but the same idea works for arbitrary ranges. For this program:
cnt = 0
for i in range(1, n1+1):
for j in range(i, n2+1):
for k in range(j, n3+1):
for l in range(k, n4+1):
cnt += 1
print(cnt)
we can use Wolfram Alpha to compute sum(sum(sum(sum(1 for l=k to n4) for k=j to n3) for j=i to n2) for i=1 to n1)
to get this beast:

Again, in principle we could have computed this by hand, but it's difficult to do so without making an error.
For the second part of the question: sums consisting of two pairs, one can use the same technique. There's fewer sums because "two pairs" means j==i
and l==k
, so one gets the equivalent of this Python program:
cnt = 0
for i in range(1, n1+1):
j = i
for k in range(j, n2+1):
l = k
cnt += 1
That's sum(sum(1 for k=i to n2) for i=1 to n1)
which comes out to -n1(n1 - 2*n2 - 1)/2
.