You are on page 1of 7

 

Zadatak STELLA  Autor: Nikola Dmitrović 

Znamenke  zadanog   četveroznamenkastog  broja  može  dobiti  pojedničnim 


određivanjem  svake  od  njih,  a  možemo  iskoristiti  i  opći  algoritam.  Za   svaku 
znamenku trebamo provjeriti je li parna ili ne. 
Programski kod (pisan u Python 3.x) 

N = int(input()) 

kockica = 0 

for i in range(4): 

zn = N % 10 

if zn % 2 == 0: 

  kockica += zn 

N //= 10 

print(kockica) 

potrebno znanje: ​
naredba odlučivanja, algoritam određivanja znamenki 

kategorija: ​
ad­hoc 
 
Zadatak PAULA  Autor: Nikola Dmitrović 

Rješenje zadatka se svodi na to da za svaki redak ulaza provjerimo je li zbroj 
elemenata u njemu između 40 i 50. 

N = int(input()) 

ukupno = 0 

for i in range(N): 

L = list(map(int, input().split()))  

# a, b, c, d, e = map(int, input().split()) 

# sum = a + b + c + d + e 
if sum(L) < 40 or sum(L) > 50: 

  ukupno += 1 

if ukupno == 0: 

print("PAULA") 

else: 

print(ukupno) 

potrebno znanje: ​
naredba odlučivanja, naredba ponavljanja, lista (opcija) 

kategorija: ​
ad­hoc 
 
Zadatak BELA  Autor: Branimir Filipović 
 
Kako bi izračunali ukupan broj bodova u partiji bele, potrebno je pozbrojiti bodove 
za svaku kartu u partiji. Za određivanje broja bodova koju pojedina karta nosi 
potrebne su nam dvije informacije: da li je karta adut (da li joj je boja jednaka ​B​
), 
te koju vrijednost nosi karta. Nakon toga, sve što je potrebno je iščitati iz dobivene 
tablice vrijednost te karte. To se jednostavno može napraviti pomoću naredbi 
odlučivanja. 
 
potrebno znanje: ​ naredba odlučivanja, naredba ponavljanja, rad sa riječima 
(stringovima) 
kategorija: ​ ad­hoc 
 
 
 
Zadatak PUTOVANJE  Autor: Dominik Gleich 
 
O ovom je zadatku jedino bitno simulirati Mislavovo kretanje i konzumiranje ukoliko 
on krene sa svake moguće pozicije i odluči od tamo početi konzumirati plodove. 
Kada krene jesti on će pojesti plod ako mu stane u želudac, inače neće i nastavit će 
dalje pokušat pojesti plodove. Dakle, potrebno je iz svake pozicije izračunat koliko 
će pojesti ako krene jesti od ploda na toj poziciji. Maksimum tih brojeva je rješenje. 
Ukupna složenost rješenja iznosi O(n^2). 
 
potrebno znanje: ​ nizovi 
kategorija: ​ad­hoc 
 
Zadatak PIANINO  Autor: Marin Tomić 
 
Neka  su  s  a​ ,  …,  a​
1​ N  označene  odsvirane   note.   Definiramo  niz  brojeva  b​ 1​,  …,  b​
N  na 
sljedeći način: 
b​  = 0 
1​
b​i+1​ = b​  + 1 ako je a​
i​  > a​
i​ , i > 1 
i­1​
b​i+1​ = b​  ­ 1 ako je a​
i​  < a​
i​ , i > 1 
i­1​
b​  = b​
i+1​  ako je a​
i​  = a​
i​ i­1​, i > 1 
 
Označimo s p​  i­tu parcijalnu sumu niza b. Lako je vidjeti da je i­ta nota koju će 
i​
Mirka odsvirati upravo p​  * K + a​
i​ . 
1​
 
Ako Mirka točno odsvira i­tu notu pjesme vrijedi p​  * K + a​
i​ = a​
1 ​ . Ako je p​
i​ = 0, onda 
i ​
točnost i­te note uopće ne ovisi o K, a inače će biti točno odsvirana ako je K 
jednako (a​ ­a​
i​ ) / p​
1​  (uočimo da kvocijent mora biti nenegativan cijeli broj).  
i​
 
Dakle, za svaku notu za koju je p​  različito od 0 postoji najviše jedan dobar kandidat 
i​
za K. Sve kandidate možemo ubaciti u niz, sortirati ga, naći koji se najviše puta 
pojavljuje te njega odabrati za optimum. 
 
Složenost rješenja je O(N lg N) zbog sortiranja. 
 
potrebno znanje: ​ kombinatorika 
kategorija: ​ ad­hoc, matematika 
 
Zadatak PAROVI  Autor: Mislav Balunović 
 
