Download as pdf or txt
Download as pdf or txt
You are on page 1of 6

HONI 2016/2017

6. kolo, 4. veljače 2017.

Opisi algoritama
Zadatak Blizanci Autor: Nikola Dmitrović

Mama će kupiti majicu ako i Filip i Jakov kažu da im se ona sviđa, tj.ako obojica kažu “1”. I
tako za svaku od N majica koje je mama odabrala.

Programski kod:

N = int(input()) # broj majica koje je mama odabrala

koliko = 0 # broj majica koje će mama kupiti

for i in range(N): # za svaku odabranu majicu


Fi, Ji = map(int, input().split()) # učitaj mišljenje Filipa i Jakova

if Fi + Ji == 2: # ako su mišljenja ista i iznose “1” (dva u zbroju)


koliko += 1¸ # kupi majicu

print(koliko) # ispiši broj majica koje će mama kupiti

Potrebna znanja: ​naredba ponavljanja, naredba odlučivanja


Kategorija:​ ad-hoc

Zadatak Podjela Autor: Marija Gegić

Ivica će vrećicu moći ponijeti u školu ukoliko je broj bombona koji se nalazi u vrećici djeljiv s
brojem njegovih prijatelja. Za dobivanje traženog rješenja, potrebno je prilikom učitavanja
svakog od N brojeva provjeriti je li ostatak pri dijeljenju učitanog broja s M jednak 0, te ako
jest, povećati neki brojač. Vrijednost brojača nakon učitavanja svih N brojeva bit će traženo
rješenje.

Potrebna znanja:​ ​for petlja


Kategorija:​ ad-hoc

Zadatak H-indeks Autor: Adrian Satja Kurdija

Pri određivanju h-indeksa očito treba gledati radove sa što većom citiranošću. Zato najprije
sortiramo brojeve po veličini počevši od najvećeg. Po takvom nizu prolazimo redom (indeks
K = 1, 2, 3, …) i ako je K-ti element veći ili jednak K, to znači da je K potencijalni h-indeks
(jer znanstvenik tada ima barem K radova s citiranošću većom ili jednakom K). Zadatak se
svodi na pronalaženje najvećeg takvog K, što lako rješavamo pamteći rješenje u pomoćnoj
varijabli i ažurirajući ga dok prolazimo nizom.
Potrebna znanja:​ sortiranje niza
Kategorija:​ ad-hoc

Zadatak Telefoni Autor: Nikola Herceg

Primijetimo da će niz telefona koji zvone uvijek biti neki uzastopni niz telefona od onog na
prvom stolu do onog na p-tom(prefiks). Sada želimo povećati taj prefiks dodavanjem novog
telefona. Njega možemo postaviti na stol p + 1, p + 2,...,p + d, jer ako ga postavimo desnije
od stola p + d, on neće zazvoniti. Očito se najviše isplati postaviti ga na stol p + d, jer će tako
novi prefiks biti najveće duljine. To implementiramo tako da iteriramo slijeva nadesno i
pamtimo lokaciju zadnjeg telefona koji zvoni te postavljamo novi telefon ako je razlika
trenutne pozicije i stola na kojem je zadnji telefon jednaka d. Složenost je O(n).

Potrebna znanja:​ nizovi


Kategorija:​ greedy

Zadatak: Turnir Autor: Dominik Gleich

Prvo je potrebno primijetiti da nam je jedina bitna informacija za svaki broj ​X broj većih
brojeva od njega. Zašto nam je to bitno? Zato što samo će veći brojevi prelaziti na razinu
iznad, sa svim ostalim brojevima trenutni će broj ​X ​nastavljati put prema vrhu. Tu je
informaciju lako izračunati sortiranjem brojeva.

