Koliko puta se izvrši?
Za dati broj n (1 ≤ n ≤ 1018) ispiši koliko puta se izvrši telo petlje for (i = 1; i <= n; i *= 2).
Primer 1
Ulaz
1Izlaz
1Primer 2
Ulaz
8Izlaz
4Primer 3
Ulaz
1000000000000000000Izlaz
60Dva tačna programa mogu da rade potpuno različito vreme: jedan za delić sekunde, a drugi satima. Složenost opisuje kako vreme rada raste kada raste ulaz. Kada je znamo, pre pisanja programa možemo da procenimo da li će rešenje stići u vremensko ograničenje zadatka.
Ne merimo sekunde (zavise od računara), već broj osnovnih koraka u zavisnosti od veličine ulaza n. Pogledajmo tri načina da se izračuna zbir 1 + 2 + … + n:
#include <iostream>
using namespace std;
int main() {
long long n;
cin >> n;
// 1) jedna petlja: n sabiranja – O(n)
long long s1 = 0;
for (long long i = 1; i <= n; i++) s1 += i;
// 2) dve petlje: dodajemo 1 po 1 – oko n²/2 sabiranja – O(n²)
long long s2 = 0;
for (long long i = 1; i <= n; i++)
for (long long j = 1; j <= i; j++) s2++;
// 3) formula: tri operacije bez obzira na n – O(1)
long long s3 = n * (n + 1) / 2;
cout << s1 << " " << s2 << " " << s3 << endl;
return 0;
}
Za n = 109 prvi način radi oko sekunde, drugi bi trajao vekovima, a treći je trenutan.
Kažemo da algoritam ima složenost O(f(n)) ako je broj koraka najviše srazmeran sa f(n). Konstante i manji sabirci se zanemaruju: 3n² + 5n + 7 koraka je O(n²), jer za veliko n dominira n².
| Složenost | Naziv | Tipičan primer |
|---|---|---|
| O(1) | konstantna | formula, pristup a[i] |
| O(log n) | logaritamska | binarna pretraga, brzo stepenovanje |
| O(√n) | korenska | provera da li je broj prost (delioci do √n) |
| O(n) | linearna | jedan prolaz kroz niz |
| O(n log n) | „n log n“ | sortiranje |
| O(n²) | kvadratna | dve ugnježdene petlje, svi parovi |
| O(n³) | kubna | tri petlje, Floyd-Warshall |
| O(2ⁿ) | eksponencijalna | svi podskupovi, bektreking |
| O(n!) | faktorijelna | sve permutacije |
Računar uradi oko 108 prostih operacija u sekundi. Iz ograničenja za n u postavci zato se skoro uvek vidi kakvo rešenje se očekuje:
| Ograničenje | Najsporija složenost koja prolazi (≈1 s) | Šta to obično znači |
|---|---|---|
| n ≤ 10–11 | O(n!) | sve permutacije |
| n ≤ 20–25 | O(2ⁿ) | svi podskupovi, bektreking |
| n ≤ 500 | O(n³) | tri petlje, DP sa tri indeksa |
| n ≤ 5 000 | O(n²) | dve petlje, DP sa dva indeksa |
| n ≤ 106 | O(n log n) | sortiranje, binarna pretraga, priority_queue |
| n ≤ 108 | O(n) | jedan prolaz, prefiksne sume |
| n ≤ 1018 | O(log n) ili O(1) | formula, binarna pretraga po odgovoru, brzo stepenovanje |
while (n > 0) n /= 2;sort je O(n log n), s.insert u set O(log n), v.erase(v.begin()) nad vektorom O(n)!// koliko cifara ima broj n u binarnom zapisu? – O(log n)
int cifre = 0;
while (n > 0) {
n /= 2;
cifre++;
}
for (int i = 0; i < s.size(); i++) s = s + "x"; izgleda kao jedna petlja, ali svako sabiranje stringova kopira ceo string – ukupno O(n²). Isto važi za v.insert(v.begin(), x) i brisanje sa početka vektora.I memorija je ograničena (obično 64–256 MB). Niz od 107 brojeva tipa int zauzima 40 MB, a tipa long long 80 MB. Matrica int a[10000][10000] zauzima 400 MB – prevelika. Zato se pazi i na memorijsku složenost: O(n) memorije je skoro uvek u redu, O(n²) samo za n do nekoliko hiljada.
Za svaki zadatak postoji primer, uputstvo i rešenje. Rešenja su provereno tačna na primerima iz teksta.
Za dati broj n (1 ≤ n ≤ 1018) ispiši koliko puta se izvrši telo petlje for (i = 1; i <= n; i *= 2).
1184100000000000000000060Dato je n ≤ 2·105 različitih celih brojeva i broj K. Ispiši koliko ima parova (neuređenih) sa zbirom tačno K. Rešenje O(n²) je prespor.
6 10
1 9 3 7 5 223 4
2 1 31long long; složenost ne pomaže ako je rezultat pogrešan zbog prekoračenja.1. Kolika je složenost dve ugnježdene petlje do n?
2. Ograničenje je n ≤ 10⁶. Koja složenost sigurno prolazi za oko sekundu?
3. Kolika je složenost petlje while (n > 0) n /= 2;?
4. Koliko operacija u sekundi otprilike uradi računar?