Označimo sa A​  familiju skupova koji imaju pregradu na mjestu k, a sa X označimo 
k​
familiju svih mogućih početnih skupova. 
n
Tada su rješenje svi skupovi iz  X  ∖
 ∪Ai    
i = 1
 
Formula uključivanja i isključivanja nam daje efikasan način za računanje veličine 
skupa rješenja. Vrijedi: 
 
n   k  
k
 ∪Ai |  = ∑(− 1)    ∙ |  ∩ Ai[j]|  
| X ∖
i = 1   j = 1  
Kako bismo izračunali kardinalitet potrebnog presjeka trebamo prebrojati koliko 
postoji uparivanja takvih da su pregrade postavljene na određenih k mjesta (za 
ostala mjesta nam nije bitno postoje li pregrade na njima). 
t​
Taj broj je jednak 2​  gdje je t ukupan broj parova koji ne “preskaču” niti jednu 
ogradu. 
N​
Vremenska složenost ovog rješenja je O(2​  * N). 
Za detalje implementacije pogledajte službeno rješenje. 
 
Napomena: Postoji i rješenje koje koristi dinamičko programiranje, a ostavljamo ga 
čitatelju za vježbu. 
 
 
potrebno znanje: ​ formula uključivanja i iskuljučivanja, matematika 
kategorija: ​ matematika 
 
 
 
Zadatak KRUMPIRKO  Autor: Dominik Gleich 
 
Rješenje koje donosi 30% bodova trivijalno je i implementira točno ono što zadatak 
traži: od svih odabira rasporeda vreća krumpira u dućane kojih ima O(2^n), 
odaberi onaj s najmanjim umnoškom prosječnih cijena kod kojeg je barem jedna 
polovica veličine ​
L​
. Složenost tog rješenja je O(2^n * n). Pokušajmo sada riješiti 
zadatak za sve bodove. Označimo li ukupnu cijenu krumpira u prvom dućanu s ​ c​1​ i 
ukupan broj krumpira s ​ w1​ ​, te analogno za drugi dučan s ​ c2​
​ i ​
w2​
​, umnožak 
prosjećnih cijena jednak je ​ c​*​c​/​
w ​/​
w ​
1​ 2​ 1​ 2. ​S obzirom da je suma cijena i suma broja 
krumpira konstantna možemo ovaj izraz zapisati i kao ​ c​ *(​
1​ c​
 ­ ​
c​)/(​
1​ w​ *​
1​ (​
w­w​ )). 
1​
Ukoliko fiksiramo neki ​w​ možemo primijetiti da je ovaj izraz minimalan kad je ​
1 ​ c​1 
također minimalan. Sada je naš zadatak za svaki ​ w1​
​ pronaći najmanji ​ c1 ​
​takav da je 
u prvom dućanu točno ​ L​ ili ​
N ­ L ​vreća krumpira. Najmanji takav ​ c​ tražimo 
1​
dinamičkim programiranjem, neka je ​ f​
(​
n, w, l) ​
najmanja cijena odabira točno ​ l 
vreća krumpira u prvih ​ n ​vreća krumpira tako da u odabranim vrećama imamo 
točno ​w​ krumpira. Relaciju za tu dinamiku ostavljamo na vježbu čitatelju, za ostale 
detalje pogledajte službeno rješenje. Ukupna složenost rješenja iznosi O(​ wn^2​ ). 
 
potrebno znanje: ​ dinamičko programiranje 
kategorija: ​ matematika 
 
 
 
 
 
 
 
Zadatak SAN  Autor: Marin Tomić 
 
Neka je tab[y] broj pojavljivanja broja y u tablici. Možemo ga (neefikasno) 
izračunati sljedećim algoritmom za sve y od 1 do N: 
 
za x od 1 do N: 
tab[x] = tab[x] + 1 
tab[x + rev(x)] = tab[x + rev(x)] + tab[x] 
 
10​
Ovaj algoritam je linearan, no N je do 10​  pa nije dovoljno efikasan. Ključno je 
uočiti da brojeva za koje je tab[y] > 1 ima vrlo malo. Označimo s cnt[y] broj 
različitih brojeva x takvih da je x + rev(x) = y. Uočimo da je cnt[y] > 0 ako i samo 
ako je tab[y] > 1. Označimo sa S niz brojeva koji se sastoji od svih brojeva za koje 
je cnt[y] > 0 sortiranih uzlazno. Vrijednosti tab[y] za te brojeve možemo izračunati 
sljedećim algoritmom: 
 
za sve x u S: 
tab[x] = tab[x] + cnt[x] 
tab[x + rev(x)] = tab[x + rev(x)] + tab[x] 
 
