We know that the values โโare nonzero and grow monotonously from left to right.
The idea is to list the possible amounts (any order, from left to right in order) and then list the subsets to the left of this value, because the values โโon the right cannot participate (they would make the amount too large). We do not need to instantiate the set; as we consider each value, see how it affects the amount. It can be too large (just ignoring this value cannot be in the set), right (its last member in the set), or too small, and at what point it can or cannot be set.
[This problem made me play with Python for the first time. Fun.]
Here's the Python code; according to Cprofile.run it takes .00772 seconds on my P8700 2.54Ghz laptop.
values = [3, 4, 9, 14, 15, 19, 28, 37, 47, 50, 54, 56, 59, 61, 70, 73, 78, 81, 92, 95, 97, 99] def count(): # sort(values) # force strictly increasing order last_value=-1 duplicates=0 totalsets=0 for sum_value in values: # enumerate sum values if last_value==sum_value: duplicates+=1 last_value=sum_value totalsets+=ways_to_sum(sum_value,0) # faster, uses monotonicity of values return totalsets-len(values)+duplicates def ways_to_sum(sum,member_index): value=values[member_index] if sum<value: return 0 if sum>value: return ways_to_sum(sum-value,member_index+1)+ways_to_sum(sum,member_index+1) return 1
The resulting number I get is 179. (Corresponds to another poster.)
EDIT: ways_to_sum can be partially implemented using a tail recursion loop:
def ways_to_sum(sum,member_index): c=0 while True: value=values[member_index] if sum<value: return c if sum==value: return c+1 member_index+=1 c+=ways_to_sum(sum-value,member_index)
This requires: .005804 seconds: -} The same answer.