Pokušajmo izračunati najvišu razinu na kojoj se broj ​X može nalaziti. Za nultu razinu on očito
ne smije imati niti jedan broj veći od sebe, tj. broj brojeva većih od njega mora biti 0. Kako bi
završio na prvoj razini, mora postojati najviše n/2 brojeva većih od njega, jer u suprotnom
barem će jedan broj veći od njega imati ‘okršaj’ s njim na nekoj nižoj razini što će rezultitirati
njegovim ne prolaskom na višu razinu. U slučaju da ima više brojeva od n/2 koji su veći od
njega on se mora nalaziti na nekoj razini ispod 1. razine. Sada, kako bi se nalazio na 2.
razini broj brojeva većih od njega ne smije biti veći od n/2 + n/4. Zašto?
Lako je uvidjeti kako n/2 brojeva možemo ostaviti na razini iznad na drugoj strani stabla,
zatim nam ostaje n/2 brojeva u kojoj se nalazi broj X. I na trenutnoj drugoj razini radimo istu
odluku gdje gledamo možemo li u drugom podstablu veličine n/4 ostaviti sve veće brojeve od
njega kako bi se broj X nesmetano mogao uzdići do vrha svog podstabla, tj. razine 2.
Nastavljamo sljedeći algoritam, oduzimajući padajuće potencije broja 2 s broja brojeva većih
od ​X​. Za implementacijske detalje pogledajte službeno rješenje.

Ukupna složenost algoritma je O(N lg N).

Potrebna znanja:​ nizovi, rekurzivan rastav problema


Kategorija:​ ad-hoc, matematika
Zadatak Savršen Autor: Adrian Satja Kurdija

Umjesto da za zadane brojeve tražimo njihove djelitelje (što je presporo), možemo ići
obrnuto, slično Eratostenovom situ: za svaki broj d = 1, 2, 3, …, B pogledati čiji je on djelitelj,
tj. proći po njegovim višekratnicima između A i B te za svaki njegov višekratnik V povećati
njegov zbroj djelitelja: zbroj[V] += d. Na kraju prođemo po dobivenom nizu zbrajajući tražene
apsolutne razlike.

Na prvi pogled se čini da bi ovaj pristup mogao biti prespor, ali empirijski se utvrđuje da nije.
Teorijski to možemo ovako zaključiti: za svaki djelitelj d prolazimo po B/d višekratnika, što
daje ukupnu složenost B/1 + B/2 + B/3 + … + B/B, tj. B * (1 + 1/2 + 1/3 + … + 1/B), a to je
približno B log B.

Potrebna znanja:​ Eratostenovo sito


Kategorija:​ teorija brojeva

Zadatak Sirni Autor: Domagoj Bradač

U zadatku je potrebno pronaći minimalno razapinjajuće stablo u grafu u kojem su dva čvora
a i ​b povezana težinom min(P a % P b, P b % P a) . Ovaj izraz je jednak P a % P b za
P a > P b i obratno.

Ako postoje dva čvora s jednakom vrijednošću, njih možemo povezati s cijenom nula i
promatrati kao jedan čvor. Nadalje ćemo pretpostaviti da su sve vrijednosti čvorova
jedinstvene. Za svaku vrijednost čvora ​Px iterirat ćemo po svim njezinim višekratnicima
k * P x ≤ M pri čemu ​M označava najveću moguću vrijednost nekog čvora. Za svaki takav
višekratnik, pronaći ćemo čvor s najmanjom vrijednošću većom ili jednakom od x, te u
slučaju k = 1 , čvor s najmanjom vrijednošću strogo većom od P ​ x. Označimo taj čvor s ​y, te
dodajmo odgovarajući brid u popis bridova koje moramo obraditi.

Time smo dobili najviše O(M log M) bridova, od kojih možemo Kruskalovim algoritmom
napraviti minimalno razapinjajuće stablo. Sortiramo li bridove naivno, dobit ćemo rješenje
vrijedno 70% bodova, no s obzirom da su sve težine bridova do M ​ , možemo koristeći
counting sort dobiti algoritam složenosti O(N + M log M) .

