we're given a set of naturals and we want to find , the smallest number that can't be written as a sum of elements from .
§ By observation
- Key observation: If we sort the set as , then we must have . For if not, then is the smallest nmber which cannot be written as a sum of elements.
- Next, if we think about the second number, it must be . If not, we return as the answer.
- The third number can be . Interestingly, it can also be , since we can write , so we can skip as an input.
- What about ? If we had so far, then see that we can represent all numbers upto . If we have so far, then we can represent all numbers upto . Is it always true that given a "satisfactory" sorted array (to be defined recursively), we can always build numbers upto ?
- The answer is yes. Suppose the array can represent numbers upto . Let's now append into . ( for result). Define
B := append(A, r). We claim we can represent numbers using numbers from . By induction hypothesis onA. We can represent from . We've added to this array. Since we can build numbers from , we can add to this to build the range . In total, by not choosing , we build the segment and by choosing we build the segment giving us the full segment .
§ Take 2: code
- Input processing:
void main() { int n; cin >> n; vector<ll> xs(n); for (ll i = 0; i < n; ++i) { cin >> xs[i]; }- Sort to order array
sort(xs.begin(), xs.end());- Next define
ras max sum seen so far.
ll r = 0; // Σ_i=0^n xs[i]- We can represent number What can be? If it is greater than , then we have found a hole. If , then we can already represent . We now have . By using the previous numbers, we can represent the sums , which is equal to .
- More generally, if , we can represent .
- The condition that this will not leave a gap between and is to say that .
for (ll i = 0; i < n; ++i) { if (xs[i] <= r+1) { // xs[i] can represent r+1. // We can already represent [0..r] // By adding, we can represent [0..r] + (xs[i]) = [xs[i]..r+xs[i]] // Since xs[i] <= r+1, [xs[i]..r+xs[i]] <= [r+1, 2r+1]. // In total, we can represent [0..r] (not using xs[i]) and [<=r+1, <=2r+1] // (by using xs[i]) So we can can be sure we won't miss numbers when going // from [1..r] to [xs[i]<=r+1...] The largest number we can represent is // [xs[i]+r]. r += xs[i]; // max number we can represent is previous max plus current } else { // xs[i] > r+1. We have a gap at r+1 cout << r + 1 << "\n"; return; } } cout << r + 1 << "\n";}