Well, i had some time so i quickly implemented a class that can do what you want 
using UnityEngine;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
using Stopwatch = System.Diagnostics.Stopwatch;
public class CombinationFinder
{
Stopwatch m_Stopwatch = new Stopwatch();
List<int> m_Values;
int m_TotalSum;
public System.TimeSpan TimeTaken { get { return m_Stopwatch.Elapsed; } }
public CombinationFinder(IEnumerable<int> aValues)
{
m_TotalSum = aValues.Sum();
m_Values = aValues.OrderByDescending(v => v).ToList();
}
public CombinationFinder(params int[] aValues) : this(aValues as IEnumerable<int>){ }
IEnumerable<int> FindCombinationStep(int aSum, int aTotalSum, int aStart)
{
if (aTotalSum == aSum)
return m_Values.Skip(aStart);
if (aTotalSum < aSum)
return null;
for (int i = aStart; i < m_Values.Count; i++)
{
aTotalSum -= m_Values*;*
if (i > aStart && m_Values[i - 1] == m_Values*)
continue;
int newSum = aSum - m_Values;
if (newSum == 0)
return Enumerable.Range(m_Values, 1);
if (newSum < 0)
continue;
var res = FindCombinationStep(newSum, aTotalSum, i + 1);
if (res == null)
continue;
return Enumerable.Range(m_Values, 1).Concat(res);
_}
return null;
}*_
public int[] FindCombination(int aSum)
{
m_Stopwatch.Reset();
m_Stopwatch.Start();
var result = FindCombinationStep(aSum, m_TotalSum, 0);
int[] array = null;
if (result != null)
array = result.ToArray();
m_Stopwatch.Stop();
return array;
}
}
Usage:
//C#
void RunTest()
{
var finder = new CombinationFinder(50, 2, 4, 6, 3, 5, 2, 7,10,55,800,40,20,15,18,17,23,25,29,40);
for (int i = 0; i < 1000; i++)
{
var res = finder.FindCombination(i);
if (res != null)
Debug.Log(“# " + i + " = " + string.Join(” + ", res.Select(a => a.ToString()).ToArray()) + " Time: " + finder.TimeTaken.TotalMilliseconds * 1000 + “µs”);
else
Debug.LogError("# " + i + " — " + " Time: " + finder.TimeTaken.TotalMilliseconds * 1000 + “µs”);
}
}
This test routine will try to find a combination with the given 20 numbers for every number between 0 and 1000 and prints the result. Note: On my PC each FindCombination call usually took something under 10µs. If there are spikes it’s most likely due to task switch / core switch (damn multitasking :D). The over all time for those 1000 calls is about 2 sec but only because of the Debug.Logs which are about 98% of that time 
I used a hybrid of recursive and iterative approach. So it actually iterates through the (sorted) list. If (theDesiredSum - theCurrentValue ) is still larger than 0, it will start a new recursion on the remaining sum and the remaining list values. There are a lot optimisations in each recursion step to terminate early when possible. For example when the list contains the same number multiple times and it doesn’t work out when using the first, it makes no sense to use the others at the same place since all combinations below this value has already been checked.
Example:
Sum = 27
values = 11, 11, 11, 11, 11, 10, 10, 4, 3
recur.
#1: 11 → remaining 16
#2: 11+ 11 → remaining 5
#3: 11+ 11+ 11 → fail
#3: 11+ 11+ – – – 10 → fail
#3: 11+ 11+ – – – – – 4 → remaining 1
#4: 11+ 11+ – – – – – 4+ 3 → fail
#2: 11+ – – – – 10 → remaining 6
#3: 11+ – – – – 10+ 10 → fail
#3: 11+ – – – – 10+ – 4 → remaining 2
#4: 11+ – – – – 10+ – 4+ 3 → fail
#2: → fail due to not enough values remaining
#1: – – – – – 10 → remaining 17
#2: → solution since remaining sum == sum
#2: returns → 10, 4, 3
#1: returns → 10, 10, 4, 3
The --
indicates a skipped number.
edit Just realized i had the 3 and 4 swapped in my example ^^ fixed it.