You can work it out with a recursive algorithm. I'm not sure if there is a neater way, for example with a closed formula - you have to account for the different numbers of doughnuts of each type at some point.
The line of thinking goes like this: if you look at the first type of doughnuts, you can choose freely how many to take. You then subtract that number from the total you want, and apply the same process to the other types. Once you run out of types of doughnuts, you either want a total of 0, in which case you've picked the required number of doughnuts, or you want a non-zero number of doughnuts, which means you picked too few or too many.
So the base of the recursion is that there is one way of picking no doughnuts from no baskets, and zero ways of picking any other number of doughnuts.
From that, you can work backwards, summing up the number of ways of making up the remaining total, given that you pick a certain number from the previous baskets.
I've written some Python code which does the calculations, and I've tried to add descriptions of how it works as much as possible:
#This function returns the number of ways of picking `total` doughnuts from #the array `numbers`, which is an array of numbers of each type of doughnut #available work recursively: for each possible number of doughnuts picked #from the first basket, work out how many ways there are of making up the #rest of the total from the other baskets def kcombs(numbers,total): #Base case: there is 1 way of choosing no doughnuts from no baskets #It's impossible to pick any other number of doughnuts from no baskets if len(numbers)==0: if total==0: return 1 else: return 0 else: #Otherwise, we have baskets to choose from. #we can pick at most `total` doughnuts from the first basket. #`range(0,numbers[0]+1)` represents the options for how many #doughnuts we pick from the first basket. #If we pick `i` doughnuts from the first basket, take that away from the #total, and then work out how many ways there are of picking that many #from the other baskets return sum([ #no. of ways of making up the total from the other baskets kcombs(numbers[1:],total-i) #for each choice of no. of doughnuts from the first basket for i in range(0,numbers[0]+1) ]) if __name__=='__main__': #some tests for numbers,total in [ ([],0), #one way of picking nothing from nothing ([],1), #impossible to pick one from nothing ([1],1), #one way ([2],1), #still one way - all doughnuts of one type lookthe same ([2],2), #still one way... ([2],3), #impossible to pick 3 from 2 ([1,1],2), #one way - one from each basket ([2,2],2), #3 ways - both from the first basket, one from each, or #both from the second basket ([2,2],3), #2 ways - one from 1st and two from 2nd, or vice versa ([3,1,2],4) #should be five ways ]: print('%i from %s: %i ways' % (total,numbers,kcombs(numbers,total)))