Preostaje pokazati da postoji minimalno razapinjajuće stablo koje sadrži samo bridove koje
smo izdvojili. Pretpostavimo suprotno, tj. postoji stablo koje sadrži neki drugi brid, i ima
manju cijenu od bilo kojeg stabla koje sadrži samo izdvojene bridove. Neka je taj brid između
čvorova ​a i ​b. Neka je P a < P b i k * P a ≤ P b < (k + 1) * P a . Tada, s obzirom da
nismo izdvojili taj brid, postoje neki čvorovi ​c1, c​2​, … c​n​ takvi da vrijedi
k * P a ≤ P c1 < P c2 < ... < P cn < P b , tj. P a < P c1 < P c2 < ... < P cn < P b ako je
k = 1 . No, tada smo izdvojili bridove (a, c1), (c1, c2), (c2, c3), ... (cn−1, cn), (cn, b) . Njihova
ukupna cijena je P b − k * P a = P b % P a . No, tada možemo izbaciti brid (a, b) i umjesto
njega staviti put od ​a do ​b ili neki njegov dio i time dobiti povezan graf s manjom ili jednakom
težinom prijašnjem.

Potrebna znanja:​ Kruskalov algoritam, Eratostenovo sito


Kategorija:​ grafovi, matematika

Zadatak Gauss Autor: Mislav Balunović

Prvo primijetimo kako će Gauss u optimalnom rješenju operaciju drugog tipa (ostavljanje
trenutnog broja na ploči) raditi samo za jedan broj. Označimo sa A početni broj, sa B konačni
broj te sa C broj koji smo ostavljali na ploči.

Drugo, primijetite da je broj operacija između brojeva A i C te između C i B najviše 20 jer u


svakom trenutku novi broj bude manji ili jednak polovice starog broja. Nije teško uočiti da je
cijena najkraćeg puta od A do C jednaka cijeni najkraćeg puta od A/C do 1 (analogno za C i
C/B).

Zbog specifičnosti formule za izračun cijena, vidimo da je cijena najkraćeg puta do 1 jednaka
primjerice za brojeve 12 i 18. Preciznije, neka su e​1​, e​2​, …, e​k​ eksponenti prostih brojeva u
rastavu nekog broja na proste faktore. Tada je cijena najkraćeg puta od tog broja do 1
jednaka za sve brojeve koji imaju isti multiskup eksponenata {e​1​, e​2​, …, e​k​}.
Možemo izgenerirati sve takve brojeve i vidjeti da ih ima manje od 250.
Svakom broju n dodijelimo najmanji broj s kojim dijeli multiskup i označimo ga sa k(n).

Sažmimo dosadašnje rezultate:


Najkraći put od A do B ide preko nekog broja C. Cijena od A do C jednaka je cijeni od A/C
do 1, a to je jednako cijeni od k(A/C) do 1. Analogno za C do B i k(B/C).
Označimo sa b[x][y][C][L] najkraći put od nekog A do nekog B takvih da vrijedi k(A/C) = x i
k(C/B) = y te je ukupna duljina puteva od A do C i C do B jednaka točno L (ne računajući
poteze iz C u samog sebe).
Taj niz se može dovoljno brzo izračunati na početku programa uz jednu optimizaciju -
računat ćemo ga samo za parove x i y takve da je x * y najviše 1 000 000 jer inače nam ti
parovi nisu korisni.

Kako odgovaramo na upite kada imamo takav niz?


Prođimo po svim mogućim C te pogledajmo kako izgleda formula za neki ukupan broj poteza
L, te označimo sa L’ broj poteza kada smo ostavili C na ploči:
Ukupna cijena je b[x][y][C][L - L’] + L’ * cijena[C].
Sada vidimo da za neki fiksni L moramo pronaći par (C, L’) koji minimizira vrijednost gornjeg
izraza, a to je zapravo standardni problem u kojemu moramo izračunati donju ljusku pravaca
te za svaki L pronaći presjek vertikalnog pravca x = L sa ljuskom.
Treba još primijetiti da svi pravci za neki fiksni C imaju isti nagib tako da je dovoljno
izračunati najveći presjek njegovih pravaca sa y osi te samo njega ubaciti u ljusku.
Upite u kojima je L manji od 20 treba obraditi posebno dinamičkim programiranjem.

Potrebna znanja: ​teorija brojeva, konveksna ljuska pravaca


Kategorija: ​teorija brojeva

You might also like