Најмањи број који није збир елемената скупа - Решење

Поставка

Чињеница да су елементи сортирани олакшава решење задатка. Обрађиваћемо елемент по елемент и одржаваћемо границу до које смо сигурни да се сваки број може представити као збир неког подскупа. Можда мало изненађујуће, та граница је у сваком кораку једнака збиру свих тренутно учитаних елемената. Ако је нови учитани елемент строго већи од збира свих претходних елемената увећаног за један, онда се тај увећани збир не може добити као подскуп. У супротном можемо бити сигурни да се сви бројеви од 0 па до збира свих елемената (у који је укључен и нови елемент) могу добити као збир неког подскупа. Наиме, пошто је у претходном кораку било могуће добити све бројеве од 1 до збира свих елемената без тог новог, када у све те подскупове укључимо нови елемент добићемо све бројеве од тог новог елемента, па до збира свих елемената са тим новим елементом.

Пример. На пример, нека је дат низ \(1, 2, 3, 5, 14, 20, 27\).

#include <iostream>

using namespace std;

int main() {
  int n;
  cin >> n;
  // sabiranjem elemenata trenutnog skupa mogu se dobiti svi elementi
  // iz intervala [0, mozeDo]
  int mozeDo = 0; 
  for (int i = 0; i < n; i++) {
    int x; cin >> x;
    if (x > mozeDo + 1)
      break;
    mozeDo += x;
  }
  cout << mozeDo + 1 << endl;
  return 0;
}

Сложеност. Програм се решава једним проласком кроз низ бројева и сложеност је прилично очигледно \(O(n)\).

Доказ коректности. Докажимо и формално коректност, овог алгоритма тј. програма датог у прилогу.

Лема: Нека је \(m\) вредност променљиве mozeDo. Инваријанта петље је да је \(0 \leq i \leq n\), да је \(m\) збир првих \(i\) елемената низа и да се сваки број из интервала \([0, m]\) може добити као збир неког подскупа првих \(i\) елемената низа.

Доказ: Пре уласка у петљу је \(i=0\) и \(m=0\). Збир првих \(i=0\) елемената низа је по дефиницији нула (тј. \(m\)). Број \(0\) је једини елемент интервала \([0, m] = [0, 0]\) и он се може добити као збир празног подскупа (тј. 0 елемената полазног низа).

Претпоставимо да тврђење важи пре уласка у петљу.

Теорема: Када се програм заврши, вредност \(m+1\) је најмањи природни број који се не може представити као збир унетих бројева.

Доказ: Случај када се петља заврши прекидом, јер је \(a_i > m+1\) је већ размотрен. Када се петља заврши, важи да је \(i = n\). На основу инваријанте \(m\) је збир свих елемената низа, и сваки број из \([0, m]\) јесте збир неког подскупа првих \(i=n\) елемената низа, тј. целог низа. Зато је \(m+1\) најмањи елемент који није могуће добити (јер се укључивањем свих елемената добија највише \(m\)) и исписано решење је исправно.

У наредном аплету можете видети како овај алгоритам функционише.