U ovom algoritmu imamo |S| iteracija petlje. Ključno je uočiti da brojeva u skupu S 
ima relativno malo (samo nekoliko milijuna) pa je gornji algoritam dovoljno 
efikasan da bi izračunali vrijednosti tab[y] za sve y za koje je to veće od 1. Za sve 
ostale y vrijedi tab[y] = 1 pa sada zapravo imamo izračunate vrijednosti tab[y] za 
sve y što nam omogućava da efikasno odgovaramo na upite (koristeći parcijalne 
sume niza tab). Uočimo da su indeksi u nizu tab vrlo veliki, no ne treba nam cijeli 
niz pa ćemo ga zapravo držati u mapi. 

Preostaje  izračunati  vrijednosti  cnt[y]  za  sve  brojeve.  Rekurzijom  ćemo  naći  sve 
brojeve  y  i  vrijednosti  cnt[y]  za  sve  y   za  koje  je  to  veće od 0.  Pogledajmo  što  se 
dogodi kada zbrojimo neki 6­znamenkasti broj s njim samim okrenutim naopako: 

 
a1 a2 a3 a4 a5 a6 
+ a6 a5 a4 a3 a2 a1 
­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ 

  c0 b1+c1 b2+c2 b3+c3 b3+c4 b2+c5 b1 

Ovdje  su c0, …, c5 0 ili 1 i označavaju znamenke prijenosa, a b1 je (a1+a6) modulo 
10, b2 je (a2+a5) modulo 10 i b3 je (a3+a4) modulo 10. 
Vrijednosti  cnt[y]  bi  mogli  odrediti  tako  da  fiksiramo  znamenke  a1,  …,  a6  na  sve 
moguće  načine,  no  za  to  postoji  mnogo  kombinacija.  Drugi  pristup  bi  bio  da 
odredimo  b1,  b2  i b3,  te  c0, …, c5 na sve  moguće načine (time je zbroj jedinstveno 
određen)  i  izračunamo  koliko  različitih  odabira  a1,  …,  a6  daje  točno te b1, b2 i b3 i 
c0,  …,  c5.  Kako  to  napraviti?  Koristit  ćemo  rekurzivnu  funkciju  gen   koja  ima  4 
parametara čije je značenje opisano u tablici: 

 
pos  znači da trenutno određujemo b​
pos 

c1  znači da c​  mora biti jednak c​


pos­1​ 1 

c2  znači da je c​  jednak c2 


6­pos+1​

num  trenutno određeni dio sume a1...a6 + a6...a1 

Pseudo kod za funkciju gen: 

gen(pos, c1, c2, num): 

    ako je pos = 4:  
(odredili smo cijelu sumu i broj načina da ju dobijemo) 
ako je c1 != c2 izađi iz funkcije 
(c1 i c2 moraju biti jednaki jer oba predstavljaju c3) 
u mapi povećaj cnt[num] za 1 i izađi iz funkcije 

    za parove znamenki (x1, x2): 
(x1 i x2 određuju b​
pos,
​ određujemo znamenke pos i 6­pos+1 u num) 
ako je c1 = 1 a x1+x2 < 10 preskoči 
ako je c1 = 0 a x1+x2 >= 10 preskoči 
  bb = (x1 + x2) % 10 
 

nnum = num 
postavi znamenku 6­pos+1 u nnum na bb + c2 
postavi znamenku pos u nnum na bb + 1 i pozovi 
  gen(pos+1, 1, x1+x2 >= 10, nnum) 
  (c1 = 1 označava da tražimo znamenku prijenosa) 

postavi znamenku pos u nnum na bb i pozovi 
  gen(pos+1, 0, x1+x2 >= 10, nnum) 
  (c1 = 0 označava da zabranjujemo prijenos) 
Gornji  pristup  može  se  poopćiti  za  proizvoljan  broj  znamenaka.  Gornja  rekurzija za 
L/2
neku  duljinu  broja  L  radi  otprilike  81​   što  je  presporo  da  bi  osvojilo  sve  bodove. 
Potrebno  je  uočiti  da  ne  moramo  iterirati  po  svim  parovima  znamenaka,  već  je 
dovoljno  iterirati  po   svim  mogućim  zbrojevima  i  za  svaki  zbroj  znati  na  koliko 
L/2
načina  ga  možemo  ostvariti.  Tada  radimo  otprilike  19​   operacija  što  je  dovoljno 
brzo  za  sve   bodove.  Detalje  ostavljamo   čitatelju,  no  mogu  se  naći  i  u  izvornom 
kodu. 

 
potrebno znanje:​ rekurzija, mapa 
kategorija: ​
dinamika, matematika 

You might also like