Documente Academic
Documente Profesional
Documente Cultură
date la olimpiade
în
2020
2019 2018 2017 2016 2015
2014 2013 2012 2011 2010
la clasa a 7-a
9 decembrie 2020
Dedicaµie
1
to myself ...
in a time when ...
I will not be able ...
2
to be.
3
When I Die Nobody Will Remember Me
1
I Dedicate This Book to Myself By Carol Lynne
2
To be, or not to be ..., Hamlet, Act III, Scene I, William Shakespeare, 1564-1616
3
https://www.youtube.com/watch?v=eMtcDkSh7fU
ii
Prefaµ
Stilul acestor c rµi este ... ca ³i cum a³ vorbi cu nepoµii mei (³i chiar cu mine însumi!) ... încercând
împreun s g sim o rezolvare cât mai bun pentru o problem dat la olimpiad .
Ideea, de a scrie aceste culegeri de probleme date la olimpiadele de informatic , a ap rut acum
câµiva ani când am întrebat un student (care nu reu³ea s rezolve ni³te probleme foarte simple):
Ce te faci dac un elev, care ³tie c e³ti student ³i c studiezi ³i informatic , te roag , din când în
când, s -l ajuµi s rezolve câte o problem de informatic dat la gimnaziu la olimpiad , sau pur
³i simplu ca tem de cas , ³i tu, aproape de ecare dat , nu îl poµi ajuta? Eu cred c nu este prea
bine ³i poate c ... te faci ... de râs! Pe vremea mea (!), când eram elev de gimnaziu, un student
era ca un fel de ... zeu! Cu trecerea anilor am înµeles c nu este chiar a³a! i înc ceva: nu am
reu³it s înµeleg de ce, atunci când cineva nu poate s rezolve corect o problem de informatic
de clasa a 6-a, dat la olimpiada de informatic sau ca tem de cas , folose³te aceast scuz : eu
nu am f cut informatic în liceu! ³i acest cineva este zeul sau zeiµa despre care vorbeam!.
4
Sunt convins c este important s studiem cu atenµie cât mai multe probleme rezolvate! Cred
cred c sunt utile ³i primele versiuni în care sunt prezentate chiar ³i numai enunµurile ³i indicaµiile
"ociale" de rezolvare. Acestea se g sesc în multe locuri; aici încerc s le pun pe toate la un loc !
Cred c , de cele mai multe ori, este foarte greu s gândim "simplu" ³i s nu "ne complic m"
atunci când caut m o rezolvare pentru o problem dat la olimpiad . Acesta este motivul pentru
care vom analiza cu foarte mare atenµie atât exemplele date în enunµurile problemelor cât ³i
"restricµiile" care apar acolo (ele sigur "ascund" ceva interesant din punct de vedere al algoritmului
7
de rezolvare!) .
Am început câteva c rµi (pentru clasele de liceu) cu mai mulµi ani în urm , pentru perioada
2000-2007 ([29] - [33]), cu anii în ordine cresc toare!). A urmat o pauz de câµiva ani (destul de
mulµi!). Am observat c acele cursuri s-au împr ³tiat un pic pe net ([48] - [56])! Încerc acum
s ajung acolo unde am r mas ... plecând mereu din prezent ... pân când nu va mai posibil ...
a³a c , de aceast dat , anii sunt în ordine ... descresc toare! :-)
Codurile surs sunt cele ociale (publicate pe site-urile olimpiadelor) sau publicate pe alte
site-uri (dac mi s-a p rut c sunt utile ³i se poate înv µa câte ceva din ele).
Pentru liceu perioada acoperit este de azi (pân când va exista acest azi pentru mine!)
pân în anul 2000 (aveam deja perioada 2000-2007!).
Pentru gimnaziu perioada acoperit este de azi pân în anul 2010 (nu am prea mult timp
disponibil ³i, oricum, calculatoarele folosite la olimpiade înainte de 2010 erau ceva mai 'slabe' ³i
8
... restricµiile de memorie, din enunµurile problemelor, par 'ciudate' acum!). i indc a venit
vorba despre calculatoare mai slabe sau mai puternice: laptopul meu¯t u este puµin mai slab
decât cel mai puternic calculator din lume în 1985 dar ³i ... un pic mai puternic decât cel mai
9
puternic calculator din lume în 1983. (armaµia este valabil acum, în 2020).
4
Se poate observa din Coduri surs c orice problem are numeroase soluµii, atât ca algoritmi de rezolvare
cât ³i ca stil de programare! Studiind aceste coduri ... avem ce înv µa ... de³i uneori pare c 'se trage cu tunul' ...
5
IOI2019 ³i IOI2020 au a permis utilizarea limbajelor de programare C++ ³i Java
6
IOI2015 a permis utilizarea limbajelor de programare C++, Java, Pascal, Python ³i Rubi (...)
7
8
Vezi cele 5 secunde pentru Timp maxim de executare/test din problema avârcolaci - ONI2014 clasa a 11-a
Când eram eu elev/student un calculator obi³nuit executa în jur de 1.000.000 de operaµii pe secund , acum
execut 1.000.000.000 de operaµii pe secund , iar mai târziu ... cine stie ce va mai ?!
9
https://en.wikipedia.org/wiki/List_of_fastest_computers
iii
În perioada 2017-2020 cele mai puternice calculatoare din lume au fost: în noiembrie 2017 în
China, în noiembrie 2019 în SUA ³i ... în iunie 2020 în Japonia (Fugaku: 415 petaops, adic
15 10
415 10 operaµii pe secund , adic ... 415 milioane de ... miliarde de ... operaµii pe secund ).
O mic observaµie: în 2017 a fost prima ediµie a olimpiadei EJOI11 în Bulgaria ³i ... tot în
12
Bulgaria a fost ³i prima ediµie a olimpiadei IOI în 1989.
Dar ... prima ediµie a olimpiadei IMO (International Mathematical Olympiad) a fost în
13
România în 1959. Tot în România s-au µinut ediµiile din anii 1960, 1969, 1978, 1999 ³i 2018.
Revenind la ... culegerile noastre ... mai departe, probabil, va urma completarea unor
informaµii în Rezolv ri detaliate ... pentru unele probleme numai (tot din cauza lipsei timpului
necesar pentru toate!). Prioritate vor avea problemele de gimnaziu (nu pentru c sunt mai 'u³oare'
ci pentru c ... elevii de liceu se descurc ³i singuri!). Totu³i, vor prezentate ³i Rezolv ri
detaliate ale problemelor de liceu (pe care le-am considerat în mod subiectiv!) utile.
Îmi aduc aminte c exista o interesant vorb de duh printre programatorii din generaµia mea:
nu se trage cu tunul într-o musc . Sensul este: nu se scrie un cod complicat dac se poate
scrie un cod simplu ³i clar! Asta încerc eu în Rezolv ri detaliate .
Vom încerca, împreun , ³i câteva probleme de ... IOI ... dar asta este o treab ... nu prea
u³oar ! Cred totu³i c este mai bine s prezint numai enunµuri ale problemelor date la IOI în
ultimii câµiva ani! (asta a³a, ca s vedem cum sunt problemele la acest nivel!). Cei care ajung
acolo sau vor s ajung acolo (la IOI) nu au nevoie de ajutorul meu! Se descurc singuri! La
Indicaµii de rezolvare voi prezenta numai ... numele algoritmilor clasici folosiµi în rezolvare.
O alt mic observaµie: ce am strâns ³i am scris în aceste c rµi se adreseaz celor interesaµi de
aceste teme! Nu cârcota³ilor! Sunt evidente sursele de pe net (³i locurile în care au fost folosite).
Nu sunt necesare preciz ri suplimentare!
i un ultim gând: criticile ³i sfaturile sunt utile dac au valoare! Dac sunt numai a³a ...
cum critic lumea la un meci de fotbal ... sau cum, pe banc în parc, î³i d cu p rerea despre
rezolvarea problemelor economice ale µ rii ... atunci ... !!!
https://stats.ioinformatics.org/halloffame/
https://stats.ioinformatics.org/tasks/
http://stats.ioinformatics.org/results/ROU
http://adrianrabaea.scienceontheweb.net/
https://www.scribd.com/user/243528817/Adrian-Rabaea
https://drive.google.com/drive/folders/1hC5PZuslCdS95sl37SW46H-qy59GRDGZ
http://www.ise.ro/wp-content/uploads/2017/01/Informatica-si-TIC.pdf
http://programe.ise.ro/Portals/1/Curriculum/Progr_Lic/TH/Informatica_teoretic_vocatio
nal_intensiv_clasa%20a%20IX-a.pdf
http://programe.ise.ro/Portals/1/Curriculum/Progr_Lic/TH/Informatica_teoretic_vocatio
nal_intensiv_clasa%20a%20X_a.pdf
http://programe.ise.ro/Portals/1/Curriculum/Progr_Lic/TH/Informatica_teoretic_vocatio
nal_intensiv_clasa%20a%20XI-a.pdf
10
https://www.top500.org/lists/top500/
11
https://ejoi.org/about/
12
https://stats.ioinformatics.org/olympiads/
13
https://en.wikipedia.org/wiki/International_Mathematical_Olympiad
14
https://www.etsy.com/listing/604809336/john-wayne-quotes-i-am-only-responsible
"Acknowledgements"
15
"I want to thank God most of all because without God I wouldn't be able to do any of this."
Adrian R.
15
I.d.k.: "I don't know who the author is."
v
Despre autor16
nume: R bâea Aurel-Adrian, 18.03.1953 - ...
adresa: Str. Valea Ghinzii nr. 21 B, Bistriµa, România
telefon: +40 728 18 03 53 +40 363 10 25 10
email: adrian1803@gmail.com
https://scholar.google.com/citations?user=-sSE_1wAAAAJ&hl=en
https://www.scopus.com/authid/detail.uri?origin=resultslist&authorId=56122389200&zone=
http://www.facebook.com/adrian.rabaea
16
https://stiinte.utcluj.ro/files/cv/CV%20Rabaea_Adrian.pdf
17
http://opac.biblioteca.ase.ro/opac/bibliographic_view/149021
18
http://www.ionivan.ro/2015-PERSONALITATI/Dodescu.htm
19
https://sites.google.com/site/ciprianatudor/Home/professor-constantin-tudor
20
https://ro.wikipedia.org/wiki/Ion_V%C4%83duva
vi
Cuprins
Prefaµ iii
Cuprins vii
Lista gurilor xiii
Lista tabelelor xiv
Lista programelor xv
2 OJI 2019 22
2.1 poarta - OJI 2019 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.1.2 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.1.3 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.2 valutar - OJI 2019 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.2.2 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.2.3 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3 OJI 2018 36
3.1 puzzle - OJI 2018 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.1.2 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.1.3 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.2 tbile - OJI 2018 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.2.2 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.2.3 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4 OJI 2017 44
4.1 Cursuri - OJI 2017 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
4.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.1.2 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.1.3 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.2 joc - OJI 2017 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
4.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
vii
4.2.2 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
4.2.3 Codul surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
5 OJI 2016 64
5.1 axyz - OJI 2016 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
5.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
5.1.2 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
5.1.3 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
5.2 galerie - OJI 2016 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
5.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
5.2.2 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
5.2.3 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
6 OJI 2015 74
6.1 ech - OJI 2015 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
6.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
6.1.2 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
6.1.3 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
6.2 lasere - OJI 2015 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
6.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
6.2.2 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
6.2.3 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
7 OJI 2014 92
7.1 p trat - OJI 2014 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
7.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
7.1.2 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
7.1.3 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
7.2 schi - OJI 2014 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
7.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
7.2.2 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
7.2.3 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
Glosar 278
Bibliograe 279
Lista autorilor 282
Lista gurilor
3.1 Puzzle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.2 tbile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.1 joc1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
4.2 joc2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
4.3 Puzzle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
5.1 galerie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
7.1 patrat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
xiii
Lista tabelelor
17.1 cript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
xiv
Lista programelor
1.1.1 foto_1_c.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1.2 foto_2_c.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1.3 foto_1_cpp.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.1.4 foto_2_cpp.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.1.5 foto_AB.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.1.6 foto_AF.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.1.7 foto_cm_rec.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.1.8 fotoCS.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.1.9 fotoFB.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.1.10 fotoKB.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.1.11 fotoMM.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.2.1 wind.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.2.2 wind.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.2.3 windCM.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.2.4 windCS.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.1.1 poarta1_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.1.2 poarta2_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.1.3 poarta3_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.1.4 poarta4_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.2.1 valutar_cpp_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.2.2 valutar1_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.2.3 valutar2_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.1.1 p2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.1.2 p4.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
3.2.1 t1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.2.2 t2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4.1.1 cursuri_Dan_100p.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.1.2 cursuri_NlogN.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.1.3 cursuri_NxN.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
4.1.4 cursuri_raluca_100p.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
4.1.5 cursuri_rm.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
4.2.1 joc.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
4.2.2 joc_dl.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
4.2.3 joc_pracsiu.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
4.2.4 joc_rm.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
5.1.1 axyz.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
5.2.1 galerie0.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
5.2.2 galerie1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
6.1.1 ech_add11.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
6.1.2 ech_lucia_miron.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
6.1.3 ech_Ovidiu_Dumitrescu.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
6.1.4 ech_raluca_costinescu.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
6.1.5 ech_vasile_pit_rada.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
6.2.1 lasere_adrian_pintea.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
6.2.2 lasere_emanuela_cerchez.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
6.2.3 lasere_lucia_miron.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
6.2.4 lasere_nicu_vlad.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
6.2.5 lasere_raluca_costinescu.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
6.2.6 lasere_vasile_pit_rada.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
xv
7.1.1 patratdl.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
7.1.2 patratdt.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
7.1.3 patratMN.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
7.1.4 patratsj.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
7.1.5 patratvg.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
7.2.1 schi.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
7.2.2 schidL.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
7.2.3 schidt.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
7.2.4 schiNQ.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
7.2.5 schiNQcb.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
7.2.6 schiSortQ.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
8.1.1 compar_dm.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
8.1.2 compara_en.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
8.2.1 unic_em.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
8.2.2 unic_eugen_1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
9.1.1 arme_Adrian.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
9.1.2 arme_ema.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
9.1.3 arme_Ovidiu.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
9.2.1 tri_adrian_.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
9.2.2 tri_marinel_.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
9.2.3 triunghi_Eugen00.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
9.2.4 triunghi_Eugen11.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
9.2.5 triunghi_Eugen22.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
9.2.6 triunghi_O_Marcu_matrice.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
9.2.7 triunghi_O_Marcuo.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
10.1.1 RCGRUPE.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
10.2.1 litere.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
11.1.1 7_pr1_s.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
11.2.1 7_pr2_s.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
13.1.1 Domino_1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
13.1.2 domino_2_assert.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
13.1.3 domino_3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
13.2.1 tuburi_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
13.2.2 tuburiOcial.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
13.3.1 venus_1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
13.3.2 venus_2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
15.1.1 carte.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
15.2.1 ghinde.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
15.3.1 submat_cpp.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
16.1.1 ABbirouri.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
16.1.2 CSbirouri.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
16.1.3 FUbirouri.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
16.2.1 ABcristale.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
16.2.2 CIcristale.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
16.2.3 CMcristale.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
16.2.4 CScristale.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
16.3.1 ABparchet.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
16.3.2 CSparchet.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
16.3.3 MSparchetBiti.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
16.3.4 MSparchetVector.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
17.1.1 cript_emcerchez_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
17.1.2 cript_LuciaMiron.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
17.1.3 cript_odumitrascu.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
17.1.4 cript_rcostineanu_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
17.2.1 scadere_100_emcerchez.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
17.2.2 scadere_100_odumitrascu.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
17.3.1 tv_odumitrascu_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
18.1.1 codat_mn.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
18.1.2 codat_patratic.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
18.1.3 codat_stack.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
18.2.1 nod.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
18.2.2 nod_dl_pct1_2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
18.2.3 nod_dt_ok.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
18.3.1 placa.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
18.3.2 placa1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
18.3.3 placa2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236
18.3.4 placa3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
18.3.5 placa4.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
18.3.6 placa5.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
18.3.7 placa6.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
18.3.8 placa8.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
18.3.9 placa10.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
19.1.1 secvp.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
20.1.1 bile.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
20.2.1 proiecte1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
20.2.2 proiecte2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
20.3.1 zigzag.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
22.1.1 CHAR.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
22.2.1 MARATON.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
22.2.2 MARAton2.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
22.3.1 Roboti.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
Partea I
1
Capitolul 1
OJI 2020
1.1 foto
Problema 1 - foto 100 de puncte
O fotograe alb-negru a surprins imaginea fulgerelor pe cerul întunecat în timpul unei furtuni
electrice. M rit , fotograa arat ca un caroiaj format din mici p trate identice, albe sau negre,
dispuse al turat pe N rânduri ³i M coloane, câte M pe ecare rând.
P tratele albe formeaz fulgerele din fotograe, iar p tratele negre reprezint cerul.
În fotograe, nu exist dou p trate albe dispuse al turat pe acela³i rând. Un fulger este
format din p trate albe situate pe rânduri consecutive care respect urm toarele condiµii:
a) p tratele albe situate pe dou rânduri consecutive au un vârf comun sau o latur comun ;
În fotograe, fulgerele sunt distincte, ele neavând p trate albe cu laturi sau vârfuri comune.
În lµimea unui fulger este dat de num rul de p trate albe ale acelui fulger.
Cerinµe
Scrieµi un program care cite³te numerele N ³i M, cele N M elemente ale tabloului T care
codic fotograa, ³i rezolv urm toarele cerinµe:
Date de intrare
Fi³ierul de intrare foto.in conµine pe prima linie un num r natural C reprezentând cerinµa
care trebuie rezolvat (1 sau 2).
Pe a doua linie se a cele dou numere naturale N ³i M, separate printr-un spaµiu, cu
semnicaµia din enunµ.
Pe ecare dintre urm toarele N linii se a câte M valori 0 sau 1, separate prin câte un spaµiu,
reprezentând elementele tabloului care codic fotograa, în ordinea parcurgerii lor pe rânduri,
de sus în jos, ³i de la stânga la dreapta în cadrul unui rând.
Date de ie³ire
2
CAPITOLUL 1. OJI 2020 3
a dac C 2, cele dou numere F ³i H, în aceast ordine, separate printr-un singur spaµiu,
reprezentând r spunsul la cerinµa 2.
Restricµii ³i preciz ri
a N num r natural, 4&N & 100
a M num r natural, 4&M & 100
a Pentru rezolvarea cerinµei 1 se acord 20 de puncte, pentru rezolvarea cerinµei 2 se acord
70 de puncte (30 de puncte pentru F ³i 40 de puncte pentru H ).
Exemple:
O soluµie posibil , la nivelul programei clasei a VII-a, se poate poate obµine astfel:
Cerinµa 1.
Iniµializam variabila P 0
Se parcurge ecare linie a tabloului (matrice).
La întâlnirea primei valori de 0, începem s contoriz m 0-rile succesive din linia curent (adic
determin m lungimea maxim a unei secvenµe de valori 0 succesive în linie). Contorizarea se
încheie la întâlnirea primei valori 1 sau la încheierea parcurgerii liniei.
Actualiz m valoarea lui P cu maximul dintre P ³i valoarea contorului.
Apoi reiniµializ m contorul cu 0 ³i c ut m urm torul 0 în linie. Dac a fost parcurs toat
linia, se trece la linia urm toare.
Cerinµa 2.
Folosim variabila F pentru a num ra fulgerele din fotograe. Iniµial F 0.
Folosim variabila H pentru a memora în lµimea maxim a unui fulger. Iniµial H 0.
I. Solutie complexitate O N N M
Pentru a evita ie³irea din matrice, e recomandat s bordaµi cu 0 matricea, adic s adaugaµi
linia 0, linia N 1, coloana 0 ³i coloana M 1, toate având doar valori egale cu 0.
CAPITOLUL 1. OJI 2020 4
Parcurgem matricea, de la linia 1 c tre linia N, iar ecare linie este parcurs de la prima
coloan c tre ultima.
Prima valoare 1 întâlnit , reprezint primul p trat alb dintr-un fulger.
Dac T lincol 1 atunci vom proceda astfel:
a) Num r m noul fulger: F=F+1; Iniµializam contorul h care va num r patratele albe ce
formeaz un fulger: h=0. El va în lµimea fulgerului. Fie I=lin ³i J=col
b2) C ut m în linia I+1 urm torul p trat alb al fulgerului, în coloanele J-1 sau J+1.
Dac T[I+1][J-1]=1, atunci p tratul alb este în coloana J-1 ³i vom actualiza I=I+1
³i J=J-1. Mergi la b1)
Altfel dac T[I+1][J-1]=1 atunci p tratul alb este în coloana J+1 ³i vom actualiza
I=I+1³i J=J+1. Mergi la b1)
Altfel dac T[I+1][J]=1atunci p tratul alb este în coloana J+1 ³i vom actualiza
I=I+1. Mergi la b1)
OBS: cel mult una dintre valorile T[I+1][J-1], T[I+1][J] ³i T[I+1][J+1] este egal
cu 1
a vericam dac vreunul cei trei vecini T[I-1][J-1], T[I-1][J], T[I-1][J-1], situati in linia I-1 este
nenul. Doar unul poate nenul.
a dac toµi trei sunt nuli, atunci T[I][J] este primul patrat alb dintr-un fulger nou si num r m
acest fulger (F++);
a dac unul dintre ei este nenul, e T[LIN][COL] acest vecin nenul. Atunci T[I][J]
³iT[LIN][COL] fac parte din acela³i fulger ³i vom memora în T[i][j] lungimea actual a
fulgerului. : T[I][J]=T[LIN][COL]+1;
1 #include <stdio.h>
2
3 int a[102][102];
4 FILE *f,*g;
5
6 int main()
7 {
8 int C,N,M;
9
10 f=fopen("foto.in","r");
11 g=fopen("foto.out","w");
12
13 fscanf(f,"%d%d%d",&C,&N,&M);
14
CAPITOLUL 1. OJI 2020 5
15 if(C==1)
16 {
17 int x,P=0,i,j,p=0;
18 for(i=1;i<=N;i++)
19 { p=0;
20 for(j=1;j<=M;j++)
21 { fscanf(f,"%d",&x);
22 if(x==0)p++;
23 else
24 {if(P<p)P=p;
25 p=0;}
26 }
27 if(P<p)P=p;
28 }
29 fprintf(g,"%d\n",P);
30 }
31 else
32 {
33 int H=0,F=0,i,j,h,r,c;
34
35 for(r=1;r<=N;r++)
36 for(c=1;c<=M;c++)
37 fscanf(f,"%d",&a[r][c]);
38
39 for(r=1; r<=N; r++)
40 for(c=1; c<=M; c++)
41 if(a[r][c]==1)
42 { F++;
43 i=r;
44 j=c;
45 h=0;
46
47 while(a[i][j]==1)
48 { h++;
49 a[i][j]=0;
50 if(a[i+1][j]==1)i++;
51 else
52 if(a[i+1][j-1]==1){i++;j--;}
53 else
54 if(a[i+1][j+1]==1){i++; j++;}
55 }
56
57 if(H<h) H=h;
58 }
59
60 fprintf(g,"%d %d\n",F,H);
61 }
62
63 return 0;
64 }
1 #include <stdio.h>
2
3 int T[102][102];
4 FILE *f,*g;
5
6 int main()
7 {
8 int C,N,M;
9
10 f=fopen("foto.in","r");
11 g=fopen("foto.out","w");
12
13 fscanf(f,"%d%d%d",&C,&N,&M);
14
15 if(C==1)
16 {
17 int x,P=0,i,j,p=0;
18 for(i=1;i<=N;i++)
19 { p=0;
20 for(j=1;j<=M;j++)
21 { fscanf(f,"%d",&x);
22 if(x==0)p++;
CAPITOLUL 1. OJI 2020 6
23 else
24 {if(P<p)P=p;
25 p=0;}
26 }
27
28 if(P<p)P=p;
29 }
30
31 fprintf(g,"%d\n",P);
32 }
33 else
34 {
35 int H=0,F=0,i,j,hant;
36
37 for(i=1;i<=N;i++)
38 for(j=1;j<=M;j++)
39 { fscanf(f,"%d",&T[i][j]);
40 if(T[i][j]==1)
41 { hant=T[i-1][j-1]+
42 T[i-1][j]+
43 T[i-1][j+1];///lg fulger pana in aceasta pozitie
44 /// doar una dintre valorile
45 /// T[i-1][j-1],T[i-1][j],T[i-1][j+1]este nenula
46 if (hant==0) F++; ///primul patrat alb din fulger
47 T[i][j]=1+hant;
48 if(H<T[i][j])H=T[i][j];
49 }
50 }
51
52 fprintf(g,"%d %d\n",F,H);
53 }
54
55 return 0;
56 }
1 #include <fstream>
2 #include <iostream>
3
4 using namespace std;
5
6 ifstream f("foto.in");
7 ofstream g("foto.out");
8
9 int T[102][102];
10
11 int main()
12 {
13 int C,N,M;
14 f>>C>>N>>M;
15
16 if(C==1)
17 {
18 int x,P=0,i,j,p=0;
19 for(i=1;i<=N;i++)
20 { p=0;
21 for(j=1;j<=M;j++)
22 { f>>x;
23 if(x==0)p++;
24 else
25 {P=max(p,P); p=0;}
26 }
27
28 P=max(P,p);
29 }
30
31 g<<P<<endl;
32 }
33 else
34 {
35 int H=0,F=0,i,j,h,r,c;
36
37 for(r=1;r<=N;r++)
38 for(c=1;c<=M;c++)
CAPITOLUL 1. OJI 2020 7
39 f>>T[r][c];
40
41 for(r=1; r<=N; r++)
42 for(c=1; c<=M; c++)
43 if(T[r][c]==1)
44 { F++;
45 i=r;
46 j=c;
47 h=0;
48 while(T[i][j]==1)
49 { h++;
50 T[i][j]=0;
51 if(T[i+1][j]==1)i++;
52 else
53 if(T[i+1][j-1]==1){i++;j--;}
54 else
55 if(T[i+1][j+1]==1){i++; j++;}
56 }
57
58 H=max(h,H);
59 }
60
61 g<<F<<" "<<H<<endl;
62 }
63
64 return 0;
65 }
1 #include <fstream>
2 #include <iostream>
3
4 using namespace std;
5
6 ifstream f("foto.in");
7 ofstream g("foto.out");
8
9 int T[102][102];
10
11 int main()
12 {
13 int C,N,M;
14 f>>C>>N>>M;
15
16 if(C==1)
17 {
18 int x,P=0,i,j,p=0;
19 for(i=1;i<=N;i++)
20 { p=0;
21 for(j=1;j<=M;j++)
22 { f>>x;
23 if(x==0)p++;
24 else
25 {P=max(p,P); p=0;}
26 }
27
28 P=max(P,p);
29 }
30
31 g<<P<<endl;
32 }
33 else
34 {
35 int H=0,F=0,i,j,h,r,c;
36
37 for(r=1;r<=N;r++)
38 for(c=1;c<=M;c++)
39 f>>T[r][c];
40
41 for(r=1; r<=N; r++)
42 for(c=1; c<=M; c++)
43 if(T[r][c]==1)
44 { F++;
45 i=r;
CAPITOLUL 1. OJI 2020 8
46 j=c;
47 h=0;
48 while(T[i][j]==1)
49 { h++;
50 T[i][j]=0;
51 if(T[i+1][j]==1)i++;
52 else
53 if(T[i+1][j-1]==1){i++;j--;}
54 else
55 if(T[i+1][j+1]==1){i++; j++;}
56 }
57
58 H=max(h,H);
59 }
60
61 g<<F<<" "<<H<<endl;
62 }
63
64 return 0;
65 }
1 #include <fstream>
2
3 using namespace std;
4
5 int a[103][103];
6
7 int main()
8 {
9 int i,j,nr=0,nrmax=0,c, hmax=0,nrfulgere=0,n,m;
10
11 ifstream f("foto.in");
12 ofstream g("foto.out");
13
14 f>>c>>n>>m;
15 for(i=1; i<=n; i++)
16 {
17 nr=0;
18 for(j=1; j<=m; j++)
19 {
20 f>>a[i][j];
21 if(a[i][j]==0)
22 {
23 nr++;
24 if(nr>nrmax)
25 nrmax=nr;
26 }
27 else
28 {
29 nr=0;
30 if(a[i-1][j]!=0)
31 a[i][j]=a[i-1][j]+1;
32 else if(a[i-1][j-1]!=0)
33 a[i][j]=a[i-1][j-1]+1;
34 else if(a[i-1][j+1]!=0)
35 a[i][j]=a[i-1][j+1]+1;
36 if(hmax<a[i][j])
37 hmax=a[i][j];
38 if (a[i][j]==1)nrfulgere++;
39 }
40 }
41 }
42
43 if(c==1)
44 g<<nrmax;
45 else
46 g<<nrfulgere<<" "<<hmax;
47
48 return 0;
49 }
1 #include <iostream>
2 #include <fstream>
3
4 using namespace std;
5
6 ifstream fin("foto.in");
7 ofstream fout("foto.out");
8
9 int a[105][105],i,j,n,m,c,k,mx,kmax,fmax,nr,kf;
10 int dl[]={-1,-1,-1,0,1,1,1,0};
11 int dc[]={-1,0,1,1,1,0,-1,-1};
12
13 void lee(int a[][105],int n,int m,int l, int c, int &nr)
14 {
15 int i,ln,cn;
16 a[l][c]=0;nr++;
17 for(i=0;i<=7;i++)
18 {
19 ln=l+dl[i];
20 cn=c+dc[i];
21 if(a[ln][cn]==1)
22 lee(a,n,m,ln,cn,nr);
23 }
24 }
25
26 int main()
27 {
28 fin>>c;
29 fin>>n>>m;
30 mx=0;
31 kmax=0;
32 for(i=1; i<=n; i++)
33 {
34 k=0;
35 for(j=1; j<=m; j++)
36 {
37 fin>>a[i][j];
38 if(a[i][j]==0)k++;
39 else
40 {if(k>kmax)
41 kmax=k;
42 k=0;}
43 }
44 if(k>kmax)
45 kmax=k;
46 }
47
48 if(c==1)
49 fout<<kmax;
50 else
51 {
52 for(i=1;i<=n;i++)
53 {
54 for(j=1;j<=m;j++)
55 if(a[i][j]==1)
56 {
57 nr=0;kf++;
58 lee(a,n,m,i,j,nr);
59 if(nr>fmax)
60 fmax=nr;
61 }
62 }
63
64 fout<<kf<<’ ’<<fmax;
65 }
66
67 return 0;
68 }
1 #include <fstream>
2 #include <iostream>
3
CAPITOLUL 1. OJI 2020 10
1 #include <fstream>
2
3 using namespace std;
4
5 ifstream fin("foto.in");
6 ofstream fout("foto.out");
7
8 int a[105][105],n,m,c,i,j;
9
10 int fulger(int i, int j)
CAPITOLUL 1. OJI 2020 11
11 { int k=i;
12 for(;i<n;i++)
13 { a[i][j]=2;
14 if(a[i+1][j]==1) continue;
15 if(a[i+1][j-1]==1) j--;
16 else if(a[i+1][j+1]==1) j++;
17 else break;
18 }
19
20 if(i==n)a[i][j]=2;
21 return i-k+1;
22 }
23
24 void c1()
25 {int zmax=0, z=0, i, j;
26 for(i=1;i<=n;i++)
27 { z=0;
28 for(j=1;j<=m;j++) if(a[i][j]==0)z++;
29 else {zmax=max(zmax,z);z=0;}
30 zmax=max(zmax,z);
31 }
32 fout<<zmax<<’\n’;
33 }
34
35 void c2()
36 { int i,j, h, hmax=0, f=0;
37 for(i=1;i<=n;i++)
38 for(j=1;j<=m;j++)
39 if(a[i][j]==1){f++; h=fulger(i,j);
40 hmax=max(hmax,h);
41 }
42 fout<<f<<’ ’<<hmax<<’\n’;
43 }
44
45 int main()
46 {fin>>c>>n>>m;
47 for(i=1;i<=n;i++)
48 for(j=1;j<=m;j++) fin>>a[i][j];
49
50 if(c==1) c1();
51 else c2();
52 fin.close();
53 fout.close();
54 return 0;
55 }
1 #include <iostream>
2 #include <fstream>
3
4 using namespace std;
5
6 ifstream f("foto.in");
7 ofstream g("foto.out");
8
9 int i,j,n,m,a[101][101],k,maxim,C,fulgere;
10
11 int main()
12 {
13 f>>C;
14 if(C==1)
15 {
16 f>>n>>m;
17 for(i=1; i<=n; i++)
18 {
19 k=0;
20 for(j=1; j<=m; j++)
21 {
22 f>>a[i][j];
23 if(a[i][j]==0)
24 k++;
25 else
26 {
27 if(k>maxim)
CAPITOLUL 1. OJI 2020 12
28 maxim=k;
29 k=0;
30 }
31 }
32 if(k>maxim) maxim=k;
33 }
34 g<<maxim;
35 }
36 else
37 {
38 f>>n>>m;
39 for(i=1; i<=n; i++)
40 {
41 for(j=1; j<=m; j++)
42 {
43 f>>a[i][j];
44 if(a[i][j])
45 {
46 if(a[i-1][j-1]==0 and a[i-1][j]==0 and a[i-1][j+1]==0)
47 fulgere++;
48 if(a[i-1][j-1])
49 a[i][j]=a[i-1][j-1]+1;
50
51 if(a[i-1][j])
52 a[i][j]=a[i-1][j]+1;
53
54 if(a[i-1][j+1])
55 a[i][j]=a[i-1][j+1]+1;
56 if(a[i][j]>maxim)
57 maxim=a[i][j];
58 }
59
60 }
61 }
62 g<<fulgere<<" "<<maxim;
63 }
64
65 return 0;
66 }
1 #include <fstream>
2 #include <cmath>
3 #include <limits.h>
4
5 #define Ni 105
6 #define Mi 105
7
8 using namespace std;
9
10 int main()
11 {
12 ifstream f("foto.in");
13 ofstream g("foto.out");
14
15 short c;
16 f>>c;
17
18 short N,M,i,j, T[Ni][Mi];
19 f>>N;
20
21 f>>M;
22
23 for(i=1; i<=N; i++)
24 for(j=1; j<=M; j++)
25 f>>T[i][j];
26
27 if(c==1)
28 {
29 short maxi=0,kez;
30 for(i=1; i<=N; i++)
31 {
32 kez=0;
33 for(j=1; j<=M; j++)
CAPITOLUL 1. OJI 2020 13
34 {
35 if(T[i][j]==1 && j>1)
36 {
37 if (maxi<kez)
38 {
39 maxi=kez;
40 }
41 kez=0;
42 }
43 else if(T[i][j]==0) kez++;
44 }
45 if(T[i][M]==0)
46 {
47 if (maxi<kez)
48 {
49 maxi=kez;
50 }
51 kez=0;
52 }
53 }
54 g<<maxi;
55 }
56 else
57 {
58 int ta=0,maxk=-1,k=0,l=0;
59
60 for(i=0; i<=N+1; i++)
61 {
62 T[i][0]=T[i][M+1]=0;
63 }
64 for(i=0; i<=M+1; i++)
65 {
66 T[0][i]=T[N+1][i]=0;
67 }
68 for(i=1; i<=N; i++)
69 for(j=1; j<=M; j++)
70 {
71 if(T[i][j]>=1)
72 {
73 k=0;
74 if(T[i-1][j]>=1) k++;
75 if(T[i-1][j-1]>=1) k++;
76 if(T[i-1][j+1]>=1) k++;
77 if(k>1) return 1;
78 l=T[i+1][j]+T[i+1][j-1]+T[i+1][j+1];
79 if(k>1)
80 return 1;
81 if(k==0 && T[i][j]==1)
82 ta++;
83 if(k==1 && T[i][j]>=1)
84 {
85 if(T[i-1][j]>=1) T[i][j]=T[i-1][j]+1;
86 if(T[i-1][j+1]>=1) T[i][j]=T[i-1][j+1]+1;;
87 if(T[i-1][j-1]>=1) T[i][j]=T[i-1][j-1]+1;
88 }
89
90 if(l==0 && k==0 && T[i][j]==1) if (maxk<0) maxk=1;
91 if(l==0 && k==1)
92
93 if(maxk<=T[i][j]) maxk=T[i][j];
94 }
95 }
96
97 g<<ta<<" "<<maxk;
98 }
99 return 0;
100 }
1 #include <fstream>
2
3 using namespace std;
4
5 ifstream fin("foto.in");
CAPITOLUL 1. OJI 2020 14
6 ofstream fout("foto.out");
7
8 int imin, imax, a[105][105],n,m,ct;
9
10 int platou(int lin)
11 {
12 int l=0,lmax=0,i;
13 for(i=1; i<=m; i++)
14 if(a[lin][i]==0)
15 l++;
16 else
17 {
18 if(l>lmax)
19 lmax=l;
20 l=0;
21 }
22
23 if(l>lmax)
24 lmax=l;
25
26 return lmax;
27 }
28
29 void umple(int x,int y, int &xmin, int &xmax)
30 {
31 a[x][y]=0;
32 if(x<xmin)
33 xmin=x;
34 if(x>xmax)
35 xmax=x;
36 if(y-1>0 && a[x][y-1]==1)
37 umple(x,y-1,xmin,xmax);
38 if(y-1>0 && x+1<=n && a[x+1][y-1]==1)
39 umple(x+1,y-1,xmin,xmax);
40 if(x+1<=n && a[x+1][y]==1)
41 umple(x+1,y,xmin,xmax);
42 if(y+1<=m && x+1<=n && a[x+1][y+1]==1)
43 umple(x+1,y+1,xmin,xmax);
44 if(y+1<=m && a[x][y+1]==1)
45 umple(x,y+1,xmin,xmax);
46 }
47
48 void citire()
49 {
50 int i,j;
51 fin>>ct>>n>>m;
52 for(i=1; i<=n; i++)
53 for(j=1; j<=m; j++)
54 fin>>a[i][j];
55 }
56
57 int main()
58 {
59 citire();
60 int i, maxi=0,x,j,xmin,xmax,fulgere=0;
61 if(ct==1)
62 {
63 for(i=1; i<=n; i++)
64 {
65 x=platou(i);
66 if(x>maxi)
67 maxi=x;
68 }
69
70 fout<<maxi<<" ";
71 fout<<’\n’;
72 return 0;
73 }
74
75 for(i=1; i<=n; i++)
76 for(j=1; j<=m; j++)
77 if(a[i][j]==1)
78 {
79 fulgere++;
80 xmin=100;
81 xmax=0;
CAPITOLUL 1. OJI 2020 15
82 umple(i,j,xmin,xmax);
83 if(xmax-xmin>maxi)
84 maxi=xmax-xmin;
85 }
86
87 fout<<fulgere<<" "<<maxi+1<<’\n’;
88 return 0;
89 }
1.2 wind
Problema 2 - wind 100 de puncte
Domnul Vânt a pus pe marginea unei ³osele N centrale eoliene, dintre care unele produc energie
electric , iar altele, deocamdat , doar consum energie. El a etichetat centralele cu numerele
naturale distincte de la 1 la N, în ordinea poziµion rii lor pe ³osea. Fiecare central eolian are
la baz un ecran pe care este a³at un num r întreg, reprezentând cantitatea de energie pe care
o produce (dac num rul este pozitiv) sau pe care o consum (dac num rul este negativ).
Pentru a construi corect k ora³e de-a lungul acestei ³osele, un arhitect trebuie s aib în vedere
c :
a ec rui ora³ îi va atribuit câte un grup format din centrale eoliene vecine pe ³osea, toate
grupurile având acela³i num r de centrale;
a cantitatea de energie repartizat unui ora³ este egal cu suma numerelor a³ate pe ecranele
centralelor eoliene din grupul atribuit; uneori este posibil ca, deocamdat , suma obµinut s
e negativ ;
Cerinµe
Scrieµi un program care cite³te num rul N, valorile a³ate pe cele N ecrane ale centralelor
eoliene ³i rezolv urm toarele dou cerinµe:
1. a³eaz num rul M de moduri în care se pot grupa cele N centrale pentru construcµia
corect de ora³e;
2. a³eaz num rul maxim X de ora³e ce pot construite corect, dintre cele care au factorul de
dezechilibru minim, precum ³i eticheta E a primei centrale eoliene atribuit ora³ului cu cea
mai mare cantitate de energie repartizat , dintre cele X ora³e; dac sunt mai multe astfel
de ora³e, se ia în considerare cel care are atribuite centrale etichetate cu numere mai mari.
Date de intrare
Fi³ierul wind.in conµine pe prima linie un num r natural C reprezentând cerinµa care trebuie
rezolvat (1 sau 2).
A doua linie a ³ierului conµine un num r natural N, cu semnicaµia din enunµ.
A treia linie din ³ier conµine N numere întregi, separate prin câte un spaµiu, reprezentând
valorile a³ate pe cele N ecrane ale centralelor eoliene, în ordinea poziµion rii acestora pe ³osea.
Date de ie³ire
Fi³ierul wind.out va conµine pe prima linie:
a dac C 1, num rul natural M, reprezentând r spunsul la cerinµa 1;
a dac C 2, cele dou numere naturale X ³i E, în aceast ordine, separate printr-un singur
spaµiu, reprezentând r spunsul la cerinµa 2.
CAPITOLUL 1. OJI 2020 16
Restricµii ³i preciz ri
a 2&N & 100 000, N num r natural;
a Numerele a³ate pe ecranele centralelor sunt numere întregi formate din cel mult 9 cifre;
Exemple:
Pentru a putea împ rµi cele n eoliene în mod egal în k ora³e trebuie s determin m divizorii
num rului n.
Cerinµa 1: Se determin num rul de divizori al num rului de eoliene (n). Rezultatul va
num rul de divizori-1 deoarece se specic în enunµ c se vor costrui cel puµin dou ora³e, deci n
nu este un divizor valid.
Cerinµa 2: Se folose³te un vector suma, ecare element al acestuia memorând suma energiilor
dintre poziµia 1 (prima central ) ³i poziµia elementului respectiv (pozitia curent ).
sumai va reprezenta suma valorilor energiilor generate (pierdute) de centralele de la 1 la i.
Pentru a împ rµi centralele în mod corect trebuie s determin m divizorii num rului n. Pentru
ecare divizor se parcurge vectorul de sume din divizor in divizor ³i se calculeaz diferenµa dintre
sumele de pe poziµiile respective. Se alege împ rµirea optim .
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 long long d,smin,smax,divx,poz,pozmax,minimm=99999999999999999,
5 C,n,i,k,s[200001],v[10001],x,j,dif,minim=99999999999999999,
6 numar,gasit;
7
8 FILE *f,*g;
9
10 int main()
11 {
12 f=fopen("wind.in","r");
13 g=fopen("wind.out","w");
14
15 fscanf(f,"%lli",&C);
16
17 if(C==1)
18 {
19 fscanf(f,"%lli",&n);
20 for(i=1; i*i<=n; i++)
21 if(n%i==0)
22 {
23 k++;
24 if(i!=n/i)
25 k++;
26 }
27 k=k-1;
28 fprintf(g,"%lli",k);
29 }
30 else
31 {
32 fscanf(f,"%lli",&n);
33 for(i=1; i<=n; i++)
34 {
35 fscanf(f,"%lli",&x);
36 s[i]=s[i-1]+x;
37 }
38 for(i=1; i*i<=n; i++)
39 if(n%i==0)
40 {
41 k++;
42 v[k]=i;
43 if(i!=n/i)
44 if(n/i!=n)
45 {
46 k++;
47 v[k]=n/i;
48 }
49 }
50
51 for(i=1; i<=k; i++)
52 {
53 x=v[i];
54 smin=99999999999999999;
55 smax=-99999999999999999;
56
57 for(j=x; j<=n; j=j+x)
58 {
59 if ( s[j]-s[j-x]< smin)
60 smin=s[j]-s[j-x];
61 if (s[j]-s[j-x] >= smax)
62 {
63 smax=s[j]-s[j-x];
64 poz=j-x+1;
65 }
66 }
67 dif=smax-smin;
68
69 if(dif<minimm)
70 {
71 minimm=dif;
72 divx=x;
73 pozmax=poz;
74 }
CAPITOLUL 1. OJI 2020 18
1 #include <iostream>
2 #include <fstream>
3 #include <algorithm>
4
5 using namespace std;
6
7 ifstream f("wind.in");
8 ofstream g("wind.out");
9
10 long long d,smin,smax,divx,poz,pozmax,minimm=99999999,C,n,i,k,
11 s[200001],v[10001],x,j,dif,minim=99999999,numar,gasit;
12 int main()
13 {
14 f>>C;
15 if(C==1)
16 {
17 f>>n;
18 for(i=1; i*i<=n; i++)
19 if(n%i==0)
20 {
21 k++;
22 if(i!=n/i)
23 k++;
24 }
25 g<<k-1;
26 }
27 else
28 {
29 f>>n;
30 for(i=1; i<=n; i++)
31 {
32 f>>x;
33 s[i]=s[i-1]+x;
34 }
35 for(i=1; i*i<=n; i++)
36 if(n%i==0)
37 {
38 k++;
39 v[k]=i;
40 if(i!=n/i and n/i!=n)
41 {
42 k++;
43 v[k]=n/i;
44 }
45 }
46
47 for(i=1; i<=k; i++)
48 {
49 x=v[i];
50 smin=99999999999;
51 smax=-99999999999;
52
53 for(j=x; j<=n; j=j+x)
54 {
55 if ( s[j]-s[j-x]< smin)
56 smin=s[j]-s[j-x];
57 if (s[j]-s[j-x] >= smax)
58 {
59 smax=s[j]-s[j-x];
CAPITOLUL 1. OJI 2020 19
60 poz=j-x+1;
61 }
62 }
63 dif=smax-smin;
64 if(dif<minimm)
65 {
66 minimm=dif;
67 divx=x;
68 pozmax=poz;
69 }
70 else if(dif==minimm && x<divx)
71 {
72 divx=x;
73 pozmax=poz;
74 }
75 }
76 g<<n/divx<<" "<<pozmax;
77 }
78
79 return 0;
80 }
1 ///#include <iostream>
2 #include <fstream>
3
4 using namespace std;
5
6 ifstream f("wind.in");
7 ofstream g("wind.out");
8
9 long long s[100001];
10 int N,cer;
11
12 int nr_divizori()
13 { if(N==1)return 1;
14 int k=2,d;
15 for(d=2;d*d<=N;d++)
16 {
17 if(N%d==0)
18 { k++;
19 if(d*d!=N)k++;
20 }
21 }
22 return k;
23 }
24
25 int main()
26 {
27 f>>cer>>N;
28 if(cer==1)
29 {g<<nr_divizori()-1; return 0;}
30
31 ///cerinta 2
32 int ind=1,d,k,indk,nro=N,i,j,tt=2;
33 long long x, dmin, sd,sdmin,sdmax,difkmin, xmin, xmax;
34 f>>s[1];
35 xmin=xmax=s[1];
36 for(i=2;i<=N;i++)
37 {
38 f>>x;
39 xmin=min(xmin,x);
40 if(x>=xmax){xmax=x; ind=i;}
41 s[i]=s[i-1]+x;
42 }
43
44 dmin=xmax-xmin;
45 s[0]=0;
46 for(d=2;d<=N/2;d++)
47 {
48 if(N%d==0)
49 { k=N/d; sdmin=sdmax=s[d];indk=1;
50
51 for(j=d;j<=N;j=j+d)
CAPITOLUL 1. OJI 2020 20
52 { sd=(s[j]-s[j-d]);
53 if(sd<sdmin)sdmin=sd;
54 if(sd>=sdmax)
55 { sdmax=sd; indk=j-d+1; }
56 }
57 difkmin=sdmax-sdmin;
58
59 if(difkmin<dmin)
60 { nro=k; dmin=difkmin;ind=indk; tt=d; }
61 else if(difkmin==dmin && nro<k)
62 { nro=k; ind=indk; }
63 }
64 }
65
66 g<<nro<<" "<<ind;
67 return 0;
68 }
1 #include <fstream>
2
3 using namespace std;
4
5 ifstream fin("wind.in");
6 ofstream fout("wind.out");
7
8 int c, n, i, j, k, dm, um, d, u, emax, emin;
9 long long e[100005],dif, difm;
10
11 void c1()
12 {
13 int nrd=-1,d;
14 for(d=1;d*d<n;d++)if(n%d==0)nrd+=2;
15 fout<< nrd+(d*d==n);
16 }
17
18 long long diferenta(int d, int &u)
19 { long long smin,smax,s;
20 smin=smax=e[d];u=1;
21 for(int i=2*d;i<=n;i+=d)
22 { s=e[i]-e[i-d];
23 if(s>=smax)smax=s,u=i-d+1;
24 else if(s<smin)smin=s;
25 }
26 return smax-smin;
27 }
28
29 void refresh(int d)
30 { dif=diferenta(d,u);
31 if(dif<difm || dif==difm && d<dm)difm=dif,dm=d,um=u;
32 }
33
34 void c2()
35 {
36 dm=1;um=1;
37 fin>>e[1];emax=emin=e[1];
38 for(i=2;i<=n;i++){fin>>e[i];
39 if(e[i]<emin)emin=e[i];
40 else if(e[i]>=emax) emax=e[i],um=i;
41 e[i]+=e[i-1];}
42
43 difm=emax-emin;
44 for(d=2;d*d<n;d++)
45 if(n%d==0){ refresh(d);refresh(n/d);}
46 if(d*d==n)refresh(d);
47 fout<<n/dm<<’ ’<<um;
48 }
49
50 int main()
51 { fin>>c>>n;
52 if(c==1)c1();
53 else c2();
54 fin.close();fout.close();
55 return 0;
CAPITOLUL 1. OJI 2020 21
56 }
OJI 2019
Cerinµe
Scrieµi un program care cite³te valorile N ³i P cu semnicaµia din enunµ ³i rezolv urm toarele
cerinµe:
1. a³eaz num rul minim de dale pe care trebuie s calce pentru a deschide poarta;
2. a³eaz num rul natural T, reprezentând num rul minim de pic turi de poµiune magic
necesare pentru deschiderea porµii.
Date de intrare
Fi³ierul de intrare poarta.in conµine pe prima linie un num r natural C reprezentând cerinµa
din problem care trebuie rezolvat (1 sau 2). Pe a doua linie se a num rul natural N, iar pe
a treia linie se a num rul natural P cu semnicaµia din enunµ.
Date de ie³ire
Fi³ierul de ie³ire poarta.out va conµine o singur linie pe care va scris un num r natural
reprezentând r spunsul la cerinµa C.
Restricµii ³i preciz ri
2 & N $ 104
a P este num r natural nenul cu cel mult 1000 de cifre; pentru o parte dintre teste, valorând
în total 60 de puncte, P are cel mult 18 cifre.
a Recipientul conµine o cantitate sucient de poµiune magic .
a Pentru rezolvarea cerinµei 1 se acord maximum 60 de puncte, iar pentru rezolvarea cerinµei
2 se acord maximum 30 de puncte.
22
CAPITOLUL 2. OJI 2019 23
Exemple
poarta.in poarta.out Explicaµii
1 3 Tunelul are 5 dale pe ecare linie. Sindbad trebuie s ajung pe dala
5 numerotat cu 9. Num rul minim de dale pe care trebuie s calce
9 pentru a ajunge pe dala 9 pentru a deschide poarta este 3.
De pe margine poate s ri:
- pe dala numerotat cu 4 (consum 0 pic turi de poµiune magic );
- de pe dala numerotat cu 4 pe cea numerotat cu 8 (consum 2
pic turi de poµiune magic );
- de pe dala numerotat cu 8 pe cea numerotat cu 9 (consum 1
pic tur de poµiune magic ).
2 3 Pentru a ajunge pe dala numerotat cu 9 are nevoie de cel puµin 3
5 pic turi de poµiune magic .
9
Acest pas se repeta cat timp valoarea lui P este mai mare decat N. in cazul in care
la ultimul pas, este posibil sa ajunga pe prima linie atat prin scadere cu 1 cat si
impartire la 2, vom alege sa scadem 1, astfel incat sa obtinem numarul minim de pic
magice.
Pentru rezolvarea cerintei 1: numarul minim de dale pe care calca este numarul de p
efectuati pana cand valoarea lui P devine mai mica sau egala cu N
11 f>>cer>>n;
12 nv=0;
13 while(f>>c)
14 if(c>=’0’&&c<=’9’)
15 v[++nv]=c-’0’;
16 //for(i=1;i<=nv;i++) g<<v[i];g<<"\n";
17 ck=n;
18 while(ck)
19 {
20 nk++;ck=ck/10;
21 }
22
23 while(!gata)
24 {
25 j=0;k++;
26 if(v[nv]%2==0)
27 {
28 T+=2;pas=2;
29 for(i=1;i<=nv;i++)
30 {
31 j=j*10+v[i];
32 v[i]=j/2;j=j%2;
33
34 }
35 }
36 else
37 {
38 T++;pas=1;
39 if(v[nv]>0) v[nv]--;
40 }
41 if(v[1]==0)
42 {
43 i=1;j=1;
44 while(v[i]==0)i++;nv=nv-i+1;
45 while(j<=nv)v[j++]=v[i++];
46 }
47
48 if(nv<=nk)
49 {
50 ck=0;
51 for(i=1;i<=nv;i++) ck=ck*10+v[i];
52 if(ck<=n)gata=1;
53 }
54
55 //for(i=1;i<=nv;i++) g<<v[i];g<<"\n";
56 }
57 if(pas==2&&ck*2==n+1){ck=n;T=T-1;}
58 if(cer==1) g<<k<<"\n";//ne minim de dale
59 else g<<T<<"\n";//nr minim de picaturi
60 //g<<k<<"\n"<<ck<<"\n"<<T<<"\n";
61
62 return 0;
63 }
20 R%=2;
21 }
22 while (n && p[n]==’0’) p[n--]=0;
23 }
24
25 int Cmp(char p[], int&n, char N[])
26 {
27 if (n < l)
28 return -1;
29 else if (n > l)
30 return 1;
31 for (int i = n; i >= 0; --i)
32 if (p[i] < N[i])
33 return -1;
34 else if (p[i] > N[i])
35 return +1;
36 return 0;
37 }
38
39 void citire()
40 {
41 in>>c>>N;
42 in.get();
43 in.get(p,10001);
44 n=strlen(p)-1;
45 l=strlen(N)-1;
46 }
47
48 void rev(char p[], int n)
49 {
50 int i=0, j=n;
51 while(i<j)
52 {
53 char aux=p[i];p[i]=p[j];p[j]=aux;
54 i++;j--;
55 }
56 }
57
58 int main()
59 {
60 citire();
61 rev(p,n);
62 rev(N,l);
63 char pp[12];
64 unsigned long long pic=0,dal=1,pu;
65
66 while(Cmp(p,n,N)>0)
67 {
68 if(p[0]%2)
69 {
70 p[0]--;
71 dal++;
72 pic++;
73 }
74 else
75 {
76 if(n<=11)
77 {
78 strcpy(pp,p);
79 rev(pp,n);
80 pu=atoi(pp);
81 }
82 Divide(p,n);
83 pic+=2;
84 dal++;
85 }
86 //out<<p<<’ ’<<dal<<’ ’<<pic<<endl;
87 }
88
89 rev(N,l);
90 if(pu-1==atoi(N)) pic--;
91
92 if(c==1)
93 out<<dal<<’\n’;
94 else
95 out<<pic<<’\n’;
CAPITOLUL 2. OJI 2019 26
96
97 return 0;
98 }
64 else
65 {
66 potiune ++;
67 nr[k] --;
68 }
69 }
70
71 val = 0;
72 for(i=1; i<=k; i++)
73 val = val *10 + nr[i];
74
75 while(val > n)
76 {
77 if(val == n+1)
78 {
79 pasi ++;
80 potiune ++;
81 start = val-1;
82 break;
83 }
84
85 if(val % 2 == 0)
86 {
87 pasi ++;
88 potiune +=2;
89 val /=2;
90 }
91 else
92 {
93 pasi ++;
94 potiune ++;
95 val --;
96 }
97 if(val <= n)
98 start = val;
99 }
100 }
101
102 void write()
103 {
104 if(pr == 1)
105 cout << pasi << ’\n’;
106 else
107 cout << potiune << ’\n’;
108 }
109
110 int main()
111 {
112 read();
113 drum();
114 write();
115 return 0;
116 }
Exemple
CAPITOLUL 2. OJI 2019 29
Iniµial toµi juc torii pornesc de la casa de schimb valutar 1 care este alb . Exist N case
de schimb valutar ³i M juc tori. Juc torii mut pe rând în ordinea jetoanelor. Mai întâi mut
juc torul 1, apoi 2, 3, ..., M . Dup juc torul M va muta din nou 1 etc. La o mutare, un juc tor
care nu a fost eliminat din joc:
- d cu zarul electronic; zarul va a³a un num r întreg nr;
- avanseaz cu nr poziµii (adic dac jetonul s u este la casa i va ajunge la casa i nr);
- execut acµiunea asociat casei de schimb valutar în care a ajuns, în funcµie de culoarea
acesteia.
Zarul electronic funcµioneaz astfel: la mutarea cu num rul j este generat num rul nrj calculat
dup formula nrj a nrj 1 b%N 1, unde nrj 1 este num rul generat la mutarea j 1;
a, b ³i nr0 sunt trei valori cunoscute, iar % reprezint restul împ rµirii întregi (mod).
Cerinµe
Scrieµi un program care s rezolve urm toarele cerinµe:
1. determin num rul de juc tori existenµi în joc dup X mut ri;
2. determin juc torul care a r mas în joc ³i care are cea mai mare sum de Euro dup X
mut ri.
Date de intrare
Fi³ierul de intrare valutar.in conµine pe prima linie cerinµa care trebuie s e rezolvat (1 sau
2).
Pe a doua linie se a numerele naturale a b ³i nr0, cu semnicaµia din enunµ.
Pe a treia linie se a numerele naturale N M L E X , reprezentând num rul de case de
schimb valutar, num rul de juc tori, câµi lei ³i câµi euro prime³te ecare juc tor la începutul
jocului, respectiv num rul de mut ri din joc. Pe urm toarele N linii sunt descrise casele de schimb
valutar, câte o cas pe o linie, în ordinea de la 1 la N, sub forma Cod C V , cu semnicaµiile din
enunµ. Valorile scrise pe aceea³i linie sunt separate prin câte un spaµiu.
Date de ie³ire
Fi³ierul de ie³ire valutar.out va conµine o singur linie. Dac cerinµa este 1, linia va conµine
un num r natural reprezentând num rul de juc tori existenµi în joc dup X mut ri. Dac cerinµa
este 2, linia va conµine num rul jetonului juc torului r mas în joc ³i care are cea mai mare sum
de euro dup X mut ri.
Restricµii ³i preciz ri
1 & M, C, V & 100
a 1 & a, b, nr0, N, X & 10000
a 1L, E & 106
a Toate casele de schimb valutar au sucienµi lei ³i euro pentru efectuarea oric rei acµiuni.
a Se garanteaz c pentru datele de test la cerinµa 2 va r mâne în joc dup X mut ri un singur
juc tor cu suma maxim de euro.
a Pentru ecare cerinµ se acord 50% din punctajul obµinut pe teste.
CAPITOLUL 2. OJI 2019 30
Exemple
valutar.in valutar.out valutar.in valutar.out
1 1 2 2
3 2 7 3 2 7
5 3 2 3 8 5 3 2 3 8
A 1 1 A 1 1
G 5 4 G 5 4
G 6 4 G 6 4
V 6 5 V 6 5
R 2 3 R 2 3
Explicaµie:
Numerele care se obµin când se d cu zarul se genereaz astfel: nrj 3 nrj 1 2%5 1,
unde nr0 7.
Exist în joc 5 case de schimb valutar ³i 3 juc tori. Toµi juc torii au iniµial 2 lei ³i 3 euro ³i se
a la casa de schimb valutar 1 care este alb . Se efectueaz 8 mut ri astfel:
Pentru a memora datele despre casele de schimb valutar vom defini o structura
denumita casa cu 3 campuri: cod, C si V (conform enuntului).
Pentru a memora datele despre un jucator vom defini o structura denumita jucator
cu urmatoarele campuri:
-sl - suma in lei pe care o are jucatorul respectiv la un moment dat
-se - suma in euro pe care o are jucatorul la un moment dat
-pas - numarul de cartonase pas detinute de jucatorul respectiv.
CAPITOLUL 2. OJI 2019 31
47 if (J[cine].sl>=J[cine].unde*C[J[cine].unde].c)
48 {//cumpar euro
49 J[cine].se+=J[cine].unde;
50 J[cine].sl-=J[cine].unde*C[J[cine].unde].c;
51 }
52 else
53 if (J[cine].pas>0) J[cine].pas--;
54 else {J[cine].out=1; nrout++;}
55 }
56 else //vand euro
57 if (J[cine].se>=J[cine].unde)
58 {
59 J[cine].se-=J[cine].unde;
60 J[cine].sl+=J[cine].unde*C[J[cine].unde].v;
61 }
62 else
63 if (J[cine].pas>0) J[cine].pas--;
64 else {J[cine].out=1; nrout++;}
65 }
66
67 if (cerinta==1)
68 fout<<m-nrout;
69 else
70 {
71 for (i=1; i<=m; i++)
72 if (!J[i].out)
73 if (J[i].se>sum) {sum=J[i].se; jmax=i;}
74 fout<<jmax;
75 }
76
77 fout<<’\n’;
78 fout.close();
79 return 0;
80 }
39 J[i].e=e;
40 J[i].stare=true;
41 J[i].pas=0;
42 }
43 }
44
45 inline int aruncare(int zar)
46 {
47 return (a*zar+b)%n+1;
48 }
49
50 int main()
51 {
52 citire();
53 int i=1;
54 int p1=m;
55 for(int j=1; j<=x; ++j)
56 {
57 while(!J[i].stare)
58 {
59 ++i;
60 if(i>m)i-=m;
61 }
62 nr0=aruncare(nr0);
63 J[i].cc+=nr0;
64 if(J[i].cc>n) J[i].cc-=n;
65 int cc=J[i].cc;
66 switch(c[cc].cod)
67 {
68 case ’R’:
69 J[i].pas++;
70 break;
71 case ’G’:
72 if(c[cc].c*cc<=J[i].l)
73 {
74 J[i].l-=c[cc].c*cc;
75 J[i].e+=cc;
76 }
77 else if(J[i].pas) J[i].pas--;
78 else
79 {
80 J[i].stare=false;
81 p1--;
82 }
83 break;
84 case ’V’:
85 if(cc<=J[i].e)
86 {
87 J[i].l+=c[cc].v*cc;
88 J[i].e-=cc;
89 }
90 else if(J[i].pas) J[i].pas--;
91 else
92 {
93 J[i].stare=false;
94 p1--;
95 }
96 }
97 ++i;if(i>m)i-=m;
98 }
99 if(p==1) out<<p1<<’\n’;
100 else
101 {
102 unsigned long long k=0,maxi=0;
103 for (int i=1; i<n; ++i)
104 if(J[i].stare&&J[i].e>maxi){k=i;maxi=J[i].e;}
105 out<<k<<’\n’;
106 }
107 return 0;
108 }
3
4 #define Max 105
5 #define MaxC 10005
6
7 using namespace std;
8
9 ifstream cin("valutar.in");
10 ofstream cout("valutar.out");
11
12 struct case_schimb
13 {
14 char cul;
15 int c, v;
16 };
17
18 struct jucator
19 {
20 int sumL, sumE, pas, e_joc, poz;
21 };
22
23 jucator v[Max];
24 case_schimb c[MaxC];
25
26 int n, m, a, b, nra, X;
27 int pr;
28
29 void read()
30 {
31 int lei, euro;
32 cin >> pr;
33 cin >> a >> b >> nra;
34 cin >> n >> m >> lei >> euro >> X;
35 for(int i=1; i<=m; i++)
36 {
37 v[i].sumL = lei;
38 v[i].sumE = euro;
39 v[i].pas = 0;
40 v[i].e_joc = 1;
41 v[i].poz = 1;
42 }
43 for(int i=1; i<=n; i++)
44 {
45 cin >> c[i].cul >> c[i].c >> c[i].v;
46 }
47 }
48
49 void joc()
50 {
51 int nru, j, nrjucator, casa, val;
52 nrjucator = 1;
53 for(j=1; j<=X; j++)
54 {
55 nru = (a*nra+b)%n+1;
56 nra = nru;
57 while(v[nrjucator].e_joc == 0)
58 {
59 nrjucator ++;
60 if(nrjucator > m)
61 nrjucator = 1;
62 }
63 v[nrjucator].poz += nru;
64 v[nrjucator].poz = v[nrjucator].poz%n;
65 if(v[nrjucator].poz == 0)
66 v[nrjucator].poz = n;
67 casa = v[nrjucator].poz;
68 if(c[casa].cul ==’R’)
69 v[nrjucator].pas ++;
70 else
71 if(c[casa].cul == ’G’)
72 {
73 val = casa * c[casa].c;
74 if(v[nrjucator].sumL < val)
75 if(v[nrjucator].pas > 0)
76 v[nrjucator].pas --;
77 else
78 v[nrjucator].e_joc = 0;
CAPITOLUL 2. OJI 2019 35
79 else
80 {
81 v[nrjucator].sumL -= val;
82 v[nrjucator].sumE += casa;
83 }
84 }
85 else
86 if(c[casa].cul == ’V’)
87 {
88 val = casa * c[casa].v;
89 if(v[nrjucator].sumE < casa)
90 if(v[nrjucator].pas > 0)
91 v[nrjucator].pas --;
92 else
93 v[nrjucator].e_joc = 0;
94 else
95 {
96 v[nrjucator].sumE -= casa;
97 v[nrjucator].sumL += val;
98 }
99 }
100 nrjucator ++;
101 }
102 }
103
104 void write()
105 {
106 int i, nrj = 0, sum_max = 0, viz[100]={0}, k = 0;
107 for(i=1; i<=m; i++)
108 if(v[i].e_joc == 1)
109 {
110 nrj ++;
111 if(v[i].sumE > sum_max)
112 {
113 sum_max = v[i].sumE;
114 k=1;
115 viz[k] = i;
116 }
117 else
118 if(v[i].sumE == sum_max)
119 viz[++k] = i;
120 }
121 if(pr == 1)
122 cout << nrj << ’\n’;
123 else
124 {
125 for(i=1; i<=k; i++)
126 cout << viz[i] << ’ ’;
127 cout << ’\n’;
128 }
129 }
130
131 int main()
132 {
133 read();
134 joc();
135 write();
136 return 0;
137 }
Capitolul 3
OJI 2018
În gurile 1, 2, 3, 4 sunt piese de puzzle care respect regulile descrise, iar în gura 5 ³i în gura
6 NU sunt piese de puzzle, pentru c nu pot obµinute prin lipirea unor coloane de X -uri, una
dup cealalt , de la stânga spre dreapta.
Fiind mic, Mihai nu poate rezolva puzzle-ul, dar poate face o singur operaµie: alege dou piese
³i le îmbin în dreptul laturilor de sus, r sturnând una dintre piese sus-jos (f r s o roteasc sau
s o r stoarne stânga-dreapta). Dac în urma acestei operaµii el obµine un dreptunghi format din
coloane complete de X -uri, toate coloanele având aceea³i în lµime, este mulµumit. De exemplu,
piesa din gura 1 2 pot îmbinate în modul descris.
³i cea din gura
În gura 7 este piesa din gura 2 r sturnat sus-jos. În gura 8 este ilustrat dreptunghiul care
se obµine din piesa din gura 1 ³i piesa din gura 2 r sturnat sus-jos.
Observaµi c , dac am roti piesa din gura 4, am putea s o îmbin m cu piesa din gura 1,
dar rotaµia nu este permis .
Vom codica o pies printr-un num r natural, ecare cifr din num r reprezentând (în ordine
de la stânga la dreapta) câte X -uri se a pe coloana corespunz toare din pies .
De exemplu:
- piesa din gura 1 este codicat 4232;
- piesa din gura 2 este codicat 1323;
- piesa din gura 3 este codicat 4444;
- piesa din gura 4 este codicat 3231.
Cerinµe
Determinaµi care este num rul de moduri în care Mihai poate alege câte dou piese dintre cele
N pentru a face o operaµie în modul descris mai sus.
36
CAPITOLUL 3. OJI 2018 37
Date de intrare
Fi³ierul de intrare puzzle.in conµine pe prima linie un num r natural N ce reprezint num rul
de piese din joc. Pe linia a doua se g sesc N numere naturale, separate prin câte un singur spaµiu,
reprezentând codic rile celor N piese.
Date de ie³ire
Fi³ierul de ie³ire puzzle.out va conµine o singur linie pe care va scris num rul cerut.
Restricµii ³i preciz ri
2&N & 105
a Numerele care reprezint codic rile pieselor au acela³i num r de cifre (cel mult 5) ³i nu
conµin cifra 0.
a Într-o operaµie nu conteaz care dintre piese este r sturnat , ca urmare perechea format
din piesa a ³i piesa b este considerat ca ind aceea³i cu perechea format din piesa b ³i piesa a.
a Dreptunghiul obµinut în urma unei operaµii poate avea în lµimea mai mare decât 9.
a Pentru teste valorând 30 de puncte N & 1000. Se acord 10 puncte din ociu.
Exemple
puzzle.in puzzle.out Explicaµii
5 3 Se pot îmbina 3 perechi de piese: piesa 1 cu piesa 5, piesa
222 432 234 123 111 2 cu piesa 3, piesa 2 cu piesa 4. Piesele 3 ³i 4 s-ar putea
îmbina corect dac una dintre ele ar r sturnat stânga-
dreapta sau rotit , dar acest lucru nu e permis.
Observam ca doua numere reprezinta codificarile a doua piese ce pot fi cuplate daca
insumand doua cate doua cifrele de pe aceleasi pozitii in cele doua numere se obtin
aceeasi valoare.
O prima solutie, care obtine punctaj partial, neincadrandu-se in timp, fixeaza toat
perechile posibile de numere si aplica testul de mai sus.
O solutie mai buna, liniara este urmatoarea: observam ca doua configuratii sunt
identice daca scazand cu aceeasi valoare fiecare cifra a uneia, se obtine cealalta.
Astfel, fiecarui numar dat ii asociem drept cod valoarea obtinuta scazand din fieca
cifra a sa cifra cu valoare minima.
Astfel, intr-un vector c, pe pozitia fiecarui cod vom numara cate numere cu acel co
Pentru codul 0 adunam la solutie c[0] * (c[0] - 1) / 2, adica toate modurile de a a
piese cu toate laturile netede. Pentru fiecare dintre celelalte coduri i exista un
cod j pentru care piesele cu cele 2 coduri se pot imbina. Astfel, adunam la solutie
c[i] * c[j]. Codul j asociat unui cod i se obtine usor folosind algoritmul de parcu
cifrelor unui numar, aplicat lui i (practic, inlocuind fiecare cifra de valoare x a
valoarea maxim-x, unde maxim reprezinta valoarea celei mai mari cifre din i).
Gradul de dificultate: 3
CAPITOLUL 3. OJI 2018 38
1 #include <fstream>
2 #include <iostream>
3
4 #define DIMN 100010
5 #define DIMK 100010
6
7 using namespace std;
8
9 int f[DIMK];
10 int v[DIMN];
11 int c[12];
12 long long sol;
13 int n, k;
14
15 int getCode(int x)
16 {
17 int t = 0, minim = 9;
18 while (x)
19 {
20 c[++t] = x%10;
21 x /= 10;
22 if (c[t] < minim)
23 minim = c[t];
24 }
25
26 int r = 0;
27 for (int i=t;i>=1;i--)
28 r = r * 10 + (c[i] - minim);
29 return r;
30 }
31
32 int getReverse(int code, int k)
33 {
34 int t = 0, aux = code, maxim = 0;
35 for (int i=1;i<=k;i++)
36 {
37 c[++t] = aux%10;
38 aux /= 10;
39 maxim = max(maxim, c[t]);
40 }
41
42 int r = 0;
43 for (int i = t; i>=1; i--)
44 {
45 r = r * 10 + (maxim - c[i]);
46 }
47 return r;
48 }
49
50 int numar(int n)
51 {
52 int s = 0;
53 while (n)
54 {
55 s++;
56 n /= 10;
57 }
58 return s;
59 }
60
61 int main ()
62 {
63
64 ifstream fin ("puzzle.in");
65 ofstream fout("puzzle.out");
CAPITOLUL 3. OJI 2018 39
66
67 int aux;
68 fin>>n;
69
70 for (int i=1;i<=n;i++)
71 {
72 fin>>v[i];
73 if (i == 1)
74 k = numar(v[i]);
75 f[aux = getCode(v[i])]++;
76 //cout<<v[i]<<" "<<aux<<" "<<getReverse(aux, k)<<"\n";
77 }
78
79 sol = 0;
80 for (int i=1;i<=100000;i++)
81 sol += f[i] * 1LL * f[ getReverse(i, k) ];
82
83 sol /= 2;
84
85 sol += f[0] * 1LL * (f[0] - 1) / 2;
86
87 fout<<sol<<"\n";
88 return 0;
89 }
1 #include <fstream>
2
3 using namespace std;
4
5 ifstream f("puzzle.in");
6 ofstream g("puzzle.out");
7
8 int n,v[100000],nrc,x,y,k,i,Max;
9 long long s,z;
10
11 void red(int &x)
12 { int y=x,c=x%10; x=x/10;
13 while(x)
14 { c=min(c,x%10);
15 x/=10;
16 }
17 x=y-c*k;
18 }
19
20 int main()
21 { f>>n>>x;
22 y=x;
23 while(y){nrc++;y=y/10; k=k*10+1;}
24 red(x);
25 if(x==0) z++;
26 else v[x]++;
27
28 for(i=2;i<=n;++i)
29 { f>>x;
30 red(x);
31 if(x==0) z++;
32 else {Max=max(Max,x);v[x]++;}
33 }
34
35 s= z*(z-1)/2;
36 for(i=1;i<Max;i++)
37 if(v[i]) {x=9*k-i;
38 red(x);
39 if(x>i && v[x]) s=s+v[i]*v[x];
40 }
41
42 g<<s<<’\n’;
43 f.close();
44 g.close();
45 return 0;
46 }
CAPITOLUL 3. OJI 2018 40
Cerinµe
Se dau numerele naturale n ³i m ³i se cere s se determine:
1. Num rul de tuburi de culoare ro³ie necesare pentru a împacheta bilele din ³irul Y ³i num rul
total de bile conµinute de acestea.
2. Pentru un nivel v dat, suma numerelor inscripµionate pe bilele de pe nivelul v.
Date de intrare
Fi³ierul de intrare tbile.in c reprezentând cerinµa
conµine pe prima linie un num r natural
care trebuie s e rezolvat (1 sau 2), n, reprezentând num rul
pe a doua linie un num r natural
de bile ce se inscripµioneaz , iar pe cea de a treia linie un num r natural m, reprezentând num rul
de bile care încap într-un tub. Dac cerinµa este c 2, ³ierul de intrare conµine, în plus, pe a
patra linie, un num r natural v reprezentând num rul unui nivel.
Date de ie³ire
Dac cerinµa este c 1, atunci, pe prima linie a ³ierului tbile.out, vor scrise dou numere
naturale, separate printr-un spaµiu, reprezentând, în aceast ordine, num rul de tuburi de culoare
ro³ie necesare pentru a împacheta bilele din ³irul Y, respectiv, num rul total de bile conµinute de
acestea.
Dac cerinµa este c 2, atunci, pe prima linie a ³ierului tbile.out va scris un num r natural
reprezentând suma numerelor inscripµionate pe bilele de pe nivelul v.
Restricµii ³i preciz ri
5 & n & 2000000000
a 1 & c & m & 311445015
a Se acord 10 puncte din ociu, 30 de puncte pentru rezolvarea corect a cerinµei 1 ³i 60 de
puncte pentru rezolvarea corect a cerinµei 2.
Exemple
tbile.in tbile.out Explicaµii
1 6 29 Primul ³ir va conµine 7 bile (1, 3, 7, 12, 18, 26, 35), iar cel de al
36 doilea 36 7 29 de bile (ca în gura de mai sus). Sunt necesare
5 6 tuburi de capacitate 5.
2 126 Pe nivelul 3 se g sesc bilele inscripµionate cu numerele
36 7, 5, 11, 17, 23, 29 ³i 34.
5 Suma acestor valori este 126. .
3
CAPITOLUL 3. OJI 2018 41
Gradul de dificultate: 4
X[v], X[v+m], X[v+2*m], ... avand valorile <= n (bilele situate pe nivelul v
in tuburi galbene);
v+r1, v+m+r2, v+2*m+r3, ... avand valorile <= n (bilele situate pe nivelul v
in tuburi rosii) unde ri este egal cu numarul de termeni din sirul X <= v+(i-1)*m.
Pentru a obtine punctajul maxim, suma valorilor inscriptionate pe bile din tuburi
rosii avand valorile situate intre doi termeni consecutivi din sirul X poate fi
determinata utilizand sume de tip Gauss.
1 #include <fstream>
2
3 using namespace std;
4
5 ifstream in("tbile.in");
6 ofstream out("tbile.out");
7
8 long long n,x[64000],y,k,m,v,p,br,c,nivg,nivr;
9 long long s=0;
10
11 void AdunaRosu(long long f)
12 {
13 long long r=k-1,t;
14 if(br+r<=f)
15 {
16 t=(f-br-r)/m;
17 s+=(br+r)*(t+1)+m*t*(t+1)/2;
18 br+=m*(t+1);
19 }
20 }
21
22 int main()
23 {
24 in>>v>>n>>m;
25 if(v==2)
CAPITOLUL 3. OJI 2018 42
26 in>>c;
27 x[1]=1;x[2]=3;
28 y=4;p=3;
29 k=2;nivg=2;
30 br=c;
31
32 while(x[k]+y<=n)
33 {
34 k++;
35 nivg++;
36 if(nivg>m)nivg=1;
37 x[k]=x[k-1]+y;
38 if(nivg==c) s+=x[k];
39 AdunaRosu(x[k]-1);
40 y++;
41 if(y==x[p]){y++;p++;}
42 }
43
44 if(v==1)
45 {
46 br=n-k;
47 if(br%m==0)
48 out<<br/m;
49 else
50 out<<br/m+1;
51
52 out<<’ ’<<br<<’\n’;
53 }
54 else
55 {
56 if(x[k]<n)
57 {
58 k++;
59 AdunaRosu(n);
60 }
61
62 out<<s<<’\n’;
63 }
64
65 return 0;
66 }
1 #include <fstream>
2
3 using namespace std;
4
5 ifstream f("tbile.in");
6 ofstream g("tbile.out");
7
8 typedef unsigned long long ull;
9
10 ull galben[100000],s,t,p,rest;
11 int i,iRosu,v,r,n,m,c,j,nr;
12
13 int main()
14 { f>>v>>n>>m;
15 galben[1]=1;galben[2]=3;
16 iRosu=2; r=4; i=2;
17
18 while(galben[i]+r<=n)
19 { galben[++i]=galben[i-1]+r++;
20 if(r==galben[iRosu+1]) {iRosu++; r=galben[iRosu]+1;}
21 }
22
23 rest=n-galben[i];
24 r=n-i;
25
26 if(v==1)g<<r/m+(r%m>0)<<’ ’<<r<<’\n’;
27 else
28 { f>>c;
29 if(c==1) s=3;
30 else if(c==2) s=2;
31
CAPITOLUL 3. OJI 2018 43
32 nr=1;
33 for(j=3;j<=i;j++)
34 { if(j%m==c || j%m==0 && m==c) s=s+galben[j];
35 if(nr<c)
36 if(nr+galben[j]-galben[j-1]-1<c) {nr=nr+galben[j]-galben[j-1]-1; continue;}
37 else
38 p=galben[j-1]+(c-nr);
39 else
40 {
41 while(nr+(galben[j]-galben[j-1])-1<=m) {nr+=(galben[j]-galben[j-1]-1);j++;}
42 if(galben[j-1]+(m-nr)+c>=galben[j]) {nr=galben[j]-galben[j-1]-1-(m-nr);
continue;}
43 p=galben[j-1]+(m-nr+c);
44 }
45
46 nr=c;
47 t=(galben[j]-1-p)/m+1;
48 s+=p*t+(t-1)*t/2*m;
49 nr=c+galben[j]-(p+(t-1)*m)-1;
50 if(nr>m) nr-=m;
51 }
52
53 if(rest>0)
54 {
55 if(nr<c)
56 p=galben[i]+(c-nr);
57 else
58 p=galben[i]+(m-nr)+c;
59
60 while(p<=n) {s=s+p; p=p+m; }
61 }
62
63 g<<s<<’\n’;
64 }
65
66 f.close();
67 g.close();
68 return 0;
69 }
Capitolul 4
OJI 2017
Cerinµe
Cunoscându-se faptul c organizatorii doresc susµinerea a cât mai multor cursuri, s se deter-
mine:
1) Num rul maxim de cursuri care pot programate în cele K s li de clas , µinând cont de
restricµia indicat .
2) În dorinµa de a programa toate cursurile, în cele K s li, organizatorii decid s modice
durata cursurilor, p strând îns neschimbat ora de început a lor. Astfel, ei hot r sc ca toate
cursurile s dureze un interval egal de timp, care îns nu va dep ³i durata celui mai lung curs
propus iniµial de unul dintre cei N profesori. Determinaµi care poate durata maxim pe care o
pot avea cursurile în aceste condiµii.
Date de intrare
În ³ierul de intrare cursuri.in se g se³te pe prima linie un num r natural C . Pentru toate
testele, C poate lua numai valorile 1 sau 2. Pe linia a doua se g se³te o pereche de numere naturale
N K, separate printr-un spaµiu, reprezentând num rul profesorilor ³i num rul de s li de clas . Pe
urm toarele N linii se g sesc perechi de numere naturale ai bi , care reprezint intervalele de timp
în care cei N profesori î³i susµin cursurile. Numerele în cadrul unei linii sunt separate printr-un
spaµiu.
Date de ie³ire
Dac valoarea lui C este 1, se va rezolva numai punctul 1) din cerinµe. În acest caz, ³ierul de
ie³ire cursuri.out va conµine pe prima linie un num r natural reprezentând num rul maxim de
cursuri care pot programate în cele K s li de clas , µinând cont de restricµia indicat .
Dac valoarea lui C este 2, se va rezolva numai punctul 2) din cerinµe. În acest caz, ³ierul de
ie³ire cursuri.out va conµine pe prima linie un num r natural reprezentând durata maxim pe
care o pot avea cele N cursuri, astfel încât toate s poat susµinute în cele K s li disponibile.
Restricµii ³i preciz ri
a 1 & N & 1000
a 1 & K & 1000
a 1 & ai $ bi & 100000, unde 1&i&N
a în cazul cerinµei 2) se garanteaz c pentru toate testele exist soluµie
a Pentru rezolvarea corect a primei cerinµe se acord 45 de puncte, iar pentru rezolvarea
corect a celei de a doua cerinµe se acord 45 de puncte. Se acord 10 puncte din ociu.
44
CAPITOLUL 4. OJI 2017 45
Exemple
cursuri.in cursuri.out Explicaµii
1 3 O variant de programare optim este urm toarea:
4 2 - în prima sal se vor susµine cursurile programate între 1, 3 ³i
2 16 3, 18
1 3 - în a doua clas se susµine cursul programat între 1, 20.
3 18
1 20
2 4 Durata maxim pe care o pot avea toate cursurile este 4.
4 2 Cursul al treilea se va m ri ³i se va desf ³ura între 1, 5, celelalte
5 12 se vor mic³ora. Cursurile vor distribuite în cele dou s li astfel:
9 18 Sala 1: al treilea ³i primul profesor programaµi între 1, 5 res-
1 3 pectiv 5, 9;
1 7 Sala 2: al patrulea ³i al doilea profesor programaµi între 1, 5
respectiv 9, 13;
Prima cerinta poate fi rezolvata printr-un algoritm, care presuspune sortarea inter
dupa momentul de sfarsit al cursurilor. Dupa aceasta operatie, se parcurg toate cur
si pentru fiecare se verifica daca poate fi sustinut, adica daca exista vreo sala c
libera la momentul de inceput al cursului. Daca exista mai multe sali disponibile,
va fi programat in sala care minimizeaza durata cand aceasta ramane neocupata, adic
in care cursul anterior programat se termina cel mai tarziu. Complexitate O(N*N +N*
1 #include <bits/stdc++.h>
2
3 #define nmax 1005
4 #define inFile "cursuri.in"
5 #define outFile "cursuri.out"
6
7 using namespace std;
8
9 struct Interval
10 {
11 int a, b;
12 };
CAPITOLUL 4. OJI 2017 46
13
14 Interval t[nmax];
15
16 // dmax[i] = timpul final al ultimului interval
17 // pus in sala i, i=1..K
18 int d[nmax];
19
20 int n, K, op, M;
21
22 void Citire()
23 {
24 int i;
25 ifstream fin(inFile);
26 fin >> op;
27 fin >> n >> K;
28 for (i = 1; i <= n; i++)
29 {
30 fin >> t[i].a >> t[i].b;
31 M = max(M, t[i].b - t[i].a);
32 }
33 fin.close();
34 }
35
36 inline bool Cmp(const Interval X, const Interval Y)
37 {
38 if (X.b == Y.b) return X.a < Y.a;
39 return X.b < Y.b;
40 }
41
42 void Optiune1()
43 {
44 int i, j, p, ans, D;
45 sort(t + 1, t + n + 1, Cmp);
46 ans = 0;
47 for (i = 1; i <= n; i++)
48 {
49 // caut d[p] maxim, p=1..K
50 // cat mai aproape de capatul stang al intervalului i
51 p = 0; D = -1;
52 for (j = 1; j <= K; j++)
53 if (d[j] <= t[i].a && d[j] > D)
54 {
55 p = j;
56 D = d[j];
57 }
58 if (p != 0)
59 {
60 d[p] = t[i].b;
61 ans++;
62 }
63 }
64
65 ofstream fout(outFile);
66 fout << ans << "\n";
67 fout.close();
68 }
69
70 // returneaza 1 daca toate intervalele (de lungime L)
71 // se incadreaza in K clase
72 int Verifica(int L)
73 {
74 int i, j, p;
75 for (i = 1; i <= n; i++)
76 t[i].b = t[i].a + L;
77
78 for (i = 1; i <= K; i++)
79 d[i] = 0;
80
81 sort(t + 1, t + n + 1, Cmp);
82
83 for (i = 1; i <= n; i++)
84 {
85 // caut d[p] minim, p=1..K
86 p = 1;
87 for (j = 2; j <= K; j++)
88 if (d[p] > d[j]) p = j;
CAPITOLUL 4. OJI 2017 47
89
90 if (d[p] <= t[i].a)
91 d[p] = t[i].b;
92 else
93 return 0;
94 }
95
96 return 1;
97 }
98
99 void Optiune2()
100 {
101 int st, dr, L, sol;
102 st = 1;
103 dr = M;
104 sol = 0;
105 while (st <= dr)
106 {
107 L = (st + dr) / 2;
108 if (Verifica(L))
109 {
110 sol = L;
111 st = L + 1;
112 }
113 else
114 dr = L - 1;
115 }
116
117 ofstream fout(outFile);
118 fout << sol << "\n";
119 fout.close();
120 }
121
122 int main()
123 {
124 Citire();
125 if (op == 1)
126 Optiune1();
127 else
128 Optiune2();
129
130 return 0;
131 }
1 //Dana Lica
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5
6 #define inf 100001
7 #define Nmax 1010
8
9 using namespace std;
10
11 struct curs {int first; int second;};
12
13 curs A[Nmax], B[Nmax];
14 int N, K, T, Max, Lg;
15
16 bool cmps(curs x, curs y){ return x.second < y.second;}
17
18 bool cmpf(curs x, curs y){ return x.first< y.first;}
19
20 int solve_1(curs A[Nmax]){
21 int nr = 1, Sala[Nmax], Min, poz;
22 memset(Sala,0,sizeof(Sala));
23
24 sort(A + 1, A + N +1, cmps);
25
26 Sala[1]=A[1].second;
27 for(int i=2; i<=N; i++)
28 {
29 Min = inf;
CAPITOLUL 4. OJI 2017 48
1 //Dana Lica
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5
6 #define inf 100001
7 #define Nmax 1010
8
9 using namespace std;
10
11 struct curs {int first; int second;};
12
13 curs A[Nmax];
14
15 int N, K, T, Max, Lg;
16
17 void sortN2_second(curs A[Nmax])
18 {
19 curs aux;
20
21 for(int i=1; i<N; i++)
22 for(int j=i+1; j<=N; j++)
23 if(A[i].second>A[j].second ||
24 A[i].second== A[j].second && A[i].first>A[j].first)
25 aux=A[i], A[i]=A[j], A[j]=aux;
26 }
CAPITOLUL 4. OJI 2017 49
27
28 void sortN2_first(curs A[Nmax])
29 {
30 curs aux;
31
32 for(int i=1; i<N; i++)
33 for(int j=i+1; j<=N; j++)
34 if(A[i].first>A[j].first)
35 aux=A[i], A[i]=A[j], A[j]=aux;
36 }
37
38 int solve_1(curs A[Nmax])
39 {
40 int nr = 1, Sala[Nmax], Min, poz;
41
42 memset(Sala,0,sizeof(Sala));
43
44 sortN2_second(A);
45
46 Sala[1]=A[1].second;
47 for(int i=2; i<=N; i++)
48 {
49 Min = inf;
50 for(int j=1; j<=K; j++)
51 if (A[i].first>=Sala[j] && Min> A[i].first - Sala[j])
52 {
53 Min = A[i].first - Sala[j];
54 poz = j;
55 }
56
57 if(Min!= inf){ nr++; Sala[poz]=A[i].second;}
58 }
59
60 return nr;
61 }
62
63 int solve_2(curs A[Nmax])
64 {
65 int i, tmax=0, ans;
66
67 sortN2_first(A);
68
69 for(i=1; i<=N; ++i)
70 tmax = max(tmax, A[i].second - A[i].first);
71
72 ans = tmax;
73 for(i=K+1; i<=N; ++i)
74 ans = min(ans, A[i].first - A[i-K].first);
75
76 return ans;
77 }
78
79 int main()
80 {
81 freopen("cursuri.in", "r", stdin);
82 freopen("cursuri.out", "w", stdout);
83
84 scanf("%d\n%d %d\n", &T, &N, &K);
85
86 for(int i=1; i<=N; i++)
87 scanf("%d %d\n", &A[i].first, &A[i].second);
88
89 if (T==1)
90 printf("%d\n", solve_1(A));
91 else
92 printf("%d\n", solve_2(A));
93
94 return 0;
95 }
1 //Raluca Costineanu
2 #include <fstream>
3
CAPITOLUL 4. OJI 2017 50
80 if(verif(m))
81 gasit=m, s=m+1;
82 else
83 d=m-1;
84 }
85
86 return gasit;
87 }
88
89 int main()
90 {
91 int i;
92 f>>cerinta>>n>>k;
93
94 for(i=1;i<=n;i++)
95 f>>a[i].oi>>a[i].of, a[i].p=false;
96
97 sort();
98
99 if(cerinta==1)
100 g<<cerinta1();
101 else
102 g<<cerinta2();
103
104 return 0;
105 }
1 // Rotar Mircea
2 #include <bits/stdc++.h>
3
4 using namespace std;
5
6 struct curs
7 {
8 int a,b;
9 };
10
11 bool cmp(const curs X, const curs Y)
12 {
13 if (X.a == Y.a) return X.b > Y.b;
14
15 return X.a > Y.a;
16 }
17
18 int caut_bin(int v[],int n, int x)
19 {
20 int i = 0;
21 for(int step = (1<<20)/*2^20*/; step > 0; step /= 2)
22 if(i+step < n && v[i+step] <= x)
23 i += step;
24 return i;
25 }
26
27 int nr_suprapuneri(curs st[1010], const int n, const int maxn)
28 {
29 static int arr[2500000 + 100];
30
31 for(int i = 0; i < n; ++i)
32 ++arr[st[i].a], --arr[st[i].b];
33
34 for(int i = 1; i < maxn + 100; ++i)
35 arr[i] += arr[i-1];
36
37 int best = 0;
38 for(int i = 0; i < maxn +100; ++i)
39 best = max(best, arr[i]), arr[i] = 0;
40
41 return best;
42 }
43
44 int nr_cursuri(curs v[1010], const int n, const int k)
45 {
46 static curs arr[2020];
CAPITOLUL 4. OJI 2017 52
47 int poz = 0;
48
49 for(int i = 0; i < n; ++i)
50 if(arr[poz++] = v[i], nr_suprapuneri(arr, poz, 2010) > k)
51 --poz;
52
53 return poz;
54 }
55
56 void elimin_duplicat(int a[],int &len)
57 {
58 int dup=0;
59
60 for(int i=1;i<len;i++)
61 {
62 if(a[i-1]==a[i])
63 {
64 dup++;
65 }
66 else
67 {
68 a[i-dup]=a[i];
69 }
70 }
71
72 len=len-dup;
73 }
74
75 int main()
76 {
77 ifstream f("cursuri.in");
78 ofstream g("cursuri.out");
79
80 int t, n, k;
81
82 f >> t >> n >> k;
83
84 curs v[1010];
85
86 for(int i = 0; i < n; ++i)
87 f >> v[i].a >> v[i].b;
88
89 if(t == 1)
90 {
91 static int norm[2020], len = 2*n;
92
93 for(int i = 0; i < n; ++i)
94 norm[2*i] = v[i].a, norm[2*i+1] = v[i].b;
95
96 sort(norm, norm+len);
97
98 //elimina duplicatele cu exceptia primului
99 // len = unique(norm, norm+len)-norm;
100
101 elimin_duplicat(norm,len); //intr-o secv de elem consecutive
102
103 for(int i = 0; i < n; ++i)
104 {
105 v[i].a = caut_bin(norm,len,v[i].a);
106 v[i].b = caut_bin(norm,len,v[i].b);
107 }
108
109 sort(v, v+n, cmp);
110
111 g << nr_cursuri(v, n, k);
112 }
113 else
114 {
115 int rez,st=1, dr=0, mij;
116 for(int i = 0; i < n; ++i)
117 dr = max(dr, v[i].b - v[i].a);
118
119 while(st<=dr)
120 {
121 mij=st+(dr-st)/2;
122 for(int i = 0; i < n; ++i)
CAPITOLUL 4. OJI 2017 53
Cerinµe
Cunoscând numerele N, K ³i cele K ³iruri de numere care reprezint rundele jucate, scrieµi
un program care s rezolve una dintre urm toarele dou cerinµe:
1. S se determine câte runde a câ³tigat ecare copil.
2. S se determine care este cel mai mare num r de marc ri efectuate pân la câ³tigarea unei
runde.
Date de intrare
Fi³ierul de intrare joc.in conµine pe prima linie un num r natural C . Pentru toate testele, C
poate lua numai valorile 1 sau 2. Pe a doua linie se a dou numere naturale N ³i K, separate
prin câte un spaµiu, reprezentând dimensiunea tablei de joc ³i respectiv num rul de runde jucate.
Pe urm toarele K linii sunt descrise rundele de joc, câte o rund pe câte o linie a ³ierului. În
cadrul liniilor, numerele sunt separate prin câte un spaµiu.
Date de ie³ire
Dac valoarea lui C este 1, se va rezolva numai punctul 1) din cerinµe. În acest caz, ³ierul
de ie³ire joc.out va conµine pe prima linie dou numere naturale t ³i s, separate printr-un spaµiu,
unde t reprezint num rul de runde câ³tigate de Teodora, iar s num rul rundelor câ³tigate de
tefan.
Dac valoarea lui C este 2, se va rezolva numai punctul 2) din cerinµe. În acest caz, ³ierul
de ie³ire joc.out va conµine pe prima linie num rul cel mai mare de marc ri efectuate pân la
câ³tigarea unei runde.
CAPITOLUL 4. OJI 2017 54
Restricµii ³i preciz ri
a 3&N & 100
a 1&K & 25
a La ecare joc se câ³tig cel puµin o rund .
a Pentru rezolvarea corect a primei cerinµe se acord 45 de puncte, iar pentru rezolvarea
corect a celei de a doua cerinµe se acord 45 de puncte. Se acord 10 puncte din ociu.
Exemple
joc.in joc.out Explicaµii
1 2 1 Ilustrarea rundelor de joc pân la momen-
4 4 tul identic rii unui câ³tig tor este urm -
16 13 15 9 10 1 5 2 6 14 3 7 11 4 8 12 toarea:
1 2 3 4 5 6 7 8 12 11 10 9 13 14 15 16
1 5 9 6 2 7 3 8 4 10 11 12 13 14 15 16
1 2 3 4 8 7 6 5 12 11 10 9 16 15 14 13
Pentru a simplifica retinerea datelor definim structura ’’marcare’’ ale carei campu
memora numarul de celule marcate de fiecare jucator, corespunzator liniei, coloanei
diagonalei sau semidiagonalei din care face parte.
1 #include <fstream>
2
3 using namespace std;
4
5 struct marcare
6 {
7 int l[151], c[151];
8 int dp, dp1, dp2;
9 int ds, ds1, ds2;
10 } jucator[2];
11
12 int cT, cS, maxim, jucatorul;
13
14 int main()
15 {
16 ifstream f("joc.in");
17 ofstream g("joc.out");
18
19 int n, k, i, nr, j, m, lin, col, p, mutari, joc, gata, c;
20
21 f>>c>>n>>k;
22 m=n*n;
23 maxim=-1;
24
25 for(i=1;i<=k;i++)
26 {
27 j=i%2;//jucatorul care incepe runda
28 gata=0;
29 for(joc=0;joc<2;joc++)
30 {
31 for(p=1;p<=n;p++)
32 jucator[joc].l[p]=jucator[joc].c[p]=0;
33
34 jucator[joc].dp=jucator[joc].dp1=jucator[joc].dp2=0;
35 jucator[joc].ds=jucator[joc].ds1=jucator[joc].ds2=0;
36 }
37
38 mutari=m+1;
39 for(p=1; p<=m; p++)
40 {
41 joc=(j+p%2)%2;//jucatorul care marcheaza 0=T, 1=S
42 f>>nr;
CAPITOLUL 4. OJI 2017 56
43
44 if(gata==0) //runda nu s-a incheiat
45 { //determin linia si coloana celulei marcate
46 lin=nr/n;
47 col=nr%n;
48 if(col==0)
49 col=n;
50 else
51 lin++;
52
53 //actualizez corespunzator nr celulelor marcate
54 jucator[joc].l[lin]++;
55 jucator[joc].c[col]++;
56 if(lin==col)
57 jucator[joc].dp++;
58 else
59 if (lin==col+1)
60 jucator[joc].dp1++;
61 else
62 if(lin+1==col)
63 jucator[joc].dp2++;
64
65 if(lin+col==n+1)
66 jucator[joc].ds++;
67 else
68 if (lin+col==n)
69 jucator[joc].ds1++;
70 else
71 if(lin+col==n+2)
72 jucator[joc].ds2++;
73
74 //verific daca runda s-a incheiat
75 if(jucator[joc].l[lin]==n ||
76 jucator[joc].c[col]==n ||
77 jucator[joc].dp==n ||
78 jucator[joc].dp1==n-1||
79 jucator[joc].dp2==n-1||
80 jucator[joc].ds==n ||
81 jucator[joc].ds1==n-1 ||
82 jucator[joc].ds2==n-1)
83 {
84 gata=1;
85 if(joc==0)
86 cT++;
87 else
88 cS++;
89
90 mutari=p;
91 }
92 }
93 }
94
95 if(mutari>maxim && mutari<m+1)
96 maxim=mutari;
97 }
98
99 if(c==1)
100 g<<cT<<’ ’<<cS<<’\n’;
101 else
102 g<<maxim<<’\n’;
103
104 f.close();
105 g.close();
106 return 0;
107 }
1 //Dana Lica
2 #include <cstdio>
3 #include <algorithm>
4 #include <cstring>
5
6 #define Nmax 155
7
CAPITOLUL 4. OJI 2017 57
84 {
85 ++diag2S[dif];
86 if((dif==2 && diag2S[dif]==N) ||
87 (dif!=2 && diag2S[dif]==N-1))
88 return true;
89 }
90
91 return false;
92 }
93
94 void initialize()
95 {
96 memset(LT, 0, sizeof(LT));
97 memset(LS, 0, sizeof(LS));
98 memset(CT, 0, sizeof(CT));
99 memset(CS, 0, sizeof(CS));
100 memset(diag1T, 0, sizeof(diag1T));
101 memset(diag1S, 0, sizeof(diag1S));
102 memset(diag2T, 0, sizeof(diag2T));
103 memset(diag2S, 0, sizeof(diag2S));
104 }
105
106 int main()
107 {
108 freopen("joc.in", "r", stdin);
109 freopen("joc.out", "w", stdout);
110
111 scanf("%d\n", &T);
112 scanf("%d %d\n", &N, &K);
113
114 for(test=1; test<=K; ++test)
115 {
116 initialize();
117 win = 0;
118 for(i=1; i<=N*N; ++i)
119 {
120 scanf("%d", &x);
121
122 if((test%2==1 && i%2==1) || (test%2==0 && i%2==0))
123 {
124 if(addT(x))
125 {
126 ++winT;
127 win = 1;
128 moves = max(moves, i);
129 }
130 }
131 else
132 if(addS(x))
133 {
134 ++winS;
135 win = 1;
136 moves = max(moves, i);
137 }
138 }
139 }
140
141 if(T==1)
142 printf("%d %d\n", winT, winS);
143 else
144 printf("%d\n", moves);
145
146 return 0;
147 }
1 #include <bits/stdc++.h>
2
3 #define nmax 155
4
5 using namespace std;
6
7 ifstream fin("joc.in");
8 ofstream fout("joc.out");
CAPITOLUL 4. OJI 2017 59
9
10 struct scor
11 {
12 int A, B;
13 };
14
15 int n, N; /// N = n * n
16 scor a[nmax * nmax];
17 scor L[nmax], C[nmax], DP[3], DS[3];
18 /**
19 a[i] =(x,y) : coordonatele din matrice corespunzatoare
20 valorii i, unde i=1..n*n
21 L[i]=(x, y) : pe linia i sunt puse x X-uri si y zeroruri
22 D[i]=(x, y) : pe coloana i sunt puse x X-uri si y zeroruri
23 DP[i]=(x,y) : pe diagonalele paralele cu diagonala principala
24 sunt puse x X-uri si y zeroruri
25 DS[i]=(x,y) : pe diagonalele paralele cu diagonala secundara
26 sunt puse x X-uri si y zeroruri
27 */
28
29 void Matrice()
30 {
31 int i, j, p;
32 p = 0;
33 for (i = 1; i <= n; i++)
34 for (j = 1; j <= n; j++)
35 {
36 p++;
37 a[p].A = i;
38 a[p].B = j;
39 }
40 }
41
42 void Runda(int r, int &whoWins, int &nrMoves)
43 {
44 int i, laMutare, x, lin, col;
45 for (i = 1; i <= n; i++)
46 L[i].A = L[i].B = C[i].A = C[i].B = 0;
47 for (i = 0; i <= 2; i++)
48 DP[i].A = DP[i].B = DS[i].A = DS[i].B = 0;
49 whoWins = -1;
50 nrMoves = 0;
51 laMutare = 1 - r % 2;
52 for (i = 1; i <= N; i++)
53 {
54 fin >> x;
55 if (whoWins >= 0) continue;
56 nrMoves++;
57 lin = a[x].A;
58 col = a[x].B;
59
60 /// actualizare scor pe linia lin
61 if (laMutare == 0) L[lin].A++;
62 else L[lin].B++;
63 if (L[lin].A == n) {whoWins = 0; continue;}
64 else if (L[lin].B == n) {whoWins = 1; continue;}
65
66 /// actualizare scor pe coloana col
67 if (laMutare == 0) C[col].A++;
68 else C[col].B++;
69 if (C[col].A == n) {whoWins = 0; continue;}
70 else if (C[col].B == n) {whoWins = 1; continue;}
71
72 /// actualizare scor pe diag. principala
73 if (lin == col)
74 {
75 if (laMutare == 0) DP[1].A++;
76 else DP[1].B++;
77 if (DP[1].A == n) {whoWins = 0; continue;}
78 else if (DP[1].B == n) {whoWins = 1; continue;}
79 }
80
81 /// actualizare scor sub diag. principala; (i+1,i)
82 if (lin == col + 1)
83 {
84 if (laMutare == 0) DP[0].A++;
CAPITOLUL 4. OJI 2017 60
85 else DP[0].B++;
86 if (DP[0].A == n - 1) {whoWins = 0; continue;}
87 else if (DP[0].B == n - 1) {whoWins = 1; continue;}
88 }
89
90 /// actualizare scor deasupra diag. principala; (i-1,i)
91 if (lin == col - 1)
92 {
93 if (laMutare == 0) DP[2].A++;
94 else DP[2].B++;
95 if (DP[2].A == n - 1) {whoWins = 0; continue;}
96 else if (DP[2].B == n - 1) {whoWins = 1; continue;}
97 }
98
99 /// actualizare scor pe diag. secundara
100 if (lin + col == n + 1)
101 {
102 if (laMutare == 0) DS[1].A++;
103 else DS[1].B++;
104 if (DS[1].A == n) {whoWins = 0; continue;}
105 else if (DS[1].B == n) {whoWins = 1; continue;}
106 }
107
108 /// actualizare scor sub diag. secundara; (lin+col=n+2)
109 if (lin + col == n + 2)
110 {
111 if (laMutare == 0) DS[0].A++;
112 else DS[0].B++;
113 if (DS[0].A == n - 1) {whoWins = 0; continue;}
114 else if (DS[0].B == n - 1) {whoWins = 1; continue;}
115 }
116
117 /// actualizare scor deasupra diag. secundara; (lin+col=n)
118 if (lin + col == n)
119 {
120 if (laMutare == 0) DS[2].A++;
121 else DS[2].B++;
122 if (DS[2].A == n - 1) {whoWins = 0; continue;}
123 else if (DS[2].B == n - 1) {whoWins = 1; continue;}
124 }
125 laMutare = 1 - laMutare;
126 }
127 }
128
129 int main()
130 {
131 int nrMoves, whoWins, r, op, K;
132 int scorA, scorB, maxMoves;
133
134 fin >> op;
135 fin >> n >> K;
136 N = n * n;
137
138 Matrice();
139
140 scorA = scorB = maxMoves = 0;
141 for (r = 1; r <= K; r++)
142 {
143 Runda(r, whoWins, nrMoves);
144 if (whoWins == 0) scorA++;
145 else if (whoWins == 1) scorB++;
146 if (whoWins != -1) maxMoves = max(maxMoves, nrMoves);
147 }
148
149 if (op == 1)
150 fout << scorA << " " << scorB << "\n";
151 else
152 fout << maxMoves << "\n";
153
154 fout.close();
155 return 0;
156 }
77 {
78 dif=dif*(-1);
79 i1=1; j1=n-dif;
80 }
81 else
82 {
83 i1=1+dif; j1=n;
84 }
85
86 for(int i=0;i<=n-dif-1;i++)
87 {
88 if(a[i1+i][j1-i]!=p)
89 {
90 d2=0; break;
91 }
92 }
93 }
94 else
95 {
96 d2 = 0;
97 }
98
99 if(d2==1) return 1;
100
101 return 0;
102 }
103
104 void incepe_jocul()
105 {
106 int x,lin,col,contor=0,contormax=0,primul=1,poz1=1,poz2=2;
107 int crt,Teo=0,Stef=0;
108
109 f>>v>>n>>k;
110
111 ///vector<vector<int>> a(n+1,vector<int>(n+1,0));
112 int a[60][60];
113
114 while(f>>x)
115 {
116 contor++;
117 (contor%2==0) ? crt=poz2 : crt=poz1;
118
119 lin=(x-1)/n+1;
120
121 (x%n==0) ? col=n: col=x%n;
122
123 a[lin][col]=crt;
124
125 if(test(a,lin,col,crt)==1)
126 {
127 (crt==1) ? Teo++ : Stef++;
128
129 contormax=max(contor,contormax);
130
131 for(int i=1;i<=n*n-contor;++i)
132 f>>x;
133 if(primul==1)
134 {
135 primul=2;
136 poz1=2; poz2=1;
137 }
138 else
139 {
140 primul=1;
141 poz1=1; poz2=2;
142 }
143
144 zero(a,n);
145 contor=0;
146 }
147 }
148
149 if(v==1)
150 {
151 g<<Teo<<" "<<Stef<<"\n";
152 }
CAPITOLUL 4. OJI 2017 63
153 else
154 {
155 g<<contormax<<"\n";
156 }
157 }
158
159 int main()
160 {
161 incepe_jocul();
162 return 0;
163 }
Capitolul 5
OJI 2016
Date de intrare
Fi³ierul de intrare axyz.in conµine:
- pe prima linie un num r natural p; pentru toate testele de intrare, num rul p poate avea doar
valoarea 1 sau valoarea 2;
- pe a doua linie, num rul A, cu semnicaµia din enunµ;
- pe a treia linie num rul de cifre ale num rului X;
- pe a patra linie, un ³ir de N cifre, separate prin câte un spaµiu, reprezentând cifrele num rului
X, în aceast ordine.
Date de ie³ire
a Dac valoarea lui p este 1, atunci se va rezolva numai cerinµa 1. În acest caz, ³ierul de ie³ire
axyz.out va conµine pe prima linie un ³ir de cifre reprezentând num rul natural Y determinat
(r spunsul la cerinµa 1).
a Dac valoarea lui p este 2, atunci se va rezolva numai cerinµa 2. În acest caz, ³ierul de
ie³ire axyz.out va conµine pe prima linie un num r natural reprezentând num rul Z determinat
(r spunsul la cerinµa 2).
Restricµii ³i preciz ri
a 12 & A & 987
a 10 & N & 30000
a Pentru toate datele de test, numerele Y ³i A pot obµinute din num rul X
a Pentru rezolvarea corect a cerinµei 1 se acord 30% din punctaj, iar pentru rezolvarea
corect a cerinµei 2 se acord 70% din punctaj.
64
CAPITOLUL 5. OJI 2016 65
Exemple
axyz.in axyz.out Explicaµii
1 121612 Se rezolv cerinµa 1.
12 A=12, N=6, X=121621
6 Cel mai mare num r Y strict mai mic ca X este: Y=121612.
1 2 1 6 2 1
2 3 Se rezolv cerinµa 2. A=12, N=6, X=121621
12 Sunt Z=3 posibilit µi distincte prin care se obµine num rul A
6 din X: 1) 121621; 2) 121621; 3) 121621
1 2 1 6 2 1
Descrierea solutiei
- Determinam pozitia poz a celei mai mari cifre dintre cele situate pe pozitiile
k+1,k+2,...,N si cu proprietatea X[k]>X[poz]
- Altfel, daca cifra curenta este a atunci se pot forma cu NB numere A din
cifra a curenta si cele NB cifre b situate la dreapta lui a in X. Adaugam
numarul acestora la celelalte gasite pana in acest moment (Z=Z+NB)
-Complexitate O(N)
1 #include <fstream>
2
3 using namespace std;
4
5 int x[30001];
6 ifstream f("axyz.in");
7 ofstream g("axyz.out");
8
9 int main()
10 {
11 int N,A,B,C,NB,Z,i,k,j, poz, t,cer;
12 f>>cer>>A>>N;
13 for(i=1; i<=N; i++)
14 f>>x[i];
15 ///cerinta 1) - problema are solutie pentru toate testele propuse
16 if(cer==1)
17 {
18 k=N-1;
19 while(k>0 && x[k]<=x[k+1])
20 k--;
21 poz=N;
22 while(poz>k && x[poz]>=x[k])
23 poz--;
24 swap(x[k],x[poz]);
25 for(i=1; i<=k; i++)
26 g<<x[i];
27 for(i=N; i>k; i--)
28 g<<x[i];
29 g<<’\n’;
30 }
31 else ///cerinta 2
32 if(A<100)
33 {
CAPITOLUL 5. OJI 2016 67
34 B=A%10;
35 A=A/10;
36 Z=0;
37 NB=0;
38 for(i=N; i>=1; i--)
39 if(x[i]==B)NB++;
40 else if(x[i]==A)Z+=NB;
41 g<<Z<<’\n’;
42 }
43 else
44 {
45 int i,C,NC=0,NBC=0,Z=0;
46
47 C=A%10;
48 A/=10;
49 B=A%10;
50 A/=10;
51
52 for (i=N; i>=1;i--)
53 if(x[i]==C)
54 NC++;
55 else
56 if(x[i]==B)
57 NBC+=NC;
58 else
59 if(x[i]==A)
60 Z+=NBC;
61
62 g<<Z<<’\n’;
63 }
64
65 return 0;
66 }
Cerinµe
Cunoscându-se numerele n, m, t ³i cele t celule exterioare în care se a cârtiµele, s se
determine:
1. num rul maxim de celule în care sap o cârtiµ pân la oprirea tuturor cârtiµelor;
2. num rul maxim de celule din care este format o galerie interioar .
Date de intrare
Fi³ierul de intrare galerie.in conµine pe prima linie, una dintre valorile 1 sau 2 reprezentând
cerinµa 1, dac se cere determinarea num rului maxim de celule în care sap o cârtiµ pân la
oprirea tuturor cârtiµelor, respectiv cerinµa 2, dac se cere determinarea num rul maxim de celule
din care este format o galerie interioar .
Linia a doua conµine, separate prin câte un spaµiu, trei numere naturale: n ³i m (reprezentând
dimensiunile terenului) ³i t (reprezentând num rul de cârtiµe aate în galeriile exterioare).
Linia a treia conµine cele t numere naturale separate prin câte un spaµiu, reprezentând poziµiile
celor t cârtiµe.
Date de ie³ire
Fi³ierul de ie³ire galerie.out conµine pe prima linie o valoarea natural reprezentând num rul
maxim de celule în care sap o cârtiµ pân la oprirea tuturor cârtiµelor, dac cerinµa a fost 1,
respectiv un num r natural reprezentând num rul maxim de celule din care este format o galerie
interioar , dac cerinµa a fost 2.
Restricµii ³i preciz ri
a 3 & n, m & 200; 1 & t & 2 n m;
a într-o celul numerotat , exterioar terenului, se poate aa o singur cârtiµ .
a Pentru rezolvarea corect a cerinµei 1 se acord 30% din punctaj, iar pentru rezolvarea
corect a cerinµei 2 se acord 70% din punctaj.
Exemple
galerie.in galerie.out Explicaµii
1 5 Cârtiµa care pleac din poziµia 23 sap în dou celule; cârtiµele
7 5 5 care pleac din poziµiile 3 ³i 8, sap în 3 celule, iar celelalte dou
19 3 8 10 23 cârtiµe în 5 celule.
2 7 S-au format trei galerii interioare, dou formate din câte 5 celule
7 5 5 ³i o galerie interioar format din 7 celule (g.6).
19 3 8 10 23
Cerinta 1 ( 30 puncte)
Problema se restrange la fiecare pas la multimea cartitelor active (cele care sapa)
* se elimina apoi din multimea cartitelor active, cartitele care se opresc, fie pen
CAPITOLUL 5. OJI 2016 69
in celula in care au ajuns se mai afla si alte cartite, fie pentru ca au ajuns in
alta galerie (pe marginea terenului sau intr-o galerie interioara);
Cerinta 2 ( 70 de puncte)
Daca o cartita sapa singura intr-o celula, atunci, se aduna o unitate la lungimea
traseului sapat.
Daca o cartita c1 sapa intr-o galerie interioara, de lungime l1, si ajunge in galer
unei alte cartite c2, care se afla intr-o galerie interioara de lungime l2, atunci
cartita c1 se opreste, galeriile se unesc, si lungimea galeriei l2, in care se afl
cartita c2, devine l1+l2.
Daca intr-o celula ajung, in acelasi moment de timp, mai multe cartite, c1, c2, ...
atunci, toate cartitele se opresc si se formeaza o galerie de lungime l1+l2+...+lk.
1 #include <fstream>
2 #include <iostream>
3 #include <set>
4
5 using namespace std;
6
7 ifstream f("galerie.in");
8 ofstream g("galerie.out");
9
10 int n,m,t,k,x,i,pas,inou,jnou,a[205][205],
11 di[]={-1,0,1,0},dj[]={0,1,0,-1},sapa_cineva;
12
13 struct cartita{int i,j,l,di,dj;}C[1000];
14
15 set<int> s;
16 set<int> sterse;
17 set<int>::iterator it;
18
19 set<int>::iterator it1;
20
21 int interior(int i, int j)
22 { if(i*j==0)return 0;
23 if(i>n)return 0;
24 if(j>m)return 0;
25 return 1;
26 }
27
28 void uneste_galerii(int i,int j,int c1,int c2)
29 {
30 int k,i1,j1;
31
32 if(interior(i,j))
33 for(k=0;k<4;k++)
34 {
35 i1=i+di[k];
36 j1=j+dj[k];
CAPITOLUL 5. OJI 2016 70
37 if(a[i1][j1]==c1)
38 {
39 a[i1][j1]=c2;
40 uneste_galerii(i1,j1,c1,c2);
41 }
42 }
43 }
44
45 int main()
46 { f>>k>>n>>m>>t;
47
48 for(i=1;i<=t;i++)
49 {f>>x;
50 if(x<=m) {C[i].i=0;C[i].j=x;C[i].di=1;C[i].dj=0;}
51 else
52 if(x<=n+m) {C[i].i=x-m;C[i].j=m+1; C[i].di=0;C[i].dj=-1;}
53 else
54 if(x<=2*m+n){C[i].i=n+1;C[i].j=2*m+n+1-x;C[i].di=-1;C[i].dj=0;}
55 else {C[i].i=2*n+2*m+1-x;C[i].j=0;C[i].di=0;C[i].dj=1;}
56
57 s.insert(i);
58 }
59
60 for(i=1;i<=n;i++)
61 a[i][0]=a[i][m+1]=-1;
62 for(i=1;i<=m;i++)
63 a[0][i]=a[n+1][i]=-1;
64
65 while(!s.empty())
66 { sapa_cineva=0;
67 sterse.clear();
68
69 for(it=s.begin();it != s.end(); it++)
70 { i=*it;
71 inou=C[i].i+C[i].di;
72 jnou=C[i].j+C[i].dj;
73 x=a[inou][jnou];
74
75 if(x==0)
76 {
77 a[inou][jnou]=i;
78 C[i].l++;
79 C[i].i=inou;
80 C[i].j=jnou;
81 sapa_cineva=1;
82 }
83 else
84 { if(x!=-1)
85 {
86 uneste_galerii(inou,jnou,i,x);
87 C[x].l+=C[i].l;
88 if (x<i && a[inou+C[x].di][jnou+C[x].dj]!=x)
89 sterse.insert(x);
90 }
91
92 sterse.insert(i);
93 }
94 }
95
96 for(it=sterse.begin();it != sterse.end(); it++)
97 { i=*it;
98 if(s.count(i)!=0) s.erase(i);
99 }
100
101 if(sapa_cineva) pas++;
102 }
103
104 if(k==1)
105 g<<pas<<’\n’;
106 else
107 {
108 x=C[1].l;
109 for(i=2;i<=t;i++)
110 if(C[i].l>x)
111 x=C[i].l;
112 g<<x<<’\n’;
CAPITOLUL 5. OJI 2016 71
113 }
114
115 f.close();
116 g.close();
117 return 0;
118 }
1 #include <fstream>
2 using namespace std;
3
4 ifstream f("galerie.in");
5 ofstream g("galerie.out");
6
7 short n,m,t,k,x,i,j,pas,inou,jnou,a[205][205],s[805],
8 di[]={-1,0,1,0},dj[]={0,1,0,-1},sapa_cineva,nr_active,nr_sterse;
9
10 struct cartita{short i,j,l,di,dj;}C[805];
11
12 bool sterg[805];
13
14 int interior(int i, int j)
15 { if(i*j==0)return 0;
16 if(i>n)return 0;
17 if(j>m)return 0;
18 return 1;
19 }
20
21 void uneste_galerii(int i,int j,int c1,int c2)
22 {
23 int k,i1,j1;
24 if(interior(i,j))
25 for(k=0;k<4;k++)
26 {
27 i1=i+di[k];
28 j1=j+dj[k];
29 if(a[i1][j1]==c1)
30 {
31 a[i1][j1]=c2;
32 uneste_galerii(i1,j1,c1,c2);
33 }
34 }
35 }
36
37 int main()
38 {
39 f>>k>>n>>m>>t;
40
41 for(i=1;i<=t;i++)
42 {
43 f>>x;
44
45 if(x<=m)
46 {
47 C[i].i=0;
48 C[i].j=x;
49 C[i].di=1;
50 C[i].dj=0;
51 }
52 else
53 if(x<=n+m)
54 {
55 C[i].i=x-m;
56 C[i].j=m+1;
57 C[i].di=0;
58 C[i].dj=-1;
59 }
60 else
61 if(x<=2*m+n)
62 {
63 C[i].i=n+1;
64 C[i].j=2*m+n+1-x;
65 C[i].di=-1;
66 C[i].dj=0;
CAPITOLUL 5. OJI 2016 72
67 }
68 else
69 {
70 C[i].i=2*n+2*m+1-x;
71 C[i].j=0;
72 C[i].di=0;
73 C[i].dj=1;
74 }
75
76 s[i]=i;
77 }
78
79 for(i=1;i<=n;i++)
80 a[i][0]=a[i][m+1]=-1;
81 for(i=1;i<=m;i++)
82 a[0][i]=a[n+1][i]=-1;
83
84 nr_active=t;
85
86 while(nr_active)
87 {
88 sapa_cineva=0;
89 nr_sterse=0;
90
91 for(j=1;j<=nr_active;j++)
92 {
93 i=s[j];
94 inou=C[i].i+C[i].di;
95 jnou=C[i].j+C[i].dj;
96 x=a[inou][jnou];
97 if(x==0)
98 {
99 a[inou][jnou]=i;
100 C[i].l++;
101 C[i].i=inou;
102 C[i].j=jnou;
103 sapa_cineva=1;
104 }
105 else
106 {
107 if(x!=-1)
108 {
109 uneste_galerii(inou,jnou,i,x);
110 C[x].l+=C[i].l;
111 if (x<i && a[inou+C[x].di][jnou+C[x].dj]!=x)
112 sterg[x]=true;
113 }
114
115 sterg[i]=true;
116 }
117 }
118
119 j=0;
120 for(i=1;i<=nr_active;++i)
121 if(!sterg[s[i]])
122 s[++j]=s[i];
123
124 nr_active=j;
125 if(sapa_cineva)
126 pas++;
127 }
128
129 if(k==1)
130 g<<pas<<’\n’;
131 else
132 {
133 x=C[1].l;
134 for(i=2;i<=t;i++)
135 if(C[i].l>x)
136 x=C[i].l;
137 g<<x<<’\n’;
138 }
139
140 f.close();
141 g.close();
142 return 0;
CAPITOLUL 5. OJI 2016 73
143 }
Capitolul 6
OJI 2015
Cerinµe
Dat ind un num r natural N s se determine cel mai mic num r echilibrat, strict mai mare
decât N.
Date de intrare
Fi³ierul de intrare ech.in conµine pe prima linie num rul natural N .
Date de ie³ire
Fi³ierul de ie³ire ech.out va conµine o singur linie pe care va scris cel mai mic num r
echilibrat, strict mai mare decât N.
Restricµii ³i preciz ri
a Num rul N are cel mult 23 de cifre.
a Pentru teste valorând 40% din punctaj, N are cel mult 18 cifre.
Exemple
ech.in ech.out Explicaµii
99 110 1+0=1.
123133 123134 1+3+3=2+1+4.
Solutie 80 de puncte
74
CAPITOLUL 6. OJI 2015 75
sp[i]= suma cifrelor din pozitiile pare incepand cu cea mai semnificativa
cifra si terminand cu pozitia i.
Precalculam si cea mai mare suma cu care putem inlocui pozitiile impare
(numarul de cifre de 9) respectiv pare.
In cazul in care numarul are N cifre si sunt toate egale cu 9 si N este par
algoritmul se va opri la pozitia primei cifre zero din fata numarului.
Daca la o pozitie i am gasit cifra mai mica decat 9 determinam cea mai buna
inlocuire (cea mai mica cifra pentru care avem sanse la echilibru).
15 int rest();
16 int ech();
17 void citire();
18 void afisare();
19
20
21 int main()
22 {int r;
23 citire();
24 r=rest();
25 if (r) add(11-r);
26 else add(11);
27 while (!ech())
28 add(11);
29 afisare();
30 return 0;
31 }
32
33 void add(int x)
34 {int i, t=0, s;
35 nx[0]=x%10; nx[1]=x/10;
36 for (i=0; i<lg; i++)
37 {s=a[i]+nx[i]+t;
38 a[i]=s%10;
39 t=s/10;}
40 if (t+nx[i]) a[lg++]=t+nx[i];
41 }
42
43 int rest()
44 {int i, r=0;
45 for (i=lg-1; i>=0; i--)
46 {
47 r=r*10+a[i];
48 r=r%11;
49 }
50 return r;
51 }
52
53 int ech()
54 { int s1=0, s2=0;
55 for (int i=0; i<lg; i+=2)
56 s1+=a[i], s2+=a[i+1];
57 return s1==s2;
58 }
59
60 void citire()
61 {char c;
62 int st, dr, aux;
63 while (fin>>c)
64 a[lg++]=c-’0’;
65 //inversez a
66 for (st=0, dr=lg-1; st<dr; st++, dr--)
67 { aux=a[st]; a[st]=a[dr]; a[dr]=aux; }
68 }
69
70 void afisare()
71 {int i;
72 for (i=lg-1; i>=0; i--) fout<<a[i];
73 fout<<’\n’;
74 fout.close();
75 }
1 // Lucia Miron
2 // numerele echilibrate sunt divizibile cu 11,
3 // verific doar aceste numere
4
5 #include <fstream>
6
7 using namespace std;
8
9 ifstream fin("ech.in");
10 ofstream fout("ech.out");
11
CAPITOLUL 6. OJI 2015 77
12 int n,v[50],r;
13
14 void citire()
15 {
16 char ch;
17 int i,aux;
18 while(fin>>ch)
19 n++,v[n]=ch-’0’;
20 for(i=1;i<=n/2;i++)
21 aux=v[i],v[i]=v[n+1-i],v[n-i+1]=aux;
22 v[0]=n;
23 }
24
25 void aduna11(int r)
26 {
27 int i,t,aux;
28 t=r;
29 for(i=1;i<=v[0];i++)
30 {
31 aux=v[i]+t;
32 v[i]=aux%10;
33 t=aux/10;
34 }
35 if(t)v[++v[0]]=t;
36 }
37
38 int ech()
39 {
40 int i,sp=0,si=0;
41 for (i=1;i<=v[0];i++)
42 if(i%2)si+=v[i];
43 else sp+=v[i];
44 if(si==sp)return 1;
45 else return 0;
46 }
47
48 int rest11()
49 {
50 int i,r=0;
51 for(i=v[0];i>=1;i--)
52 r=(r*10+v[i])%11;
53 return r;
54 }
55
56 void afis()
57 {
58 int i;
59 for(i=v[0];i>=1;i--)
60 fout<<v[i];
61 fout<<’\n’;
62 }
63
64 int main()
65 {
66 citire();
67 r=rest11();
68
69 if(r)
70 aduna11(11-r);
71 else
72 aduna11(11);
73
74 while(!ech())
75 aduna11(11);
76
77 afis();
78 fout.close();
79 return 0;
80 }
4 #include<cstring>
5
6 #define Nmax 3000
7
8 using namespace std;
9
10 int n,i,j,s1,s2,nr,p;
11 char s[Nmax],S[Nmax];
12 int x[Nmax];
13
14 int cmp(const int a,const int b)
15 {
16 return s[a]<s[b];
17 }
18
19 void detp()
20 {
21 int i;
22 for (i=1;i<=n;i++)
23 if (s[i]>S[i])
24 {p=i; break;}
25 }
26
27 void solve()
28 {
29 int aux1,aux2;
30 if (s1>s2)
31 {
32 i=n; if (i%2==0) i++; s[n+1]=’0’;
33 while (s1-s2>s[i]-’0’+(9-s[i-1]+’0’))
34 {
35 s1-=(s[i]-’0’);
36 s[i]=’0’;
37 s2+=(9-s[i-1]+’0’);
38 s[i-1]=’9’;
39 i=i-2;
40 }
41
42 if (s[i]-’0’>s1-s2 && s1!=s2)
43 {
44 s[i]-=(s1-s2-1);
45 while (s[i-1]==’9’ &&i-1>0) i=i-2;
46 s[i-1]+=1;
47 }
48 else if (s1!=s2)
49 {
50 aux1=s[i]; aux2=i;
51 s1-=s[i]-’0’; s[i]=’0’;
52 if (s1-s2==0) s[i]=’1’,s1++;
53 i--;
54 while (s[i]+(s1-s2)>’9’ && i>0) i-=2;
55 s[i]+=(s1-s2);
56 if (i==0)
57 {
58 s[1]=’1’;
59 for (i=1;i<n;i++) s[i+1]=’0’;
60 s[++n]=’1’;
61 }
62 }
63 }
64
65 if (s2>s1)
66 {
67 i=n; if (i%2==1) i++;
68 swap(s1,s2); s[n+1]=’0’;
69 while (s1-s2>s[i]-’0’+(9-s[i-1]+’0’))
70 {
71 s1-=(s[i]-’0’);
72 s[i]=’0’;
73 s2+=(9-s[i-1]+’0’);
74 s[i-1]=’9’;
75 i=i-2;
76 }
77
78 if (s[i]-’0’>s1-s2 && s1!=s2)
79 {
CAPITOLUL 6. OJI 2015 79
80 s[i]-=(s1-s2-1);
81 while (s[i-1]==’9’ &&i-1>0) i=i-2;
82 s[i-1]+=1;
83 }
84 else if (s1!=s2)
85 {
86 aux1=s[i]; aux2=i;
87 s1-=s[i]-’0’; s[i]=’0’;
88 if (s1-s2==0) s[i]=’1’,s1++;
89 i--;
90 while (s[i]+(s1-s2)>’9’ && i>0) i-=2;
91 s[i]+=(s1-s2);
92 if (i==0)
93 {
94 s[1]=’1’;
95 for (i=1;i<n;i++) s[i+1]=’0’;
96 s[++n]=’1’;
97 }
98 }
99 }
100 }
101
102 int main()
103 {
104 freopen("ech.in","r",stdin);
105 freopen("ech.out","w",stdout);
106
107 gets(s+1);
108
109 n=strlen(s+1);
110 memcpy(S,s,sizeof(S));
111
112 for (i=1;i<=n;i++)
113 {
114 if (i%2==1) s1=s1+(s[i]-’0’);
115 else s2=s2+(s[i]-’0’);
116 }
117
118 solve();
119 detp();
120
121 if (!p)
122 {
123 i=n;
124 while (s[i]==’9’) i--;
125 if (i==0){
126 s[1]=’1’;
127 for (i=1;i<=n;i++) s[i+1]=’0’;
128 n++; s1=1; s2=0;}
129 else
130 {
131 s[i]++;
132 if (i%2==1) s1++; else s2++;
133 }
134 solve();
135 }
136
137 detp();
138
139 for (i=n;i>p;i--)
140 if (i%2==1) x[++x[0]]=i;
141
142 sort(x+1,x+x[0]+1,cmp);
143
144 for (i=p+1;i<=n;i++)
145 if (i%2==0)
146 {
147 nr=min(s[i],s[x[x[0]]]);
148 s[i]=s[i]-nr+’0’;
149 s[x[x[0]]]=s[x[x[0]]]-nr+’0’;
150 --x[0];
151 if (s[x[x[0]]]==’0’) break;
152 }
153
154 for (i=1;i<=n;i++)
155 printf("%c",s[i]);
CAPITOLUL 6. OJI 2015 80
156 return 0;
157 }
1 #include <fstream>
2
3 using namespace std;
4
5 ifstream f("ech.in");
6 ofstream g("ech.out");
7
8 int main()
9 {
10 char s[50],c;
11 int si=0, sp=0, i, x=0;
12
13 while(f>>c)if(c>=’0’ and c<=’9’) s[x++]=c;
14
15 x--;
16 for(i=0;i<=x;i++)
17 if(i%2)
18 sp+=s[i]-’0’;
19 else
20 si+=s[i]-’0’;
21
22 do
23 {
24 int ok=0;
25 for(i=x;i>=0 && !ok; i=i-1)
26 if(s[i]<’9’)
27 {
28 s[i]++;
29 ok++;
30 if(i%2)
31 sp++;
32 else
33 si++;
34 }
35 else
36 {
37 s[i]=’0’;
38 if(i%2)
39 sp-=9;
40 else
41 si-=9;
42 }
43
44 if(!ok)
45 {
46 si=1;sp=0;
47 s[0]=’1’;
48 s[x+1]=’0’;
49 x++;
50 }
51 } while(si!=sp);
52
53 for(i=0;i<=x;i++)
54 g<<s[i];
55 g<<’\n’;
56 g.close();
57 return 0;
58 }
9 };
10
11 numar next(numar a)
12 {
13 int i, s1, s2, s[2], t[2], i2, j, x, k;
14 a.v[a.n+1]=0;
15
16 s[0]=0;
17 s[1]=0;
18 for(i=1;i<=a.n+1;i++)
19 {
20 i2=i%2;//paritatea curenta; 1-i2 paritatea inversa celei curente
21 s[i2]=s[i2]+a.v[i];
22 }
23 t[0]=0;
24 t[1]=0;
25 for(i=1;i<=a.n+1;i++)
26 {
27 i2=i%2;
28 a.v[i-1]=0;
29 if(i>1)t[1-i2]=t[1-i2]+9;
30
31 s1=s[1-i2]; // suma cifrelor de pe pozitii > i
32 // cu alta paritate decat pozitia i (curenta)
33 s2=s[i2]-a.v[i]; // suma cifrelor de pe pozitii > i
34 // cu aceeasi paritate decat pozitia i
35 s[i2]=s2;//actualizez s[i2]
36
37 if(a.v[i]<9)//am gasit o cifra care poate fi crescuta;
38 {
39 if(s2+a.v[i]<s1)
40 {
41 if(s1>s2+9+t[i2])continue;//nu se poate face echilibrare
42 if(s2 + a.v[i]+1 + t[i2] >= s1)
43 {
44 j=1;
45 }
46 else
47 {
48 j=s1-(s2 + a.v[i] + t[i2]);
49 }
50 x=s1-(s2 + a.v[i]+j);
51 k=2-i2;
52 }
53 else
54 {
55 if(s2 + a.v[i]+1 > s1 + t[1-i2])
56 continue;//nu se poate face echilibrare
57 j=1;
58 x=(s2 + a.v[i]+1)-s1;
59 k=1+i2;
60 }
61
62 //construiesc numarul cautat
63 a.v[i]=a.v[i]+j;
64 while(k<=i-1)
65 {
66 if(x>=9)
67 {
68 a.v[k]=9;
69 }
70 else
71 {
72 a.v[k]=x;
73 }
74 x=x-a.v[k];
75 k=k+2;
76 }
77 break;
78 }
79 }
80 if(a.v[a.n+1]>0)a.n++;//a fost nevoie de o cifra in plus, cifra 1
81 return a;
82 }
83
84 int main()
CAPITOLUL 6. OJI 2015 82
85 {
86 char ch;
87 int aux,i;
88 numar a, b;
89
90 ifstream fin("ech.in");
91 ofstream fout("ech.out");
92
93 a.n=0;
94 while(fin>>ch)
95 {
96 if(ch>=’0’ && ch<=’9’)
97 {
98 a.n++;
99 a.v[a.n]=ch-48;
100 }
101 }
102
103 for(i=1;i<=a.n/2;i++)
104 {
105 aux=a.v[i];
106 a.v[i]=a.v[a.n+1-i];
107 a.v[a.n+1-i]=aux;
108 }
109 b=next(a);
110 for(i=b.n;i>=1;i--)
111 {
112 fout<<b.v[i];
113 }
114 fout<<’\n’;
115
116 fout.close();
117 fin.close();
118
119 return 0;
120 }
Cerinµe
Cunoscând conguraµia terenului ³i amplasarea laserelor, s se rezolve una dintre urm toarele
dou cerinµe:
1. s se determine num rul de gropi din teren, dup executarea tragerilor;
2. s se determine num rul de tran³ee existente, dup executarea tragerilor.
Date de intrare
Fi³ierul de intrare lasere.in conµine pe prima linie un num r natural c care reprezint cerinµa ce
urmeaz s e rezolvat (1 sau 2). Pe a doua linie se a dou numere naturale n ³i m, reprezentând
num rul de linii ³i de coloane ale matricei, respectiv num rul de lasere. Pe urm toarele n linii
CAPITOLUL 6. OJI 2015 83
se a câte n numere naturale, reprezentând elementele matricei. Pe urm toarele m linii sunt
descrise cele m lasere, câte un laser pe o linie. Pe o linie care descrie un laser se a 3 numere
naturale i j d, cu semnicaµia c se a un laser pe linia i ³i coloana j (1 & i, j & n), care trage
în direcµia d (1 & d & 4). Valorile situate pe aceea³i linie sunt separate prin spaµiu.
Date de ie³ire
Fi³ierul de ie³ire lasere.out va conµine pe prima linie un singur num r natural. Acest num r
reprezint num rul de gropi (dac c 1) sau num rul de tran³ee (dac c 2).
Restricµii ³i preciz ri
a 4 & n & 200
a 1 & m & 200
a Numerotarea liniilor ³i a coloanelor este de la 1 la n.
a Elementele matricei din ³ierul de intrare sunt numere naturale de maxim 4 cifre.
a Poziµiile laserelor sunt distincte.
a Pentru teste valorând 30% din punctaj cerinµa este 1.
Exemple
lasere.in lasere.out Explicaµii
1 6 Dup ce acµioneaz laserele terenul arat astfel:
5 3 1 1 3 4 4
1 1 3 4 5 8 7 6 5 4
8 6 5
7 4 9 3 4 6 7
9 5 6
3 7 0 0 -1 9 8
1 1 1 9 8 1 1 0 5 6
1 1 1 5 6 Exist 6 gropi ³i o tran³ee.
2 3 3 Se num ra gropile chiar dac fac parte dintr-o tran³ee.
4 4 4
1 4 2
2 1 Dup ce acµioneaz laserele terenul arat astfel:
5 3 1 1 3 4 4
1 1 3 4 5 8 7 6 5 4
8 6 5
7 4 9 3 4 6 7
9 5 6
3 7 0 0 -1 9 8
1 1 1 9 8 1 1 0 5 6
1 1 1 5 6 Exist 6 gropi ³i o tran³ee.
2 3 3 Se num ra gropile chiar dac fac parte dintr-o tran³ee.
4 4 4
1 4 2
Autor: prof. Nicu Vad Laurentiu, Liceul Teoretic Mihail Kogalniceanu Vaslui
Varianta 1 -100p
66 int main()
67 {
68 fin>>cerinta;
69 fin>>n>>m;
70 int max=0;
71 for(i=1;i<=n;i++)
72 for(j=1;j<=n;j++)
73 {fin>>a[i][j];if(a[i][j]>max) max=a[i][j];}
74 max++;
75 for(i=0;i<=n+1;i++){a[0][i]=max;a[n+1][i]=max;a[i][0]=max;a[i][n+1]=max;}
76
77 for(i=1;i<=m;i++)
78 {
79 fin>>x>>y>>d;
80 if(d==1) N(x,y);
81 else if(d==2) E(x,y);
82 else if(d==3) S(x,y);
83 else V(x,y);
84 }
85 fin.close();
86
87 int nrT=0,nrG=0;
88
89 if(cerinta==1)
90 {
91 for(i=1;i<=n;i++)
92 for(j=1;j<=n;j++)
93 if(groapa(i,j))nrG++;
94 fout<<nrG<<’\n’;
95 }
96 else
97 {
98 for(i=1;i<=n;i++) nrT+=transee(i);
99 fout<<nrT<<’\n’;
100 }
101 fout.close();
102 return 0;
103 }
35 {
36 fin>>lin>>col>>d;
37 trage(lin,col,d);
38 }
39
40 gropi=cauta_gropi();
41 /*for (i=1; i<=n; i++)
42 {for (j=1; j<=n; j++) fout<<G[i][j]<<’ ’;
43 fout<<’\n’;}
44 */
45 if (c==1)
46 fout<<gropi<<’\n’;
47 else
48 fout<<cauta_transee()<<’\n’;
49 fout.close();
50 return 0;
51 }
52
53 bool este_groapa(int lin, int col)
54 { int k;
55 for (k=1; k<=8; k++)
56 if (T[lin+dl[k]][col+dc[k]]<T[lin][col]) return 0;
57 return 1;
58 }
59
60 int cauta_gropi()
61 {int i, j, nr=0;
62 for (i=1; i<=n; i++)
63 for (j=1; j<=n; j++)
64 if (este_groapa(i, j))
65 {
66 nr++; G[i][j]=1;
67 }
68 return nr;
69 }
70
71 void bordare()
72 {int i;
73 for (i=0; i<=n+1; i++)
74 T[0][i]=T[i][0]=T[n+1][i]=T[i][n+1]=INF;
75 }
76
77 void trage(int lin, int col, int d)
78 {
79 do
80 {
81 lin+=dl[d]; col+=dc[d];
82 if (T[lin][col]==INF) return;
83 T[lin][col]--;
84 }
85 while (1);
86 }
87
88 int cauta_transee()
89 {int i, j, nr=0, lg;
90 for (i=1; i<=n; i++)
91 for (j=1; j<=n+1; j++)
92 if (G[i][j])
93 if (!G[i][j-1]) //incepe o transee
94 lg=1;
95 else
96 lg++;
97 else
98 if (G[i][j-1]) //se termina o transee
99 if (lg>1) nr++;
100 return nr;
101 }
6 ifstream fin("lasere.in");
7 ofstream fout("lasere.out");
8
9 struct el
10 {
11 int v,g;
12 } a[202][202];
13
14 int dx[]={-1,-1,0,1,1,1,0,-1};
15 int dy[]={0,1,1,1,0,-1,-1,-1};
16 int n,m,i,j,k,nrg,nrt,c,l;
17
18 void bordare()
19 {
20 int i;
21 for(i=0;i<=n+1;i++)
22 a[i][0].v=a[i][n+1].v=10000;
23 for(i=0;i<=n+1;i++)
24 a[0][i].v=a[n+1][i].v=10000;
25 }
26
27 int groapa(int i,int j)
28 {
29 int k;
30 for(k=0;k<8;k++)
31 if(a[i+dx[k]][j+dy[k]].v<a[i][j].v)
32 return 0;
33 return 1;
34 }
35
36 void citire()
37 {
38 int i,j,k,x,y,d;
39 fin>>c;
40 fin>>n>>m;
41 for(i=1;i<=n;i++)
42 for(j=1;j<=n;j++)
43 fin>>a[i][j].v;
44 for(i=1;i<=m;i++)
45 {
46 fin>>x>>y>>d;
47 if(d==1)
48 for(j=x-1;j>=1;j--)
49 a[j][y].v--;
50 if(d==2)
51 for(j=y+1;j<=n;j++)
52 a[x][j].v--;
53 if(d==3)
54 for(j=x+1;j<=n;j++)
55 a[j][y].v--;
56 if(d==4)
57 for(j=y-1;j>=1;j--)
58 a[x][j].v--;
59 }
60 }
61
62 int main()
63 {
64 citire();
65 bordare();
66 for(i=1;i<=n;i++)
67 for(j=1;j<=n;j++)
68 if(groapa(i,j)==1)
69 {
70 nrg++;
71 a[i][j].g=1;
72 }
73 if(c==1)fout<<nrg<<’\n’;
74 else
75 {
76 for(i=1;i<=n;i++)
77 {
78 l=0;
79 for(j=1;j<=n;j++)
80 if(a[i][j].g==1)l++;
81 else
CAPITOLUL 6. OJI 2015 88
82 {
83 if(l>=2)nrt++;
84 l=0;
85 }
86 if(l>=2)nrt++;
87 }
88 fout<<nrt<<’\n’;
89 }
90 return 0;
91 }
1 //Nicu Vlad Laurentiu - Liceul Teoretic "Mihail Kogalniceanu" Vaslui 100 puncte
2 #include <fstream>
3
4 #define N 204
5 #define INF 10000
6 #define M 10000
7
8 using namespace std;
9
10 ifstream cin("lasere.in");
11 ofstream cout("lasere.out");
12
13 struct laser
14 {
15 int x,y,dir;
16 } X[N];
17
18 int A[N][N],n,m, i,j,k, B[M],nr=0,tr,p1,p2,s,cer;
19 int dx[8]={-1,-1,-1,0,1,1,1,0};
20 int dy[8]={-1,0,1,1,1,0,-1,-1};
21
22 int main()
23 {
24 cin>>cer;
25 cin>>n>>m;
26 for(i=1; i<=n; i++)
27 for(j=1; j<=n; j++) cin>>A[i][j];
28 for(i=0;i<=n+1;i++) A[0][i]=A[i][0]=A[i][n+1]=A[n+1][i]=INF;
29
30 for(k=0; k<m; k++)
31 {
32 cin>>X[k].x>>X[k].y>>X[k].dir;
33 if(X[k].dir==1)for(i=X[k].x-1; i>=1; i--) A[i][X[k].y]--;
34 else if(X[k].dir==2)for(i=X[k].y+1; i<=n; i++) A[X[k].x][i]--;
35 else if(X[k].dir==3)for(i=X[k].x+1; i<=n; i++) A[i][X[k].y]--;
36 else if(X[k].dir==4)for(i=X[k].y-1; i>=1; i--) A[X[k].x][i]--;
37 }
38 tr=0;
39 for(i=1;i<=n;i++)
40 {
41 for(j=1;j<=n;j++)
42 {
43 int ok=1;
44 for(int l=0;l<8 && ok;l++)
45 if(A[i][j]>A[i+dx[l]][j+dy[l]])ok=0;
46 if(ok==1){ B[j]=1; nr++;}
47
48 }
49 p1=0;
50 for(s=1;s<n;)
51 if(B[s]==1)
52 {
53 p1=s;
54 while(B[s]) s++;
55 if(s-p1>=2)tr++;
56 }
57 else s++;
58
59 for(s=1;s<=n;s++){ B[s]=0;}
60 }
61 if(cer==1)cout<<nr<<"\n";
62 else cout<<tr<<"\n";
CAPITOLUL 6. OJI 2015 89
60 a[li][j]--;
61 }
62 break;
63 }
64 case 2 :
65 {
66 for(j=co+1;j<=n;j++)
67 {
68 a[li][j]--;
69 }
70 break;
71 }
72 }
73 }
74
75 nrg=0;
76 for(i=1;i<=n;i++)
77 {
78 for(j=1;j<=n;j++)
79 {
80 c=0;
81 for(k=0;k<=7;k++)
82 {
83 li=i+dl[k];
84 co=j+dc[k];
85 if(a[li][co]<a[i][j])
86 {
87 c++;
88 break;
89 }
90 }
91 if(c==0)
92 {
93 nrg++;
94 b[i][j]=1;
95 }
96 else
97 {
98 b[i][j]=0;
99 }
100 }
101 }
102
103 nrt=0;
104 for(i=1;i<=n;i++)
105 {
106 for(j=0;j<=n-2;j++)
107 {
108 if(b[i][j]==0 && b[i][j+1]==1 && b[i][j+2]==1)
109 {
110 nrt++;
111 }
112 }
113 }
114
115 if(caz==1)
116 fout<<nrg;
117 else
118 fout<<nrt;
119
120 fout.close();
121 fin.close();
122 return 0;
123 }
Capitolul 7
OJI 2014
Cerinµe
Scrieµi un program care s determine:
a) Num rul stelelelor str lucitoare;
b) Num rul constelaµiilor p trate;
c) Lungimea laturii p tratului care reprezint cea mai mare constelaµie p trat .
Date de intrare
Din ³ierul patrat.in se citesc de pe prima linie, dou numere naturale N ³i M, separate
printr-un spaµiu, reprezentând dimensiunile tabloului bidimensional, iar de pe urm toarele N
linii, câte M numere naturale separate prin câte un spaµiu, reprezentând intensitatea luminoas
a stelelor.
Date de ie³ire
În ³ierul patrat.out se va scrie pe prima linie un num r natural reprezentând r spunsul la
cerinµa a). Pe cea de-a doua linie se va scrie un num r natural reprezentând r spunsul la cerinµa
b). Pe a treia linie se va scrie un num r natural reprezentând r spunsul la cerinµa c).
Restricµii ³i preciz ri
a 1 $ N & 200
a 1 $ M & 200
a 1 & intensitatea unei stele & 1000
a pentru rezolvarea corect a cerinµei a) se acord 40% din punctajul ec rui test, pentru
rezolvarea corect a cerinµei b) se acord 40% din punctajul ec rui test iar pentru rezolvarea
corect a cerinµei c) se acord 20% din punctajul ec rui test.
a Respectaµi formatul ³ierului de ie³ire! Pentru a obµine punctajul acordat unei cerinµe,
trebuie ca r spunsul din ³ier s e corect ³i scris exact pe linia precizat în enunµ.
92
CAPITOLUL 7. OJI 2014 93
Exemple
patrat.in patrat.out Explicaµii
6 8 11 În tabloul bidimensional cu 6 linii ³i 8 coloane exist 11 stele
1 8571634 3 str lucitoare. Tabloul conµine 3 constelaµii p trate iar cea mai
1 2 3 1 1 5 2 1 5 mare are latura p tratului de lungime 5.
1 7191181
6 3 5 1 6 4 3 1
1 9571821
1 5 6 5 3 1 3 6
2 3 0 În tabloul bidimensional cu 2 linii ³i 3 coloane nu exist nicio
1 1 1 0 stea str lucitoare. Tabloul conµine 0 constelaµii p trate iar cea
1 1 1 0 mai mare are latura p tratului este de dimensiune 0.
Definesc un tip structurat stea cu doua campuri pentru a retine atat intesitatea
luminoasa cat si pentru a memora faptul ca o stea este stralucitoare sau nu.
Definesc o matrice de tipul structurat stea in care se citesc datele de intrare.
Parcurg matricea si pentru fiecare element verific daca valoarea lui este mai
mica decat valorile continute in cele 8 elemente vecine. In cazul in care
conditia este indeplinita, am gasit o stea stralucitoare si o contorizez.
i-1,j-1 i-1,j i-1,j+1
i,j-1 i,j i,j+1
i+1,j-1 i+1,j i+1,j
Daca exista, notam cu k distanta dintre cele doua stele si verific daca la
distante egale cu k de cele doua stele (dar aceasta distanta nu trebuie sa
depaseasca marginea tabloului), se gasesc alte doua stele stralucitoare,
de-a lungul coloanelor pe care se afla stelele A si B, fie acestea C si D.
Retin latura patratului determinat daca aceasta este cea mai mare pana in
acest moment.
1 #include <cstdio>
2 #include <algorithm>
3 #include <cassert>
4
5 #define MAXN 210
6
7 using namespace std;
8
9 int N, M, K, nr, nrct=0, nrst=0,x,j, Lmax=0, L, Lm, k,lat, y, c, i, l, d;
10 int dx[8]= {0,0,1,1,1,-1,-1,-1};
11 int dy[8]= {1,-1,1,-1,0,1,-1,0};
12
13 int A[MAXN][MAXN];
14 bool B[MAXN][MAXN], ok;
15
16 int main()
17 {
18 freopen("patrat.in","r",stdin);
19 freopen("patrat.out","w",stdout);
20
21 scanf("%d %d\n",&N, &M);
22 assert(N>=2 && N<=200 && M>=2 && M<=200);
23
24 for(i=1; i<=N; i++)
25 for(j=1; j<=M; j++)
26 {
27 scanf("%d",&A[i][j]);
28 assert(A[i][j]>=1 && A[i][j]<=1000);
29 }
30
31 for(i=1; i<=N; i++)
32 for(j=1; j<=M; j++)
33 {
34 Lm=0;
35 for(k=0; k<8; k++)
36 {
37 l=i+dx[k];
38 c=j+dy[k];
39 if(A[l][c]>Lm) Lm=A[l][c];
40 }
41 if(A[i][j]>Lm)
42 {
43 nrst++;
44 B[i][j]=true;
45 }
46 }
47
48 printf("%d\n", nrst);
49 for(i=1; i<=N; i++)
50 for(j=1; j<=M; j++)
51 if(B[i][j])
52 {
53 L=min(N - i + 1, M - j + 1);
54 for(d=L; d>1 ; d--)
55 if(B[i][j + d - 1] &&
56 B[i + d - 1][j] &&
57 B[i + d - 1][j + d - 1])
58 {
59 nrct++;
60 Lmax=(Lmax<d?d:Lmax);
61 }
62 }
63
64 printf("%d\n%d\n", nrct, Lmax);
65 return 0;
66 }
1 #include <fstream>
2
3 using namespace std;
4
CAPITOLUL 7. OJI 2014 95
5 ifstream f("patrat.in");
6 ofstream g("patrat.out");
7
8 int a[203][203],n,m,sf;
9
10 struct stea
11 {
12 int x,y;
13 } v[4000];
14
15 int vecini(int x,int y)
16 {
17 if(x-1>0 &&y-1>0 && a[x][y]<=a[x-1][y-1]) return 0;
18 if(x-1>0&&a[x][y]<=a[x-1][y]) return 0;
19 if(x-1>0 && y+1<=m && a[x][y]<=a[x-1][y+1])return 0;
20 if(y-1>0 && a[x][y]<=a[x][y-1]) return 0;
21 if(y+1<=m &&a[x][y]<=a[x][y+1]) return 0;
22 if(x+1<=n&&y-1>0 &&a[x][y]<=a[x+1][y-1]) return 0;
23 if(x+1<=n && a[x][y]<=a[x+1][y]) return 0;
24 if(x+1<=n && y+1<=m &&a[x][y]<=a[x+1][y+1]) return 0;
25 return 1;
26 }
27
28 int parcurg()
29 {int i,j,nr=0;
30 for(i=1;i<=n;i++)
31 for(j=1;j<=m;j++)
32 if(vecini(i,j)!=0)
33 {
34 nr++;++sf;
35 v[sf].x=i;v[sf].y=j;
36 }
37 return nr;
38 }
39
40 void constelatie(int &nr, int &max)
41 {
42 int poz1=1,k,lg,ok1,ok,poz2;
43
44 while(poz1+3<=sf)
45 {
46 poz2=sf;
47 while(poz2-3>=poz1)
48 {
49 lg=v[poz2].x-v[poz1].x;
50 if(v[poz2].y-v[poz1].y==lg)
51 {
52 k=poz1+1;
53 ok=0;
54 while (v[k].x==v[poz1].x)
55 {if(v[k].y==v[poz1].y+lg) ok=1; k++;}
56
57 if(ok)
58 {
59 k=poz2-1;ok1=0;
60 while(v[k].x==v[poz2].x)
61 {if(v[k].y+lg==v[poz2].y)
62 ok1=1;k--;
63 }
64
65 if(ok1)
66 {
67 nr++;
68 if(max<lg)
69 max=lg;
70 }
71 }
72 }
73
74 poz2--;
75 }
76 poz1++;
77 }
78 }
79
80 int main()
CAPITOLUL 7. OJI 2014 96
81 { int i,j,nr=0,p=0,max=0;
82 f>>n>>m;
83 //for(k=1;k<n/3;k++)
84 //{
85 for(i=1;i<=n;i++)
86 for(j=1;j<=m;j++)
87 f>>a[i][j];
88 nr=nr+parcurg();
89 g<<nr<<’\n’;
90 constelatie(p,max);
91 g<<p<<’\n’<<max+1<<’\n’;
92 f.close();
93 g.close();
94
95 return 0;
96 }
1 //n^3
2 #include <fstream>
3 #include <iostream>
4
5 #define DIM 300
6 #define INF 1000000
7
8 using namespace std;
9
10 int di[] = {-1, 1,-1,1,0, 0,1,-1};
11 int dj[] = { 1,-1,-1,1,1,-1,0, 0};
12
13 int a[DIM][DIM];
14 int n, m, i, j, k, maxim, stele, patrate, ok, d, iv, jv, t;
15
16 int main()
17 {
18 ifstream fin("patrat.in");
19 ofstream fout("patrat.out");
20
21 fin>>n>>m;
22 for (i=1;i<=n;i++)
23 for (j=1;j<=m;j++)
24 fin>>a[i][j];
25
26 for (i=1;i<=n;i++)
27 for (j=1;j<=m;j++)
28 {
29 ok = 1;
30 for (d=0;d<=7;d++)
31 {
32 iv = i + di[d];
33 jv = j + dj[d];
34 if (a[iv][jv] >= a[i][j])
35 ok = 0;
36 }
37 stele+=ok;
38 if (ok == 1)
39 {
40 a[i][j] = INF;
41 //cout<<i<<" "<<j<<"\n";
42 }
43 }
44
45 for (i=1;i<n;i++)
46 for (j=i+1;j<=n;j++)
47 {
48 t = j-i;
49 for (k=1; k+t<=m; k++)
50 if (a[i][k] == INF &&
51 a[i][k+t] == INF &&
52 a[j][k] == INF &&
53 a[j][k+t] == INF)
54 {
55 patrate++;
56 if (t > maxim)
CAPITOLUL 7. OJI 2014 97
57 maxim = t;
58 }
59 }
60
61 fout<<stele<<"\n"<<patrate<<"\n"<<maxim+1;
62 return 0;
63 }
1 #include <iostream>
2 #include<stdio.h>
3 #include <fstream>
4
5 using namespace std;
6
7 ifstream f("patrat.in");
8 ofstream g("patrat.out");
9
10 struct stea{
11 int x;
12 char s;
13 };
14
15 int m,n,nrs,nrc,v[]={-1,-1,0,1,1,1,0,-1},w[]={0,1,1,1,0,-1,-1,-1};
16
17 stea t[202][202];
18
19 /* nrs-numar stele stralucitoare
20 nrc-numar constelatii patrate
21 v-modifica indicele de linie
22 w-modifica indicele de coloana
23 */
24
25 int main()
26 {
27 int k,sw,maxim=0; //maxim-retine latura celei mai mari constelatii
28 int i,j;
29
30 f>>m>>n;
31
32 for(i=1;i<=m;i++)
33 for(j=1;j<=n;j++)
34 f>>t[i][j].x;
35
36 for(i=1;i<=m;i++)
37 for(j=1;j<=n;j++)
38 {
39 sw=1;
40 for(k=0;k<8;k++) // verific cei 8 vecini
41 if(t[i][j].x<=t[i+v[k]][j+w[k]].x)
42 {
43 sw=0;
44 k=8;
45 }
46 if(sw)
47 {
48 nrs++; // numar stelele stralucitoare
49 t[i][j].s=1; // memorez steaua stralucitoare
50 }
51 }
52
53 g<<nrs<<’\n’;
54 for(i=1;i<=m;i++) // parcurg liniile
55 for(j=1;j<=n;j++) // parcurg coloanele
56 if(t[i][j].s==1)
57 { // daca gasesc o stea stralucitoare
58 for(k=1;k<=n-j;k++)//caut urmatoarea stea stalucitoare
59 if(t[i][j+k].s==1) //daca o gasesc
60 if(i+k<=m && t[i+k][j].s==1 && t[i+k][j+k].s==1)
61 {
62 // verific daca exista stele stralucitoare
63 // in celelalte doua colturi
64 nrc++;
65 if(k+1>maxim)
CAPITOLUL 7. OJI 2014 98
66 maxim=k+1;//retin maximum
67 }
68 }
69
70 g<<nrc<<’\n’<<maxim;
71 f.close();
72 g.close();
73 return 0;
74 }
1 #include <iostream>
2 #include <fstream>
3
4 using namespace std;
5
6 ifstream f("patrat.in");
7 ofstream g("patrat.out");
8
9 const int valmax=1001;
10
11 int a[210][210],m,n,ss=0,cp=0,lmax=1;
12 int dx[]={0,-1,-1,-1,0,1,1,1};
13 int dy[]={1,1,0,-1,-1,-1,0,1};
14
15 void citire()
16 {
17 int i,j;
18 f>>m>>n;
19 for(i=1;i<=m;i++)
20 for(j=1;j<=n;j++)
21 f>>a[i][j];
22
23 }
24
25 void afisare()
26 {
27 int i,j;
28
29 for(i=1;i<=m;i++)
30 {
31 for(j=1;j<=n;j++)
32 g<<a[i][j]<<’ ’;
33 g<<endl;
34 }
35 }
36
37 void stralucire()
38 {
39 int i,j,p,k;
40 for(i=1;i<=m;i++)
41 for(j=1;j<=n;j++)
42 {
43 p=0;
44 for(k=0;k<8;k++)
45 p=p+(a[i][j] > a[i+dx[k]][j+dy[k]]);
46
47 if(p==8)
48 a[i][j]=valmax,ss++;
49 }
50 }
51
52 void constelatie()
53 {
54 int i,j,k;
55 for(i=1;i<=m;i++)
56 for(j=1;j<=n;j++)
57 if(a[i][j]==valmax)
58 {
59 for(k=1;k<=n-j&&k<=m-i;k++)
60 if((a[i][j+k]==valmax)&&
61 (a[i+k][j]==valmax)&&
62 (a[i+k][j+k]==valmax))
63 {
CAPITOLUL 7. OJI 2014 99
64 cp++;
65 if(k+1>lmax)
66 lmax=k+1;
67 }
68 }
69 }
70
71 int main()
72 {
73 citire();
74 stralucire();
75 // afisare();
76 constelatie();
77 g<<ss<<’\n’;
78 g<<cp<<’\n’;
79 g<<lmax<<’\n’;
80 return 0;
81 }
Date de intrare
În ³ierul schi.in, pe prima linie este scris un num r natural, N reprezentând num rul de
concurenµi. Pe a doua linie a ³ierului sunt scrise cele N numere naturale separate prin câte un
spaµiu, reprezentând punctajele obµinute de ecare dintre cei N concurenµi, în ordinea în care
ace³tia au evoluat. Pe a treia linie a ³ierului este scris num rul natural K ce reprezint num rul
de întreb ri puse de ³ef. Pe a patra linie a ³ierului sunt scrise K numere naturale separate prin
câte un spaµiu, reprezentând valorile X ale punctajelor alese de ³eful comisiei de arbitri.
Date de ie³ire
În ³ierul schi.out se vor scrie K numere, separate prin câte un spaµiu, reprezentând, în
ordine, r spunsurile la cele K întreb ri.
Restricµii ³i preciz ri
a 1 & N & 100000
a 1 & K & 100000
a 0 & punctajele obµinute de concurenµi & 1000000000
a 0 & valorile X alese de ³eful arbitrilor & 1000000000
Exemple
CAPITOLUL 7. OJI 2014 100
-Pentru punctaj maxim, trebuie sa determinam atat prima cat si ultima pozitie
din P unde se gaseste valoarea X folosind algoritmul de cautarea binara.
Exista mai multe abordari prin care se pot obtine punctaje partiale:
1 #include <fstream>
2
3 #define DIM 100010
4
5 using namespace std;
6
7 int v[DIM];
8 int n, i, T, st, dr, x, q, maxim;
9
10 int cautMinim(int x);
11 int cautMaxim(int x);
CAPITOLUL 7. OJI 2014 101
12
13 int main()
14 {
15 ifstream fin("schi.in");
16 ofstream fout("schi.out");
17
18 fin>>n;
19
20 maxim = -1;
21 for (i=1;i<=n;i++)
22 {
23 fin>>x;
24 if (x > maxim)
25 maxim = x;
26 v[i] = maxim;
27 }
28
29 fin>>q;
30 for (i=1;i<=q;i++)
31 {
32 fin>>x;
33 st = cautMinim(x);
34 if (st == -1)
35 fout<<"0 ";
36 else
37 {
38 dr = cautMaxim(x);
39 fout<<dr-st+1<<" ";
40 }
41 }
42
43 return 0;
44 }
45
46
47 int cautMinim(int x)
48 {
49 int p = 1, u = n, mid;
50
51 while (p<=u)
52 {
53 mid = (p+u)/2;
54 if (x<=v[mid])
55 {
56 u = mid-1;
57 }
58 else
59 {
60 p = mid+1;
61 }
62 }
63
64 if (v[p] == x)
65 return p;
66 else
67 return -1;
68 }
69
70 int cautMaxim(int x)
71 {
72 int p = 1, u = n, mid;
73
74 while (p<=u)
75 {
76 mid = (p+u)/2;
77 if (x>=v[mid])
78 {
79 p = mid+1;
80 }
81 else
82 {
83 u = mid-1;
84 }
85 }
86
87 if (v[u] == x)
CAPITOLUL 7. OJI 2014 102
88 return u;
89 else
90 return -1;
91 }
1 #include <cstdio>
2 #include <cassert>
3
4 #define MAXN 100010
5
6 #include <cstring>
7
8 using namespace std;
9
10 int N, M, K, c, i, j, v, Q, x, p;
11
12 struct punct{int p, t;};
13
14 int A[MAXN];
15 punct C[MAXN];
16
17 int cb(int x)
18 {
19 int st, dr, m, poz;
20 st=1; dr=v; poz=0;
21 while (st<=dr && poz==0)
22 {
23 m=(st+dr)/2;
24 if(C[m].p==x)
25 poz=m;
26 else
27 if (C[m].p>x) dr=m-1; else st=m+1;
28 }
29 return poz;
30 }
31
32 int main()
33 {
34 freopen("schi.in","r",stdin);
35 freopen("schi.out","w",stdout);
36
37 scanf("%d\n",&N);
38 assert(N>=1 && N<=100000);
39
40 C[0].p=-1; v=0;
41 for(i=1; i<=N; i++)
42 {
43 scanf("%d",&A[i]);
44 assert(A[i]>=0 && A[i]<=1000000000);
45 if(C[v].p>=A[i])
46 C[v].t++;
47 else
48 {
49 C[++v].p=A[i]; C[v].t=1;
50 }
51 }
52
53 scanf("%d\n",&Q);
54 assert(Q>=1 && Q<=100000 );
55
56 for(i=1; i<=Q; i++)
57 {
58 scanf("%d",&x);
59 assert(x>=0 && x<=1000000000);
60 p=cb(x);
61 if (p==0)
62 printf("0 " );
63 else
64 printf("%d ", C[p].t);
65 }
66
67 printf("\n");
68 return 0;
CAPITOLUL 7. OJI 2014 103
69 }
1 #include <fstream>
2
3 using namespace std;
4
5 ifstream f("schi.in");
6 ofstream g("schi.out");
7
8 struct
9 {
10 int x,y;
11 } v[100003];
12
13 int p;
14
15 int caut(int val)
16 {
17 int in=1,sf=p,mij=(in+sf)/2;
18 while(in<=sf)
19 {
20 if(v[mij].x==val) return mij;
21 else if(v[mij].x<val) in=mij+1;
22 else sf=mij-1;
23 mij=(in+sf)/2;
24 }
25 return 0;
26 }
27
28 int main()
29 {
30 int n,i,a,j=1,b,m;
31 f>>n>>a;
32 v[1].x=a;
33 v[1].y=1;
34
35 for(i=2;i<=n;i++)
36 {
37 f>>a;
38 if(a<=v[j].x)
39 v[j].y++;
40 else
41 v[++j].x=a;
42 }
43
44 p=j;
45 f>>m;
46 for(i=1;i<=m;i++)
47 {
48 f>>a;
49 b=caut(a);
50 if(b==0)
51 g<<0<<’ ’;
52 else
53 {
54 if(a==v[1].x)
55 g<<v[b].y<<’ ’;
56 else
57 g<<v[b].y+1<<’ ’;
58 }
59
60 }
61
62 g<<’\n’;
63
64 f.close();
65 g.close();
66 return 0;
67 }
1 #include <fstream>
2
3 #define DIM 100010
4
5 using namespace std;
6
7 int v[DIM];
8 int n, q, i, x, maxim, nr, j;
9
10 int main()
11 {
12 ifstream fin("schi.in");
13 ofstream fout("schi.out");
14
15 fin>>n;
16 maxim = -1;
17 for (i=1;i<=n;i++)
18 {
19 fin>>x;
20 if (x > maxim)
21 maxim = x;
22 v[i] = maxim;
23 }
24
25 fin>>q;
26 for (i=1;i<=q;i++)
27 {
28 fin>>x;
29
30 nr = 0;
31 for (j=1;j<=n;j++)
32 {
33 if (v[j] > x)
34 break;
35 if (x == v[j])
36 {
37 nr++;
38 }
39 }
40 fout<<nr<<" ";
41 }
42
43 return 0;
44 }
1 #include <fstream>
2
3 #define DIM 100010
4
5 using namespace std;
6
7 int v[DIM];
8 int n, i, T, st, dr, x, q, maxim, mid;
9
10 int caut(int x);
11
12 int main()
13 {
14 ifstream fin("schi.in");
15 ofstream fout("schi.out");
16
17 fin>>n;
18 maxim = -1;
19 for (i=1;i<=n;i++)
20 {
21 fin>>x;
22 if (x > maxim)
23 maxim = x;
24 v[i] = maxim;
25 }
26
27 fin>>q;
28 for (i=1;i<=q;i++)
CAPITOLUL 7. OJI 2014 105
29 {
30 fin>>x;
31 mid = caut(x);
32 if (mid == -1)
33 fout<<"0 ";
34 else
35 {
36 st = mid;
37 while (v[st] == x)
38 st--;
39 st++;
40 dr = mid;
41 while (v[dr] == x)
42 dr++;
43 dr--;
44 fout<<dr-st+1<<" ";
45 }
46 }
47
48 return 0;
49 }
50
51 int caut(int x)
52 {
53 int p = 1, u = n, mid;
54
55 while (p<=u)
56 {
57 mid = (p+u)/2;
58 if (x==v[mid])
59 {
60 break;
61 }
62 else
63 {
64 if (x < v[mid])
65 u = mid-1;
66 else
67 p = mid+1;
68 }
69 }
70
71 if (p<=u)
72 return mid;
73 else
74 return -1;
75 }
1 #include <fstream>
2 #include <algorithm>
3
4 #define DIM 100010
5
6 using namespace std;
7
8 struct qry
9 {
10 int v;
11 int p;
12 int r;
13 };
14
15 struct punctaj
16 {
17 int v;
18 int nr;
19 };
20
21
22 int cmpv(const qry &a, const qry &b)
23 {
24 return a.v < b.v;
25 }
CAPITOLUL 7. OJI 2014 106
26
27 int cmpp(const qry &a, const qry &b)
28 {
29 return a.p < b.p;
30 }
31
32 qry w[DIM];
33 int v[DIM];
34 punctaj s[DIM];
35
36 int n, i, x, k, L, maxim, q, j;
37
38 int main()
39 {
40 ifstream fin("schi.in");
41 ofstream fout("schi.out");
42
43 fin>>n;
44 v[0] = -1;
45
46 for (i=1;i<=n;i++)
47 {
48 fin>>x;
49 if (x > maxim)
50 maxim = x;
51 v[i] = maxim;
52
53 if (i>1 && v[i] > v[i-1])
54 {
55 s[++k].v = v[i-1];
56 s[k].nr = L;
57 }
58
59 if (v[i] == v[i-1])
60 L++;
61 else
62 L=1;
63 }
64
65 s[++k].v = v[n];
66 s[k].nr = L;
67
68 fin>>q;
69 for (i=1;i<=q;i++)
70 {
71 fin>>x;
72 w[i].v = x;
73 w[i].p = i;
74 }
75
76 sort(w+1,w+q+1,cmpv);
77
78 i = 1;
79 j = 1;
80
81 while (i<=q && j<=k)
82 {
83 if (w[i].v == s[j].v)
84 {
85 w[i].r = s[j].nr;
86 i++;
87 }
88 else
89 if (w[i].v < s[j].v)
90 i++;
91 else
92 j++;
93 }
94
95 sort(w+1, w+q+1, cmpp);
96
97 for (i=1;i<=q;i++)
98 fout<<w[i].r<<" ";
99
100 return 0;
101 }
Capitolul 8
OJI 2013
6%4%2%1$3$5
Dup aceea Ana ³terge cele N elemente ale secvenµei ³i p streaz numai semnele, astfel:
%%%$$
La nal, Ana îi arat lui Bogdan ³irul semnelor ³i îi cere s reconstituie secvenµa de numere
naturale scris iniµial pe tabl .
Cerinµe
Cunoscând ³irul semnelor construit de Ana, scrieµi un program care s îl ajute pe Bogdan s
reconstituie secvenµa de numere naturale distincte scris iniµial pe tabl .
Date de intrare
Fi³ierul de intrare compar.in conµine pe prima linie o secvenµ de caractere din mulµimea
{'<', '>'}, reprezentând ³irul semnelor obµinut de Ana dup compararea elementelor vecine din
secvenµa iniµial .
Date de ie³ire
Fi³ierul de ie³ire compar.out va conµine pe prima linie num rul natural N, reprezentând
lungimea secvenµei iniµiale. Pe a doua linie vor scrise N numere naturale distincte cuprinse între
1 ³i N, separate prin câte un spaµiu, reprezentând elementele secvenµei iniµiale, reconstituit pe
baza semnelor din ³ierul de intrare.
Restricµii ³i preciz ri
a 1$N & 100000
a Dac exist mai multe soluµii, a³aµi oricare dintre acestea.
a Pentru determinarea corect a lungimii secvenµei se acord 10% din punctajul pe test.
Exemple
compar.in compar.out Explicaµii
> 6 6>4>2>1<3<5
6 4 2 1 3 5 Exist ³i alte soluµii posibile, aceasta este doar una dintre ele.
Parcurgem secventa de semne si daca semnul curent este < atunci scriu
valoarea curenta, apoi o incrementez.
Daca insa semnul curent este > identific intreaga subsecventa care urmeaza
formata numai din semnul >; sa consideram ca lg este lungimea secventei;
vom plasa valorile de la crt pana la crt+lg in ordine descrescatoare in
secventa reconstituita.
Obtinem intotdeauna cea mai mica solutie din punct de vedere lexicografic.
Se parcurge sirul.
20
21 for(int i=0;i<N;i++)
22 if(s[i]==’<’)
23 fout<<minn<<" ",minn++;
24 else
25 fout<<maxx<<" ",maxx--;
26
27 fout.close();
28 return 0;
29 }
Dac dou elemente vecine Ai , Ai1 (1 & i $ N ) au cel puµin o cifr comun , ele se pot unica.
Procedeul de unicare const în eliminarea din numerele Ai ³i Ai1 a tuturor cifrelor comune
³i ad ugarea prin alipire a num rului obµinut din Ai1 la num rul obµinut din Ai , formându-se
astfel un nou num r. Num rul Ai va înlocuit cu noul num r, iar num rul Ai1 va eliminat din
³ir. (De exemplu, numerele Ai 23814 ³i Ai1 40273 au cifrele 2, 3, 4 comune, dup unicare
obµinem Ai 817, iar Ai1 este eliminat; observaµi c dac dup eliminarea cifrelor comune,
numerele încep cu zerouri nesemnicative, acestea vor eliminate, apoi se realizeaz alipirea).
Dac în urma elimin rii cifrelor comune, unul dintre numere nu mai are cifre, atunci num rul
rezultat va avea cifrele r mase în cel lalt. Dac în urma elimin rii cifrelor comune atât Ai cât ³i
Ai1 nu mai au cifre, atunci ambele numere vor eliminate din ³ir, f r a înlocuite cu o alt
valoare.
Ordinea în care se fac unic rile în ³ir este important : la ecare pas se alege prima pereche de
elemente vecine Ai Ai1 care poate unicat , considerând ³irul parcurs de la stânga la dreapta.
(De exemplu, considerând Ai 123, Ai1 234, Ai2 235, se unic Ai cu Ai1 % Ai 14,
iar unicarea cu urm torul num r nu mai este posibil ).
Cerinµe
Cunoscându-se ³irul celor N numere naturale, s se determine:
a) cifra care apare cel mai frecvent în scrierea tuturor celor N numere; dac exist mai multe
cifre cu aceea³i frecvenµ de apariµie maxim , se va reµine cea mai mic cifr .
b) ³irul obµinut prin efectuarea unui num r maxim de unic ri, dup regulile descrise în enunµ.
Date de intrare
Fi³ierul de intrare unic.in conµine pe prima linie o valoare natural N , iar pe urm toarele
N linii, în ordine, cele N numere naturale din ³irul A, câte un num r pe o linie.
Date de ie³ire
Fi³ierul de ie³ire unic.out va conµine pe prima linie un num r natural c reprezentând cifra
care apare cel mai frecvent în scrierea celor N numere naturale. Pe cea de a doua linie un num r
natural Nr reprezentând num rul de numere naturale r mase în ³ir dup efectuarea unui num r
maxim de unic ri. Pe cea de a treia linie se vor scrie cele Nr numere naturale r mase, în ordinea
din ³ir, separate prin câte un spaµiu.
Dac în urma procedeului de unicare, toate numerele vor eliminate, ³ierul de ie³ire va
conµine o singur linie, pe care se va scrie cifra care apare cel mai frecvent în scrierea celor N
numere naturale.
Restricµii ³i preciz ri
a 1&N & 100000
a Numerele din ³irul iniµial, precum ³i numerele obµinute în urma unic rilor, nu vor dep ³i
1018
a Pentru datele de test ³irul obµinut în urma unic rilor este nevid.
a Pentru 30% dintre teste N & 1000
a Pentru 70% dintre teste numere naturale din ³ir au cifrele nenule.
a Pentru determinarea corect a primei cerinµe se acord 10% din punctajul pe test. Punctajul
integral se acord pe ambele cerinµe rezolvate corect.
Exemple
unic.in unic.out Explicaµii
10 3 Cifra care apare cel mai frecvent este 3 (de 6 ori).
6 2 Se unic : 47 cu 67 => 46. ³irul r mas: 6 46 40 123 231 1238 331 2035
47 0 837 50007
67 Se unic : 6 cu 46 => 4. ³irul r mas: 4 40 123 231 1238 331 2035 50007
40 Se unic : 4 cu 40 => 0. ³irul r mas: 0 123 231 1238 331 2035 50007
123 Se unic : 123 cu 231, ambele numere r mân f r cifre, deci vor
231 ambele eliminate.
1238 ³irul r mas: 0 1238 331 2035 50007
331 Se unic : 1238 cu 331 => 28. ³irul r mas: 0 28 2035 50007
2035 Se unic : 28 cu 2035 => 835. ³irul r mas: 0 835 50007
50007 Se unic : 835 cu 50007 => 837. ³irul r mas: 0 837.
CAPITOLUL 8. OJI 2013 111
Solutia propusa analizeaza secvential numerele inca din citirea din fisier.
a)
Pentru realizarea primei cerinta se construieste vectorul caracteristic al
cifrelor care apar in scrierea celor N numere naturale din sir.
b)
Trebuie avut in vedere ca prin unificarea lui A[i] cu A[i+1], numarul nou
obtinut in A[i] poate genera la randul lui posibile unificari cu numerele
anterior determinate A[i-1],A[i-2], ...
Citeste a[1]
i = 1,
Cat timp Not Eof() Executa
Citeste xa - valoarea curenta
Daca comun(a[i], xa)
Atunci
a[i] = unifica (a[i],xa);
10 ofstream fout("unific.out");
11
12 int n;
13 long long int a[NMAX], rez, vmax;
14 int nrc[10];
15 int cmax;
16 int c[10];//cifrele comune perechii curente
17
18 int comun(long long int x, long long int y);
19 int concat(long long int x, long long int y, long long int &rez);
20 void numara_cifre(long long int x);
21
22 int main()
23 {int i, ok, nr, maxim, cmax,ii;
24 for (i=vmax=1; i<=18; i++) vmax=vmax*10;
25
26 fin>>n;
27 assert(1<=n && n<=100000);
28
29 fin>>a[0]; nr=1;
30 numara_cifre(a[0]);
31 assert(a[0]<=vmax);
32
33 for (i=1; i<n; i++,nr++)
34 {fin>>a[nr]; assert(a[nr]<=vmax); assert(fin.good());
35 numara_cifre(a[nr]);
36 //fout<<i<<’ ’<<a[nr]<<": ";
37 while (nr>0 && comun(a[nr],a[nr-1]))
38 {
39 ok=concat(a[nr-1],a[nr], rez);
40 if (ok) {a[nr-1]=rez; nr--;}
41 else {nr-=2;}
42 }
43 //{for (ii=0; ii<=nr; ii++) fout<<a[ii]<<’ ’;fout<<’\n’;}
44 }
45
46 for (maxim=-1, i=0; i<10; i++) if (nrc[i]>maxim) {maxim=nrc[i]; cmax=i;}
47 fout<<cmax<<’\n’;
48 fout<<nr<<’\n’;
49
50 if (nr) {for (i=0; i<nr; i++) fout<<a[i]<<’ ’;fout<<’\n’;}
51 fout.close();
52 return 0;
53 }
54
55 int comun(long long int x, long long int y)
56 //returnez 1 daca x si y au cifre in comun
57 {int cy[10], i;
58 //c[i]=vectorul caracteristic al multimii cifrelor comune
59 for (i=0; i<10; i++) cy[i]=c[i]=0;
60 do{c[x%10]=1; x/=10;} while (x);
61 do {cy[y%10]=1; y/=10;} while(y);
62 for (i=0; i<10; i++) c[i]=c[i]&&cy[i];
63 for (i=0; i<10; i++) if (c[i]) return 1;
64 return 0;
65 }
66
67 int v[20];
68
69 int concat(long long int x, long long int y, long long int &rez)
70 //returneaza 0 daca dupa unificare rezultattul nu mai are cifre;
71 {
72 int lgrez=0, lg, i;
73 rez=0;
74 do {if (!c[x%10]) v[lgrez++]=x%10; x/=10;} while (x);
75 while (lgrez>1 && !v[lgrez-1]) {lgrez--;}
76 for (i=lgrez-1; i>=0; i--) rez=rez*10+v[i];
77 lg=0;
78 do {if (!c[y%10]) v[lg++]=y%10; y/=10;} while (y);
79 while (lg>1 && !v[lg-1]) {lg--;}
80 lgrez+=lg;
81 assert(lgrez<=18);
82 //lipesc cifrele din v la rez
83 for (i=lg-1; i>=0; i--) rez=rez*10+v[i];
84 return lgrez;
85 }
CAPITOLUL 8. OJI 2013 113
86
87 void numara_cifre(long long int x)
88 {if (!x) {nrc[0]++; return ;}
89 while (x) {nrc[x%10]++;x/=10;} }
1 /*
2 Solutie 100 p
3 prof. Eugen Nodea
4 */
5 # include <cstdio>
6
7 using namespace std;
8
9 int N, k, i, c;
10 long long a[100001], xa, x;
11 int ap[10];
12
13 // construire vect. frecventa de aparitii
14 void aparitii(long long x)
15 {
16 while(x > 0)
17 {
18 ap[x % 10]++;
19 x /= 10;
20 }
21 }
22
23 //verific daca doua valori vecine au cifre comune
24 inline int comun(long long x, long long y)
25 {
26 short c, uz[10];
27
28 for (c = 0; c <= 9; ++c)
29 uz[c]=0;
30
31 if (x == 0)
32 uz[0] = 1;
33 else
34 while (x > 0)
35 {
36 uz[x % 10] = 1;
37 x /= 10;
38 }
39
40 if (y == 0 && uz[0] == 1)
41 return 1;
42
43 while(y > 0)
44 {
45 c = y % 10; y /= 10;
46 if (uz[c]) return 1;
47 }
48
49 return 0;
50 }
51
52 //unific (y alipit la x)
53 inline long long unific (long long y, long long x)
54 {
55 short c, i = 0, uz[10], uc;
56 long long z, p;
57
58 for (c = 0; c <= 9; ++c)
59 uz[c]=0;
60
61 z = y;
62 if (z == 0)
63 uz[0] = 1;
64 else
65 while (z > 0)
66 {
67 uz[z % 10] = 1;
68 z /= 10;
CAPITOLUL 8. OJI 2013 114
69 }
70
71 z = x;
72 if (z == 0 && uz[0])
73 uz[0] = 2;
74 else
75 {
76 p = 1; x = 0;
77 while (z > 0)
78 {
79 c = z % 10;
80 if (uz[c] == 0)
81 {
82 x = x + c * p;
83 p *= 10;
84 }
85 else uz[c] = 2;
86 z /= 10;
87 }
88 }
89
90 if (y > 0)
91 {
92 z = y; p = 1; y = 0;
93 while (z > 0)
94 {
95 c = z % 10;
96 if (uz[c] == 1)
97 {
98 y = y + c * p;
99 p *= 10; ++i; uc = c;
100 }
101 z /= 10;
102 }
103 }
104
105 if (x * y > 0)
106 {
107 if (uc == 0) p /= 10;
108 return x * p + y;
109 }
110 else
111 {
112 if (x > 0)
113 {
114 if (i > 0) x *= 10;
115 return x;
116 }
117 else
118 {
119 if (i == 0) y = -1;
120 return y;
121 }
122 }
123 }
124
125 int main()
126 {
127 FILE * f = fopen("unific.in", "r");
128 FILE * g = fopen("unific.out", "w");
129
130 fscanf(f, "%d", &N);
131
132 //punem in vector primul numar
133 k = 1;
134 i = 1;
135 fscanf(f, "%lld", &a[k]); aparitii(a[k]);
136
137 while (i < N)
138 {
139 //citim valoarea curenta
140 fscanf(f, "%lld", &a[++k]); aparitii(a[k]);
141 ++i;
142
143 //unific cat timp pot
144 while(comun(a[k-1], a[k]) && k > 1)
CAPITOLUL 8. OJI 2013 115
145 {
146 x = unific(a[k], a[k-1]);
147 if (x == -1) k -= 2;
148 else a[k-1] = x, --k;
149 }
150 }
151
152 c = 0;
153 for (i = 1; i<=9; ++i)
154 if (ap[i] > ap[c]) c = i;
155
156 fprintf(g, "%d\n%d\n", c, k);
157 for (i=1; i<k; ++i)
158 fprintf(g, "%lld ", a[i]);
159 fprintf(g, "%lld\n", a[k]);
160
161 return 0;
162 }
Capitolul 9
OJI 2012
Date de intrare
Fi³ierul de intrare arme.in conµine pe prima linie numerele naturale N M, reprezentând
num rul de arme pe care le are la brâu, respectiv num rul de arme aate în camera armelor. Pe
a doua linie se a N numere naturale pb1 pb2 ...pbN reprezentând în ordine puterile armelor pe
care Vasile le are la brâu. Pe a treia linie se a M numere naturale pc1 pc2 ... pcM reprezentând
în ordine puterile armelor aate în camera armelor. Numerele scrise pe aceea³i linie sunt separate
prin spaµiu.
Date de ie³ire
Fi³ierul de ie³ire arme.out va conµine o singur linie pe care va scris suma maxim a
puterilor armelor de la brâul lui Vasile, dup efectuarea înlocuirilor.
Restricµii ³i preciz ri
a 1 & N, M & 1000
a Puterile armelor sunt numere naturale & 10000.
Exemple
arme.in arme.out
3 2 16
3 1 7
4 5
116
CAPITOLUL 9. OJI 2012 117
1 //Pintea Adrian
2 #include <iostream>
3 #include <fstream>
4
5 using namespace std;
6
7 ifstream fin("arme.in");
8 ofstream fout("arme.out");
9
10 int n,m,i,j,p[2001],aux,rezultat;
11
12 int main()
13 {
14 fin>>n>>m;
15 for(i=0;i<n;i++)
16 fin>>p[i];
17 for(i=n;i<n+m;i++)
18 fin>>p[i];
19
20 rezultat=0;
21 for(i=0;i<n;i++)
22 {
23 for(j=i+1;j<n+m;j++)
24 {
25 if (p[i]<p[j])
26 {
27 aux=p[i];
28 p[i]=p[j];
29 p[j]=aux;
30 }
31 }
32
33 rezultat+=p[i];
34 }
35
36 fout<<rezultat<<"\n";
37 fout.close();
38 return 0;
39 }
1 //Emanuela Cerchez
2 #include <fstream>
3
4 using namespace std;
5
6 #define InFile "arme.in"
7 #define OutFile "arme.out"
8 #define NMAX 1001
9
10 struct arma {short int nr, p;} b[NMAX], c[NMAX], mut[NMAX];
11 short int N, M, cate;
12 long int smax;
13
14 char T[10][10];
15 char s[100];
16
17 void citire();
18 void afisare();
19 void sortare(arma[], short int);
20 long int suma();
21
22 int main()
23 {
24 citire();
25 sortare(b,N);
26 sortare(c,M);
27 smax=suma();
CAPITOLUL 9. OJI 2012 119
28 afisare();
29 return 0;
30 }
31
32 void citire()
33 {
34 int i;
35 ifstream fin(InFile);
36 fin>>N>>M;
37 for (i=1; i<=N; i++)
38 {fin>>b[i].p; b[i].nr=i;}
39 for (i=1; i<=M; i++)
40 {fin>>c[i].p; c[i].nr=i;}
41 }
42
43 void sortare(arma b[NMAX], short int N)
44 {
45 short int i, sch;
46 arma aux;
47 do
48 {
49 sch=0;
50 for (i=1; i<N; i++)
51 if (b[i].p>b[i+1].p)
52 {aux=b[i]; b[i]=b[i+1]; b[i+1]=aux; sch=1;}
53 }while (sch);
54 }
55
56 long int suma()
57 {
58 short int i, j, aux;
59 long int s=0;
60 cate=0;
61 for (i=1, j=M; i<=N && j>0;i++, j--)
62 if (b[i].p<c[j].p)
63 {
64 aux=b[i].p; b[i].p=c[j].p; c[j].p=aux;
65 mut[cate].nr=i; mut[cate].p=j; cate++;
66 }
67 else
68 break;
69 for (i=1; i<=N; i++) s+=b[i].p;
70 return s;
71 }
72
73 void afisare()
74 {
75 int i;
76 ofstream fout(OutFile);
77 fout<<smax<<’\n’;
78 /*
79 fout<<cate<<’\n’;
80 for (i=0; i<cate; i++)
81 fout<<mut[i].nr<<’ ’<<mut[i].p<<’\n’;
82 */
83 fout.close();
84 }
1 //Marcu Ovidiu
2 #include<iostream>
3
4 using namespace std;
5
6 int a[1001],b[1001],m,n,i,j,s;
7
8 int cmp1(const void *p,const void *q)
9 {
10 int x=*(int *)p;
11 int y=*(int *)q;
12 //return x-y;
13 if(x>=y)
14 return +1;
15 else
CAPITOLUL 9. OJI 2012 120
16 return -1;
17 }
18
19 int cmp2(const void *p,const void *q)
20 {
21 int x=*(int *)p;
22 int y=*(int *)q;
23 //return x-y;
24 if(x>=y)
25 return -1;
26 else
27 return +1;
28 }
29
30 void afis(int x[1001],int k)
31 {
32 int j;
33 for(j=1;j<=k;j++)
34 cout<<x[j]<<" ";
35 cout<<endl;
36 }
37
38 int main()
39 {
40 freopen("arme.in","r",stdin);
41 freopen("arme.out","w",stdout);
42
43 cin>>n>>m;
44
45 for(i=1;i<=n;i++)
46 {
47 cin>>a[i];
48 s=s+a[i];
49 }
50
51 for(i=1;i<=m;i++)
52 cin>>b[i];
53
54 qsort(a+1,n,sizeof(a[0]),cmp1);//a crescator
55 qsort(b+1,m,sizeof(b[0]),cmp2);//b descrescator
56 //afis(a,n);afis(b,m);
57
58 int k=n;
59 if(m<n)
60 k=m;
61 i=1;
62 while(i<=k && a[i]<b[i])
63 {
64 s=s+(b[i]-a[i]);
65 i++;
66 }
67
68 cout<<s;
69 return 0;
70 }
Date de intrare
Fi³ierul de intrare triunghi.in conµine pe prima linie num rul natural n reprezentând num rul
de linii din triunghi. Pe urm toarele n linii sunt descrise informaµiile despre triunghi. Mai exact,
pe linia i (1 & i & n) dintre cele n se a dou numere naturale separate prin spaµiu pi vi indicând
poziµia ³i respectiv valoarea num rului cunoscut de pe linia i a triunghiului.
Date de ie³ire
Fi³ierul de ie³ire triunghi.out va conµine o singur linie, pe care se g sesc n numere naturale
separate prin câte un spaµiu, reprezentând în ordinea de la stânga la dreapta numerele scrise pe
linia 1 a triunghiului.
Restricµii ³i preciz ri
a 1 & n & 1000
a 1 & pi & n 1 i, pentru 1&i&n
a Toate numerele din triunghi sunt numere naturale cu cel mult 18 cifre.
a Pentru elevii care implementeaz în C: când utiliza³i MINGW, dac citiµi/a³aµi valori
de tip long long int folosind scanf(), respectiv printf() utilizaµi specicatorul de format %I64d.
Exemple
triunghi.in triunghi.out Explicaµii
5 1 2 3 4 2 Triunghiul este:
4 4
2 5
45
3 13
20 25
2 25
8 12 13
1 45
3 5 7 6
1 2 3 4 2
Apoi, cunoscand linia n-1 si unul dintre numerele de pe linia n-2 le putem afla
pe celelalte doua, tot prin scaderi etc.
Trebuie sa fim doar atenti cum facem scaderile: daca cunoastem numerele de pe
linia i: vi, 1, vi, 2,..., vi, n+1-i si de pe linia i+1 cunoastem valoarea
V=v[i+1,p], de pe pozitia p, calculam numerele de pe pozitiile p+1, p+2, ..
succesiv: vi+1, p+1=v[i,p]-v[i+1,p], vi+1, p+2=v[i,p+1]-vi+1, p+1 etc., iar
numerele de pe pozitiile anterioare p-1, p-2, ...1
la fel: vi+1,p-1=vi,p-1-vi,p, etc.
1 //Adrian Pintea
2 #include <fstream>
3 //#include <iostream>
4
5 using namespace std;
6
7 ifstream fin("triunghi.in");
8 ofstream fout("triunghi.out");
9
10 long long a[1001][1001],p[1001],x,i,j,n;
11
12 int citire()
13 {
14 fin >> n;
15 for (i=n;i>0;i--) { fin>>p[i]>>x; a[i][p[i]]=x;}
16 fin.close();
17
18 //for (i = 1; i <= n; i++)
19 //{
20 //for (j = 1; j <= i; j++)
21 //cout << a[i][j] << ’ ’;
22 //cout << ’\n’;
23 //}
24 return 0;
25 }
26
27 //matricea de sus in jos
28 int construire()
29 {
30 for (i = 2; i <= n; i++)
31 {
32 if(p[i]>1)
33 { for(j=p[i]-1;j>0;j--) a[i][j]=a[i-1][j]-a[i][j+1];
34 for(j=p[i];j<=i;j++) a[i][j]=a[i-1][j-1]-a[i][j-1];
35 } else for(j=p[i]+1;j<=i;j++) a[i][j]=a[i-1][j-1]-a[i][j-1];
36 }
37
38 //for (i = 1; i <= n; i++)
39 //{
40 //for (j = 1; j <= i; j++)
41 // cout << a[i][j] << ’ ’;
42 // cout << ’\n’;
43 // }
44
45 return 0;
46 }
47
48 int afisare()
49 {
50 for (j = 1; j <= n; j++)
51 fout << a[n][j] << ’ ’;
52 return 0;
CAPITOLUL 9. OJI 2012 123
53 }
54
55 int main()
56 {
57 citire();
58 construire();
59 afisare();
60 fout.close();
61 return 0;
62 }
63 afisare();
64 fout.close();
65 return 0;
66 }
1 //Nodea Eugen
2 # include <fstream>
3
4 using namespace std;
5
6 ifstream f("triunghi.in");
7 ofstream g("triunghi.out");
8
9 long long a[1001][1001], i, n, j, k, v[1001],p[1001];
10
11 int main()
12 {
13 f>>n;
14 for (i=n;i>0;--i)
15 {
16 f>>p[i]>>v[i];
17 }
18 a[1][1]=v[1];
19 for (i=2;i<=n;++i)
20 {
21 //refac linia i
22 j=p[i];
23 a[i][j]=v[i];
24 //refac stanga
25 k=j-1;
26 while (k)
27 {
28 a[i][k]=a[i-1][k]-a[i][k+1];
29 --k;
30 }
31 //refac dreapta
32 k=j+1;
33 while (k<=i)
34 {
35 a[i][k]=a[i-1][k-1]-a[i][k-1];
36 ++k;
37 }
38 }
39 // for (i=1;i<=n;++i)
40 // {
41 for (j=1;j<=n;++j)
42 g<<a[n][j]<<’ ’;
43 // g<<’\n’;
44 // }
45 return 0;
46 }
1 //Nodea Eugen
2 # include <fstream>
3
4 using namespace std;
5
6 ifstream f("triunghi.in");
7 ofstream g("triunghi.out");
8
9 long long a[1001][1001];
10 long long i, n, j, k, v[1001], p[1001];
11
12 int main()
13 {
14 f>>n;
15 for (i=n; i>0; --i)
16 {
17 f>>p[i]>>v[i];
18 }
CAPITOLUL 9. OJI 2012 125
19 a[1][1]=v[1];
20 for (i=2; i<=n; ++i)
21 {
22 //refac linia i
23 j=p[i];
24 a[i][j]=(long long)v[i];
25 //refac stanga
26 k=j-1;
27 while (k)
28 {
29 a[i][k]=a[i-1][k]-a[i][k+1];
30 --k;
31 }
32 //refac dreapta
33 k=j+1;
34 while (k<=i)
35 {
36 a[i][k]=a[i-1][k-1]-a[i][k-1];
37 ++k;
38 }
39 }
40
41 for (j=1; j<n; ++j)
42 g<<a[n][j]<<’ ’;
43 g<<a[n][n]<<’\n’;
44
45 return 0;
46 }
1 //nodea eugen
2 # include <fstream>
3
4 using namespace std;
5
6 ifstream f("triunghi.in");
7 ofstream g("triunghi.out");
8
9 long long L[2][1001];
10 long long i, n, j, k, v[1001], p[1001];
11
12 int main()
13 {
14 f>>n;
15 for (i=n; i>0; --i)
16 {
17 f>>p[i]>>v[i];
18 }
19 L[0][1]=v[1];
20 for (i=2; i<=n; ++i)
21 {
22 //refac linia i
23 j=p[i];
24 L[1][j]=(long long)v[i];
25
26 //refac stanga
27 k=j-1;
28 while (k)
29 {
30 L[1][k]=L[0][k]-L[1][k+1];
31 --k;
32 }
33
34 //refac dreapta
35 k=j+1;
36 while (k<=i)
37 {
38 L[1][k]=L[0][k-1]-L[1][k-1];
39 ++k;
40 }
41
42 //copiez linia
43 for (j=1; j<=i; ++j)
44 L[0][j]=L[1][j];
CAPITOLUL 9. OJI 2012 126
45 }
46
47 for (j=1; j<n; ++j)
48 g<<L[1][j]<<’ ’;
49 g<<L[1][n]<<’\n’;
50
51 return 0;
52 }
1 //Marcu Ovidiu
2 #include<iostream>
3 #include<iomanip>
4
5 using namespace std;
6
7 long long a[1001][1001],p,v,x[1001],m,n,i,j;
8
9 void citire()
10 {cin>>n;
11 for(i=n;i>=1;i--)
12 {cin>>p>>v;
13 x[i]=p;
14 // y[i]=v;
15 a[i][p]=v;
16 }
17 }
18
19 void sol()
20 {for(i=1;i<=n;i++)
21 { p=x[i];//a[i][p]are valoare
22 for(j=p+1;j<=i;j++) // completez la dreapta
23 a[i][j]=a[i-1][j-1]-a[i][j-1];
24 for(j=p-1;j>=1;j--)
25 a[i][j]=a[i-1][j]-a[i][j+1];
26 }
27 }
28
29 void afis()
30 {
31 unsigned int i;
32 for(i=1;i<=n;i++)
33 cout<<a[n][i]<<" ";
34 }
35
36 int main()
37 {freopen("triunghi.in","r",stdin);
38 freopen("triunghi.out","w",stdout);
39 citire();
40 sol();
41 afis();
42
43 return 0;
44 }
1 //Marcu Ovidiu
2 #include<iostream>
3 #include<iomanip>
4
5 using namespace std;
6
7 long long p,v,x[1001],y[1001],s1[1001],s2[1001],m,n,i,j;
8
9 void citire()
10 {cin>>n;
11 for(i=n;i>=1;i--)
12 {cin>>p>>v;
13 x[i]=p;
14 y[i]=v;
15 }
16 }
CAPITOLUL 9. OJI 2012 127
17
18 void sol()
19 { s1[x[1]]=y[1];
20 for(i=2;i<=n;i++)
21 { p=x[i];
22 v=y[i];
23 s2[p]=v;
24 for(j=p+1;j<=i;j++)
25 s2[j]=s1[j-1]-s2[j-1];
26 for(j=p-1;j>=1;j--)
27 s2[j]=s1[j]-s2[j+1];
28 for(j=1;j<=i;j++)
29 s1[j]=s2[j];
30 }
31 }
32
33 void afis()
34 {
35 int i;
36 for(i=1;i<=n;i++)
37 cout<<s1[i]<<" ";
38 cout<<endl;
39 }
40
41 int main()
42 {
43 freopen("triunghi.in","r",stdin);
44 freopen("triunghi.out","w",stdout);
45
46 citire();
47 sol();
48 afis();
49
50 return 0;
51 }
Capitolul 10
OJI 2011
Cerinµe
Scrieµi un program care cite³te m, n, elementele tabloului ³i a³eaz :
a) num rul de divizori pozitivi pentru grupa A, num rul de elemente din grup ³i cea mai
mare valoare din grup ;
b) num rul de divizori pozitivi pentru grupa B, num rul de elemente din grup ³i cea mai
mare valoare din grup ; în cazul în care nu exist grupa a doua, se va a³a de trei ori valoarea 0.
Date de intrare
Fi³ierul grupe.in conµine pe prima linie valorile lui m ³i n separate printr-un spaµiu, iar pe
celelalte m linii câte n elemente separate dou câte dou printr-un spaµiu, reprezentând elementele
tabloului.
Date de ie³ire
Fi³ierul grupe.out va conµine:
- pe prima linie valoarea num rului de divizori pozitivi din grupa A, num rul de elemente din
grupa A ³i cea mai mare valoare din grupa A, valori separate dou câte dou printr-un singur
spaµiu;
- pe a doua linie valoarea num rului de divizori pozitivi din grupa B, num rul de elemente
din grupa B ³i cea mai mare valoare din grupa B, valori separate dou câte dou printr-un singur
spaµiu.
Restricµii ³i preciz ri
- 0 $ m, n $ 101;
- elementele tabloului bidimensional iniµial sunt mai mici sau egale decât 100000 ³i mai mari
decât 1;
- o grup poate compus dintr-un singur element.
Se acord punctaje parµiale:
- 50% pentru a³area valorilor corecte pe prima linie din ³ierul grupe.out (cerinµa a));
- 50% pentru a³area valorilor corecte pe a doua linie din ³ierul grupe.out (cerinµa b)).
128
CAPITOLUL 10. OJI 2011 129
Exemple
grupe.in grupe.out Explicaµii
2 3 4 2 10 Num rul divizorilor pentru ecare element al tabloului: 5 divizori
16 2 4 2 2 5 (pentru valoarea 16), 2 divizori (pentru valoarea 2), 3 divizori (pentru
10 6 5 valoarea 4), 4 divizori (pentru valoarea 10), 4 divizori (pentru valoarea
6) ³i 2 divizori (pentru valoarea 5).
Se pot forma grupele: cu 2 divizori (elementele 2, 5), cu 4 divizori
(elementele 10,6), cu 3 divizori (elementul 4) ³i cu 5 divizori (elementul
16). Dup ordonarea descresc toare a grupelor, grupele cu cele mai
multe elemente sunt cele care conµin 2 elemente: (10, 6), respectiv
(2, 5). Pentru c elementele 10 ³i 6 au 4 divizori, ele vor face parte
din grupa A, iar 2 ³i 5, având doar 2 divizori ecare, vor face parte
din grupa B. Deci grupa A are 4 divizori, 2 elemente ³i cel mai mare
element din grup este 10, iar grupa B are 2 divizori, 2 elemente ³i cel
mai mare element din grup este 5.
2 3 4 3 15 Num rul divizorilor pentru ecare element al tabloului: 2 divizori
2 15 4 2 2 5 (pentru valoarea 2), 4 divizori (pentru valoarea 15), 3 divizori (pentru
10 6 5 valoarea 4), 4 divizori (pentru valoarea 10), 4 divizori (pentru valoarea
6) ³i 2 divizori (pentru valoarea 5). Dup ordonarea descresc toare a
grupelor, grupa cu cele mai multe elemente este cea format din ele-
mentele 10, 6, 15, ecare element având exact 4 divizori. Aceasta va
grupa A. Grupa B va cea format din dou elemente, celelalt grup
având un singur element. Deci grupa A are 4 divizori, 3 elemente ³i
cel mai mare element din grup este 15, iar grupa B are 2 divizori, 2
elemente ³i cel mai mare element din grup este 5.
Se poate opta pentru utilizarea a doua matrice de dimensiuni mai mici, in a doua
pastrandu-se numarul de divizori pozitivi pentru fiecare element, dar o astfel
de solutie nu va functiona pentru toate testele.
Sursele care nu verifica eficient numarul de divizori nu vor primi punctaj maxim.
1 #include <fstream>
2 #include <math.h>
3
4 using namespace std;
5
CAPITOLUL 10. OJI 2011 130
6 ifstream f("grupe.in");
7 ofstream g("grupe.out");
8
9 long int maxx[200], x[200];
10
11 long int nr_div(long int x)
12 {
13 long int i,nr=2;
14
15 for(i=2;i<=sqrt(x);i++)
16 if (x%i==0)
17 nr+=2;
18
19 if ((int)sqrt(x)==sqrt(x))
20 nr--;
21 return nr;
22 }
23
24 int main()
25 {
26 long int nr,i,max1,max2,poz1,poz2,n,m;
27 long int a;
28 f>>n>>m;
29
30 for(i=1;i<=n*m;i++)
31 {
32 f>>a;
33 nr=nr_div(a);
34 x[nr]++;
35 if (a>maxx[nr]) maxx[nr]=a;
36 }
37 f.close();
38
39 max1 = x[2];
40 poz1 = 2;
41 max2=0;
42 for(i=3;i<=200;i++)
43 if (x[i]>=max1)
44 {
45 max2 = max1;
46 poz2 = poz1;
47 max1 = x[i];
48 poz1 = i;
49 }
50 else
51 if (x[i]>=max2)
52 {
53 max2 = x[i];
54 poz2 = i;
55 }
56
57 g<<poz1<<" "<<x[poz1]<<" "<<maxx[poz1]<<endl;
58
59 if (max2==0)
60 g<<"0 0 0";
61 else
62 g<<poz2<<" "<<x[poz2]<<" "<<maxx[poz2];
63 g.close();
64
65 return 0;
66 }
Cerinµe
Scrieµi un program care cite³te num rul n de jetoane, cele n litere asociate jetoanelor, precum
³i codurile asociate literelor, în ordinea apariµiei lor ³i a³eaz :
a) num rul de perechi de litere consecutive din cuvântul iniµial care au proprietatea c o liter
este vocal ³i cealalt este consoan (ordinea lor nu conteaz );
b) num rul k1 , format din a³ezarea iniµial a jetoanelor;
c) suma k1 k2 ... kn .
Date de intrare
Fi³ierul de intrare litere.in va conµine pe prima linie valoarea lui n, reprezentând num rul de
jetoane, pe a doua linie un cuvânt format din n litere mari (de la 'A' la 'Z'); literele sunt scrise una
dup alta, f r s e separate cu spaµii, astfel încât prima liter este cea aat pe primul jeton, a
doua liter pe al doilea jeton ³.a.m.d. Pe a treia linie din ³ier se a un num r m ce reprezint
num rul de litere distincte, iar pe a patra linie m valori reprezentând codurile literelor distincte ce
apar în cuvânt. Codurile sunt date în ordinea apariµiei literelor în cuvânt ³i sunt numere naturale
nenule formate dintr-o singur cifr , separate printr-un spaµiu, pentru ecare liter codul ind dat
o singur dat , chiar dac litera se repet .
Date de ie³ire
Fi³ierul de ie³ire litere.out va conµine pe prima linie num rul de perechi de litere consecutive
din cuvânt care au proprietatea c o liter este vocal ³i cealalt consoan (ordinea lor nu conteaz ),
pe a doua linie num rul k1 , (format din a³ezarea iniµial a jetoanelor), iar pe a treia linie suma
k1 k2 ... kn .
Restricµii ³i preciz ri
- 0 $ n & 10000
- 0 $ m $ 27
Se acord punctaje parµiale:
- 20% pentru a³area valorii corecte pe prima linie din ³ierul rezultat (cerinµa a));
- 40% pentru a³area valorii corecte pe a doua linie din ³ierul rezultat (cerinµa b));
- 40% pentru a³area valorii corecte pe a treia linie din ³ierul rezultat (cerinµa c)).
Exemple
litere.in litere.out Explicaµii
3 0 Nu exist perechi de litere consecutive care s îndeplineasc cerinµa.
CSC 121 Sunt 2 litere distincte {'C', 'S'}, cod('C')=1, cod('S')=2. k1 121,
2 143 k2 21, k3 1, iar k1 k2 k3 143.
1 2
6 5 Exist 5 perechi de litere consecutive care s îndeplineasc cerinµa:
CABABE 256567 'CA', 'AB', 'BA', 'AB', 'BE'. Sunt 4 litere distincte {'C', 'A', 'B',
4 320342 'E'}, cod('C')=2, cod('A')=5, cod('B')=6, cod('E')=7. k1 256567,
2 5 6 7 k2 56567, k3 6567, k4 567, k5 67, k6 7, iar k1 k2 k3
k4 k5 k6 320342
inc=100;
for(i=0;i<n;i++) {
sum[inc+i]=(i+1)*cost[text[i]];
}
//deplasarea cifrelor daca este cazul
for(i=n-1;(i>0)||(sum[inc+i]>9);i--) {
sum[inc+i-1]+=sum[inc+i]/10;
sum[inc+i]%=10;
}
//scrierea rezultatelor in formatul cerut
1 //O(N)
2 #include <stdio.h>
3 #include <string.h>
4
5 char S[30002];
6 char c;
7 char *voc = "AEIOU";
8 long int a, N, C, k, j, i, T, aux;
9 char P[130], cod[130];
10 long int L[30];
11
12 int main()
13 {
14 FILE *f = fopen("litere.in","r");
15 FILE *g = fopen("litere.out","w");
16 fscanf(f,"%d",&N);
17 fscanf(f,"%s",S+1);
18
19 a = 0;
20 k = 0;
21 for (i=1;i<N;i++)
22 {
23 if ((strchr(voc, S[i]) && !strchr(voc, S[i+1])) ||
24 (!strchr(voc, S[i]) && strchr(voc, S[i+1])))
25 {
26 a++;
27 }
28 if (!P[S[i]])
29 P[S[i]] = ++k;
30 }
31 if (!P[S[N]])
32 P[S[N]] = ++k;
33 fprintf(g,"%d\n",a);
34 fscanf(f,"%d",&C);
35
36 for (i=1;i<=C;i++)
37 {
38 fscanf (f,"%d",&L[i]);
39 }
40
41 for (i=1;i<=N;i++)
42 S[i] = L[P[S[i]]];
43
44 for (i=1;i<=N;i++)
45 {
46 fprintf(g,"%c",S[i] + ’0’);
47 }
48
49 for (i=1,j=N;i<=j;i++,j--)
50 {
51 c = S[i];
CAPITOLUL 10. OJI 2011 133
52 S[i] = S[j];
53 S[j] = c;
54 }
55
56 for (i=1, T = 0;i<=N;i++)
57 {
58 aux = S[i] * (N-i+1) + T;
59 S[i] = aux%10;
60 T = aux/10;
61 }
62
63 while (T)
64 {
65 S[++N] = T%10;
66 T/=10;
67 }
68
69 fprintf(g,"\n");
70
71 for (i=N;i>=1;i--)
72 {
73 fprintf(g,"%c",S[i] + ’0’);
74 }
75
76 fclose(f);
77 fclose(g);
78 return 0;
79 }
Capitolul 11
OJI 2010
Cerinµe
Scrieµi un program care s citeasc ³irul de cuvinte ³i s a³eze:
a) num rul de ordine al primului cuvânt ³ters sau valoarea 0 în cazul în care nu se ³terge niciun
cuvânt
b) numerele de ordine ale cuvintelor r mase dup nalizarea operaµiilor de modicare.
Date de intrare
Fi³ierul cuvant.in conµine o singur linie pe care se a ³irul de cuvinte separate dou câte
dou printr-un spaµiu.
Date de ie³ire
Fi³ierul cuvant.out va conµine:
- pe prima linie num rul de ordine al primului cuvânt ³ters sau valoarea 0 în cazul în care nu
se ³terge niciun cuvânt
- pe a doua linie numerele de ordine ale cuvintelor r mase în nal în ³irul de cuvinte, desp rµite
dou câte dou printr-un spaµiu.
Restricµii ³i preciz ri
- Dup ultimul cuvânt din ³irul iniµial exist caracterul !
- Fiecare cuvânt are maxim 10 caractere, iar în ³irul iniµial nu exist mai mult de 25 cuvinte.
- ³irul de cuvinte iniµial este format din cel puµin un cuvânt. O pereche de cuvinte vecine a, b,
din ³irul de cuvinte este caracterizat prin faptul c , dup cuvântul a se aa imediat cuvântul b.
- Se acord punctaje parµiale: cerinµa a) 40% din punctaj, cerinµa b) 60% din punctaj
134
CAPITOLUL 11. OJI 2010 135
Exemple
cuvinte.in cuvinte.out
alfa faal alfa fala lafa afal calfa calfa! 2
1 3 4 7 8
Explicaµii:
Cuvintele obµinute prin transformarea cuvântului alfa sunt: lfaa, faal, aalf. Prima pereche
de cuvinte vecine care îndeplinesc cerinµele sunt cuvintele cu numerele de ordine 1 ³i 2. Va ³ters
cuvântul cu num rul de ordine 2. ³irul rezultat este format din urm toarele 7 cuvinte: alfa alfa
fala lafa afal calfa calfa. Prima pereche care îndepline³te cerinµele din noul ³ir este perechea
format din cuvintele fala ³i lafa, având numerele de ordine 4 ³i 5, pentru c lista de cuvinte
obµinute prin transformarea cuvântului fala sunt: alaf, lafa, afal. Se va ³terge cuvântul cu
num rul de ordine 5. ³irul rezultat dup ³tergere este: alfa alfa fala afal calfa calfa. Prima
pereche care îndepline³te cerinµele problemei în noul ³ir este fala ³i afal. Se ³terge afal cu num rul
de ordine 6. ³irul rezultat dup ³tergere este: alfa alfa fala calfa calfa. în acest ³ir nu se mai
g se³te nicio pereche care s îndeplineasc cerinµele. Au r mas deci cuvintele: alfa, alfa, fala,
calfa, calfa care au numerele de ordine 1, 3, 4, 7, 8.
Timp maxim de executare/test: 1.0 secunde
Pentru primul cuvant se determina toate cuvintele obtinute prin transformarea lui.
1 #include<fstream>
2 #include<string.h>
3
4 using namespace std;
5
6 char x[25][255],y[25][255];
7 int poz[25];
8
9 void transforma(char s[255])
10 {
11 unsigned int i;
12 for(i=0;i<strlen(s);i++)
13 {
14 strncat(s,s,1);
15 strcpy(s,s+1);
16 strcpy(y[i],s);
17 }
18 }
19
CAPITOLUL 11. OJI 2010 136
Zarul folosit la diverse jocuri este un cub care are desenat pe ecare
faµ a sa 1, 2, 3, 4, 5 sau 6 puncte. Pe un zar nu exist dou feµe cu
acela³i num r de puncte ³i suma punctelor de pe oricare dou feµe opuse
este egal cu 7.
Pe o mas de joc este desenat un traseu în form de p trat, cu latura
de dimensiune n. Fiecare latur a traseului este împ rµit în n p tr µele Figura 11.1: triunghi
identice, care au latura egal cu cea a zarului. Zarul este a³ezat iniµial în
colµul din stânga sus al traseului ³i apoi rostogolit de pe o faµ pe alta,
din p tr µel în p tr µel, de-a lungul traseului parcurs în sensul acelor de ceasornic.
În orice moment ne-am uita la zar, putem vedea num rul punctelor desenate pe trei din feµele
sale (a³a cum se vede în desenul de mai sus).
Not m cu f1 faµa cubului orientat spre noi, f2 faµa superioar a cubului, respectiv cu f3
faµa lateral din dreapta. Pentru exemplul din gur : n 4, faµa dinspre noi (f 1) conµine trei
puncte, faµa superioar (f 2) conµine dou puncte, faµa lateral din dreapta (f 3) conµine un punct,
iar sensul de deplasare este cel precizat prin s geµi.
Cerinµe
Cunoscând dimensiunea n a traseului ³i num rul punctelor de pe cele trei feµe ale zarului în
poziµia iniµial , determinaµi dup k rostogoliri num rul punctelor ce se pot observa pe ecare din
cele trei feµe ale zarului.
Date de intrare
Fi³ierul zar.in conµine:
- pe prima linie numerele naturale n ³i k desp rµite print-un spaµiu.
- pe linia a doua trei numere naturale separate printr-un spaµiu ce corespund num rului de
puncte de pe feµele f 1, f 2, respectiv f3 ale zarului în poziµia iniµial .
Date de ie³ire
Fi³ierul zar.out va conµine o singur linie cu trei numere naturale separate prin câte un spaµiu,
care reprezint num rul punctelor ce se pot observa pe feµele f 1, f 2 ³i f 3 (în aceast ordine) dup
ce au fost efectuate k rostogoliri pe traseul dat.
Restricµii ³i preciz ri
2 & n & 20000, 1 & k & 1000000
Exemple
zar.in zar.out
4 11 1 5 3
3 2 1
Explicaµii:
Fiecare latur a traseului este format din 4 c suµe ³i se vor efectua 11 rostogoliri. Dup prima
rostogolire spre dreapta, valorile celor trei feµe (f 1, f 2, respectiv f 3) ale zarului vor 3, 6 ³i 2.
Dup a doua rostogolire obµinem numerele 3, 5, 6, iar dup a treia rostogolire valorile feµelor vor
3, 1 ³i 5. în acest moment zarul a parcurs o latur a traseului. Urm toarele trei rostogoliri se
vor efectua în jos, de-a lungul traseului iar feµele vor avea succesiv valorile 1, 4, 5 apoi 4, 6, 5 ³i 6,
3, 5. Urmeaz rostogolirile spre stânga, pe feµele zarului vom observa valorile 6, 5, 4 apoi 6, 4, 2
³i respectiv 6, 2, 3. Ultimele dou rostogoliri se vor efectua în sus de-a lungul laturii din stânga a
traseului. Dup penultima rostogolire obµinem 5, 6, 3, iar dup ultima rostogolire valorile feµelor
vor 1, 5 ³i 3.
Pozitia fetelor zarului este periodica. Din acest motiv, din patru in patru
rostogoliri pe aceeasi latura a traseului, pe fetele zarului se vor observa
aceleasi valori.
Pentru rostogoliri spre stanga sau spre dreapta de-a lungul traseului, vom
tine cont de modificarea valorilor celor patru fete implicate in rostogilirea
pe aceasta directie:
f2 f3 7-f2 7-f3
Analog vom proceda pentru fetele implicate in rostogoliri in sus sau in jos
de-a lungul celorlaltor doua laturi ale traseului. Cele patru valori ale
fetelor implicate in acest tip de rostogolire sunt:
f2 7-f1 7-f2 f1
Prin permutari ale acestor valori, vom obtine pozitia finala a zarului dupa
k rostogoliri pe traseul dat.
1 #include <fstream>
2 #include<iostream>
3
4 using namespace std;
5
6 ifstream f("zar.in");
7 ofstream g("zar.out");
8
9 int st_dr[4], sus_jos[4], f1, f2, f3;
10 long n,k;
11
12 void rostogolire_dreapta(int st_dr[],long p)
13 {
14 int i,j,aux;
15 p=p%4;
16 for(i=1;i<=p;i++)
17 {
18 aux=st_dr[1];
19 for(j=1;j<=3;j++)
20 st_dr[j]=st_dr[j+1];
21 st_dr[4]=aux;
22 }
23 }
24
25 void rostogolire_stanga(int st_dr[],long p)
26 {
27 int i,j,aux;
28 p=p%4;
29 for(i=1;i<=p;i++)
30 {
31 aux=st_dr[4];
32 for(j=4;j>=1;j--)
33 st_dr[j]=st_dr[j-1];
34 st_dr[1]=aux;
35 }
36 }
37
38 int main()
39 {
40 f>>n>>k;
41 f>>f1>>f2>>f3;
CAPITOLUL 11. OJI 2010 139
42
43 st_dr[1]=7-f2;
44 st_dr[2]=f3;
45 st_dr[3]=f2;
46 st_dr[4]=7-f3;
47
48 sus_jos[1]=7-f2;
49 sus_jos[2]=f1;
50 sus_jos[3]=f2;
51 sus_jos[4]=7-f1;
52
53 while(k>0)
54 {
55 if (k<n)//dreapta
56 {
57 rostogolire_dreapta(st_dr,k);
58 k=0;
59 }
60 else
61 {
62 rostogolire_dreapta(st_dr,n-1);
63 k=k-(n-1);
64 }
65
66 sus_jos[1]=st_dr[1];
67 sus_jos[3]=st_dr[3];
68
69 if (k<n)//jos
70 {
71 rostogolire_dreapta(sus_jos,k);
72 k=0;
73 }
74 else
75 {
76 rostogolire_dreapta(sus_jos,n-1);
77 k=k-(n-1);
78 }
79
80 st_dr[1]=sus_jos[1];
81 st_dr[3]=sus_jos[3];
82
83 if (k<n)//stanga
84 {
85 rostogolire_stanga(st_dr,k);
86 k=0;
87 }
88 else
89 {
90 rostogolire_stanga(st_dr,n-1);
91 k=k-(n-1);
92 }
93
94 sus_jos[1]=st_dr[1];
95 sus_jos[3]=st_dr[3];
96
97 if (k<n)//sus
98 {
99 rostogolire_stanga(sus_jos,k);
100 k=0;
101 }
102 else
103 {
104 rostogolire_stanga(sus_jos,n-1);
105 k=k-(n-1);
106 }
107
108 st_dr[1]=sus_jos[1];
109 st_dr[3]=sus_jos[3];
110 }
111
112 g<<sus_jos[2]<<" "<<st_dr[3]<<" "<<st_dr[2];
113
114 return 0;
115 }
Partea II
140
Capitolul 12
ONI 2020
12.1 ***
Problema 1 - ... 100 de puncte
Cerinµe
Date de intrare
Date de ie³ire
Restricµii ³i preciz ri
Exemple:
12.2 ***
Problema 2 - ... 100 de puncte
Cerinµe
Date de intrare
Date de ie³ire
Restricµii ³i preciz ri
141
CAPITOLUL 12. ONI 2020 142
Exemple:
CAPITOLUL 12. ONI 2020 143
12.3 ***
Problema 3 - ... 100 de puncte
Cerinµe
Date de intrare
Date de ie³ire
Restricµii ³i preciz ri
Exemple:
ONI 2019
13.1 domino
Problema 1 - domino 100 de puncte
Într-un joc de domino, ecare pies este împ rµit în dou zone, în ecare zon ind înscris
un num r natural. Dac jocul are dimensiunea d, în joc vor exista toate piesele distincte care se
pot forma cu numere cuprinse între 0 ³i d. Dou piese sunt considerate identice dac au înscrise
acelea³i numere, indiferent de ordinea lor. Astfel, piesele 3, 7³i 7, 3 sunt identice. De exemplu,
jocul de dimensiune d 2 va avea 6 piese distincte:
Suma tuturor numerelor de pe aceste piese este 12. Problema are dou cerinµe:
1. Dat ind un ³ir format din N numere naturale nenule reprezentând dimensiunile unor jocuri
de domino, s se determine pentru ecare joc suma tuturor numerelor înscrise pe piesele din jocul
respectiv.
2. Dat ind un ³ir format din N numere naturale nenule reprezentând sumele tuturor numerelor
de pe piesele unor jocuri de domino, se construie³te mai întâi un ³ir de cifre, notat cu A, scriind
în ordine toate numerele din ³irul dat, f r spaµii între ele. Se cere s se construiasc un ³ir strict
cresc tor de numere naturale, notat cu B, parcurgând alternativ cifrele din ³irul A de la stânga
la dreapta ³i de la dreapta la stânga dup cum urmeaz :
- primul num r din B este format din prima cifr din ³irul A;
- al doilea num r din B se construie³te concatenând (alipind) cifrele din A, începând de la
dreapta c tre stânga, pân când obµinem un num r strict mai mare decât primul num r din B;
- al treilea num r din B se construie³te concatenând cifrele din A de la stânga c tre dreapta
(începând cu prima cifr care nu a fost deja utilizat ), pân când obµinem un num r strict mai
mare decât precedentul din B;
- al patrulea num r din B se construie³te concatenând din nou cifrele din A de la dreapta la
stânga (începând cu cea mai din dreapta cifr care nu a fost deja utilizat ), pân când obµinem
un num r strict mai mare decât al treilea din B;
- se continu astfel alternativ, pân când nu se mai poate forma un num r strict mai mare
decât ultimul num r ad ugat în B.
Cerinµe
Scrieµi un program care rezolv cerinµele 1 ³i 2 descrise în enunµ.
Date de intrare
Fi³ierul de intrare domino.in conµine pe prima linie un num r natural C reprezentând cerinµa
care trebuie rezolvat (1 sau 2). Pe a doua linie se a num rul natural N. Pe a treia linie se a
N numere naturale nenule separate prin câte un spaµiu d1 d2 ... dN .
Date de ie³ire
144
CAPITOLUL 13. ONI 2019 145
Restricµii ³i preciz ri
a 1&N & 104
a Dac C 1, 1 & di & 1000, iar dac C 2, 1 & di & 109, pentru 1 & i & N .
a Numerele din ³irul B vor a³ate f r zerouri nesemnicative (de exemplu, dac în urma
aplic rii regulilor din enunµ în ³irul B se obµine num rul 0204 se a³eaz 204).
a Pentru teste în valoare de 30 de puncte cerinµa este 1.
Exemple
domino.in domino.out Explicaµii
1 12 30 2040 60 252 Cerinµa este 1, deci trebuie s determin m sumele numerelor
5 din jocurile de dimensiune 2, 3, 15, 4 ³i 7.
2 3 15 4 7
Cerinta 1:
Cerinta 2:
Testele au fost alese astfel incat se putea obtine punctaj si in situatia folosirii
tip long long.
Exista teste in care valorile pe baza carora se obtin sirurile sunt formate din cif
19 if (pr == 1)
20 {
21 int i, x, a, b, c;
22 cin >> n;
23 for(i=1; i<=n; i++)
24 {
25 cin >> x;
26 a = x;
27 b = x+1;
28 c = x+2;
29 if(a%2 == 0)
30 a /= 2;
31 else
32 b /= 2;
33 v[i] = a * b * c;
34 }
35
36 for(i=1; i<n; i++)
37 cout << v[i] << ’ ’;
38 cout << v[n];
39 cout << ’\n’;
40 }
41 else
42 {
43 char aux[1000], nr[1000];
44 int i, j, s, unde, cif;
45 bool exista;
46
47 cin >> n;
48 for(i=1; i<=n; i++)
49 cin >> v[i];
50
51 for(i=1; i<=n; i++)
52 {
53 s = v[i];
54 p[i] = 1;
55 while(s > 9)
56 {
57 p[i] = p[i]*10;
58 s /= 10;
59 }
60 }
61
62 i = 1; j = n;
63 exista = true;
64 unde = 2; //urmeaza dreapta - stanga
65 cif = v[1]/p[1];
66 nr[0] = (char)(cif+’0’);
67 nr[1] = ’\0’;
68 v[1] = v[1] % p[1];
69 p[1] = p[1] / 10;
70 if(p[1] == 0)
71 i = 2;
72 cout << nr << ’ ’; // nr format din prima cifra
73 while(i<=j && exista)
74 {
75 if(unde == 2)
76 {
77 s = 0;
78 while(v[j] > 0 && j >= i)
79 {
80 cif = v[j]%10;
81 v[j] /= 10;
82 p[j] /= 10;
83 if(cif == 0 && s == 0)
84 continue;
85 aux[s++] = (char)(cif+’0’);
86 aux[s] =’\0’;
87 if(v[j]==0 && j >= i && p[i] != 0)
88 j--;
89 if(strlen(aux) > strlen(nr) ||
90 (strcmp(aux, nr)>0 && strlen(aux) == strlen(nr)))
91 {
92 unde = 1;
93 break;
94 }
CAPITOLUL 13. ONI 2019 148
95 }
96
97 if(v[j] == 0 && j >= i && p[i] != 0)
98 j --;
99 }
100 else
101 {
102 s = 0;
103 while(p[i] > 0 && i <= j)
104 {
105 cif = v[i] / p[i];
106 v[i] = v[i] % p[i];
107 p[i] = p[i] / 10;
108 if(cif == 0 && s == 0)
109 {
110 if(p[i] == 0 && i <= j && p[j] != 0)
111 i++;
112 continue;
113 }
114
115 aux[s++] = (char)(cif+’0’);
116 aux[s] = ’\0’;
117
118 if(p[i] == 0 && i <= j && p[j] != 0)
119 i ++;
120
121 if(strlen(aux) > strlen(nr) ||
122 (strcmp(aux, nr)>0 && strlen(aux) == strlen(nr)))
123 {
124 unde = 2;
125 break;
126 }
127 }
128
129 if(p[i] == 0 && i <= j && p[j] != 0)
130 i++;
131 }
132
133 if(strlen(aux) < strlen(nr) ||
134 (strcmp(aux, nr)<0 && strlen(aux) == strlen(nr)))
135 exista = false;
136 else
137 {
138 cout << aux << ’ ’;
139 strcpy(nr, aux);
140 }
141
142 if(i == j && p[i] == 0)
143 exista = false;
144 }
145 }
146
147 return 0;
148 }
19 int compar (char a[], int lga, char b[], int lgb);
20
21 int main()
22 {int i, nr, poz, st, dr, lg, j;
23 long long int x;
24 fin>>cerinta>>n;
25 assert(cerinta==1 || cerinta==2);
26 assert(0<n && n<=10000);
27 if (cerinta==1)
28 {
29 i=0;
30 while (fin>>x)
31 {
32 i++;
33 assert(0<x && x<=1000);
34 fout<<x*(x+1)*(x+2)/2<<’ ’;
35 }
36 assert(i==n);
37 fout<<’\n’; fout.close(); return 0;
38 }
39
40 poz=0;
41 i=0;
42 while (fin>>nr)
43 {
44 i++;
45 assert(0<nr && nr<=1000000000);
46 for (x=1; x<=1000; x++) if (x*(x+1)*(x+2)/2==nr) break;
47 assert (x<=1000);
48 lg=0;
49 while (nr)
50 {v[lg++]=nr%10; nr/=10; }
51 for (j=lg-1; j>=0; j--) s[poz++]=v[j]+’0’;
52 }
53 assert(i==n);
54
55 fout<<s[0]<<’ ’;
56 last[0]=s[0]; last[1]=0; st=1; dr=poz-1; lglast=1;
57 while (1)
58 {
59 while (s[dr]==’0’ && st<=dr) dr--;
60 if (st<=dr) {crt[0]=s[dr--]; crt[1]=0; lgcrt=1;}
61 else break;
62 while (compar(last,lglast,crt,lgcrt)>=0 && st<=dr)
63 {crt[lgcrt++]=s[dr--]; crt[lgcrt]=0; }
64 if (compar(last,lglast,crt,lgcrt)<0)
65 {
66 fout<<crt<<’ ’;
67 strcpy(last,crt); lglast=lgcrt;
68 }
69 else break;
70 while (s[st]==’0’ && st<=dr) st++;
71 if (st<=dr) {crt[0]=s[st++]; crt[1]=0; lgcrt=1;}
72 else break;
73
74 while (compar(last,lglast,crt,lgcrt)>=0 && st<=dr)
75 {crt[lgcrt++]=s[st++]; crt[lgcrt]=0; }
76 if (compar(last,lglast,crt,lgcrt)<0)
77 {
78 fout<<crt<<’ ’;
79 strcpy(last,crt); lglast=lgcrt;
80 }
81 else break;
82 }
83 fout<<’\n’;
84 fout.close();
85
86 return 0;
87 }
88
89
90 int compar (char a[], int lga, char b[], int lgb)
91 {int i;
92 if (lga<lgb) return -1;
93 if (lga>lgb) return 1;
94 for (i=0; i<lga && a[i]==b[i]; i++);
CAPITOLUL 13. ONI 2019 150
95 if (i==lga) return 0;
96 if (a[i]<b[i]) return -1;
97 return 1;
98 }
69 if(strcmp(a,b))out<<b<<’ ’;
70 strcpy(a,b);
71 p++;
72 }
73 }
74 int main()
75 {
76 citire();
77 if(C==1) P1();
78 else P2();
79 return 0;
80 }
13.2 tuburi
Problema 2 - tuburi 100 de
puncte
Pe un perete au fost montate n m piese pe n rân-
duri (numerotate de sus în jos, de la 1 la n) ³i m coloane
(numerotate de la stânga la dreapta, de la 1 la m). Pie-
sele sunt tuburi sau coturi având unul dintre tipurile 1,
2, ..., 6, conform imaginii al turate.
Ionel poate introduce o bil într-o pies situat pe
rândul 1, doar dac piesa este de tip 2, 4 sau 6. Bila
poate coborî un nivel sau se poate deplasa pe orizontal Figura 13.3: joc1
într-o pies al turat , dac îmbinarea pieselor permite aceasta, dar nu poate urca, din cauza
gravitaµiei. Bila nu poate trece de dou ori prin aceea³i pies ³i se blocheaz atunci când nu se
mai poate deplasa într-o alt pies .
Cerinµe
Se citesc dou numere naturale n, m ³i apoi nm numere din mulµimea r1, 2, 3, 4, 5, 6x repre-
zentând dispunerea pieselor pe perete. Scrieµi un program care s rezolve urm toarele cerinµe:
1. determin num rul maxim de piese prin care poate trece pân la blocare o bil introdus
în una dintre piesele de pe rândul 1, având tipul 2, 4 sau 6;
2. pentru un rând k dat, determin numerele c ³i t, unde c este coloana minim pentru care,
înlocuind piesa existent pe rândul k ³i coloana c cu o pies de tipul t, se obµine un num r cât
mai mare posibil de piese prin care poate trece, pân la blocare, o bil introdus în una dintre
piesele de pe rândul 1 având tipul 2, 4 sau 6; dac exist mai multe soluµii de a înlocui piesa de
pe rândul k ³i coloana c, se alege varianta cu t minim.
Date de intrare
Fi³ierul de intrare tuburi.in conµine pe prima linie un num r natural C reprezentând cerinµa
care trebuie s e rezolvat (1 sau 2), pe a doua linie numerele naturale n, m, reprezentând
dimensiunile peretelui. Pe ecare dintre urm toarele n linii se a câte m numere aparµinând
mulµimii r1, 2, 3, 4, 5, 6x reprezentând în ordine tipurile pieselor de pe perete. Dac cerinµa este
C 2, ³ierul de intrare conµine în plus, pe a n 3-a linie, un num r natural k reprezentând
num rul unui rând de piese. Valorile scrise pe aceea³i linie sunt separate prin câte un spaµiu.
Date de ie³ire
Fi³ierul de ie³ire tuburi.out va conµine o singur linie.
Dac C 1, atunci pe prima linie a ³ierului se va scrie un num r natural reprezentând
rezultatul de la cerinµa 1.
Dac C 2, atunci pe prima linie a ³ierului se vor scrie dou numere naturale c ³i t, separate
printr-un spaµiu, cu semnicaµia din enunµ.
Restricµii ³i preciz ri
a 2 & n, m & 500
a Pentru teste valorând 40 de puncte cerinµa este 1.
CAPITOLUL 13. ONI 2019 152
Exemple
Cerinta 1: se determina pentru fiecare coloana j din multimea de indici {1, 2, ...,
numarul de piese prin care poate trece bila introdusa in piesa de pe randul 1, colo
daca aceasta este de tipul 2, 4 sau 6 si apoi maximul dintre valorile obtinute. In
rezolvarii cerintei doi, pe parcursul determinarii traseelor posibile, pentru fieca
pozitie (i,j) se retine intr-o matrice suplimentara coloana in care a fost introdus
pe randul 1, pentru a ajunge in acea pozitie, respectiv, valoarea 0 daca niciun tra
trece prin acea piesa.
Cerinta 2:
Pentru k=1 se plaseaza in fiecare coloana j, pe rand cate o piesa de orice tip si s
determina lungimea maxima a unui traseu posibil al bilei pana la blocare.
75 else
76 {
77 int t,tc,c,aux,caz;
78 in>>r;
79 for (j=1; j<=m; j++)
80 { aux=a[r][j];
81 for (tc=1; tc<=6; ++tc)
82 { a[r][j]=tc;
83 if(tc%2==0)
84 {C[0][j]=j;l=lungime(1,C[r-1][j],r);}
85 else if(tc==1)
86 l=lungime(1,C[r][j+1],r);
87 else if(tc==3)
88 l=lungime(1,C[r][j-1],r);
89 else
90 { l=lungime(1,C[r][j-1],r);
91 if (l>lm)
92 {lm=l;c=j;t=tc;}
93 l=lungime(1,C[r][j+1],r);
94 }
95 if (l>lm)
96 {lm=l;c=j;t=tc;}
97 }
98 a[r][j]=aux;
99 }
100 out<<c<<’ ’<<t<<’\n’;
101 } return 0;
102 }
45 {
46 if (a[i][j+1]==3 || a[i][j+1]==5)
47 {jj=j;j++;l++;g=1; }
48 }
49 else
50 {
51 if (a[i][j-1]==1 || a[i][j-1]==5)
52 {jj=j;j--;l++;g=1;}
53 }break;
54 case 6:
55 if (a[i][j-1]==5 || a[i][j-1]==1)
56 {jj=j;j--;l++;g=1;}
57 }
58 if(k==0) C[i][j]=col;
59 }
60 while (g);
61 return l;
62 }
63
64 int main()
65 {
66 int j, l, lmv;
67 citire();
68 for (j=1; j<=m; j++)
69 if (a[1][j]%2==0)
70 {
71 l=lungime(1,j,0);
72 if (l>lm) lm=l;
73 }
74 lmv=lm;
75 if(p==1) out<<lm<<’\n’;
76 else
77 {
78 int t,tc,c,aux,caz;
79 in>>r;
80 lm=0;
81 for (j=1; j<=m; j++)
82 { aux=a[r][j];
83 for (tc=1; tc<=6; ++tc)
84 { a[r][j]=tc;
85 if(tc%2==0)
86 if(r>1) l=lungime(1,C[r-1][j],r);
87 else l=lungime(1,j,r);
88 else if(tc==1) l=lungime(1,C[r][j+1],r);
89 else if(tc==3) l=lungime(1,C[r][j-1],r);
90 else
91 { l=lungime(1,C[r][j-1],r);
92 if (l>lm)
93 {lm=l;c=j;t=tc;}
94 l=lungime(1,C[r][j+1],r);
95 }
96 if (l>lm)
97 {lm=l;c=j;t=tc;}
98 }
99 a[r][j]=aux;
100 }
101 out<<c<<’ ’<<t<<’\n’;
102 } return 0;
103 }
13.3 venus
Problema 3 - venus 100 de puncte
Casa de Mod Venus a decis s se modernizeze ³i, începând cu 1 ianuarie 2020 ora 00 00,
l-a angajat pe robotul Vasile. Vasile poate executa orice comand în exact T ore, indiferent de
complexitatea acesteia (mai exact, dac Vasile începe s lucreze la comand în momentul x, la
momentul xT ore comanda va gata de predare). Foarte încrez toare în calit µile robotului
Vasile, Casa de Mod Venus a lansat o campanie publicitar cu sloganul Dac am întârziat,
prime³ti produsul comandat gratis!. Campania ³i-a atins scopul, ca urmare Casa de Mod a
primit deja N comenzi pentru întreg anul 2020. Pentru ecare comand sunt specicate valoarea
acesteia, precum ³i data ³i ora pân la care produsul comandat trebuie s e gata de predare.
CAPITOLUL 13. ONI 2019 156
Dac Vasile pred produsul exact la data ³i ora specicat în comand (sau înainte) el încaseaz
valoarea comenzii. Dac nu, el tot trebuie s execute comanda respectiv , dar nu va primi suma
reprezentând valoarea ei.
De³i lucreaz f r nicio pauz , Vasile estimeaz c este posibil s nu poat preda la timp
toate comenzile, dar î³i planic lucrul, astfel încât pierderea s e minim (adic suma valorilor
comenzilor care nu vor predate la timp s e cât mai mic ). Numim planicare optimal
succesiunea în care Vasile trebuie s execute cele N comenzi, astfel încât pierderea s e minim .
Cerinµe
Scrieµi un program care, cunoscând informaµiile referitoare la cele N comenzi, determin pier-
derea minim , precum ³i o planicare optimal .
Date de intrare
Fi³ierul de intrare venus.in conµine pe prima linie num rul natural N , reprezentând num rul
de comenzi ³i num rul natural T , reprezentând num rul de ore necesare lui Vasile pentru a executa
o comand . Pe urm toarele N linii se a informaµiile despre comenzi, câte o comand pe o linie,
sub forma:
V zi luna ora
unde V este valoarea comenzii, zi este ziua în care trebuie predat comanda (un num r natural
cuprins între1 ³i num rul de zile ale lunii), luna este denumirea lunii, iar ora este un num r natural
cuprins între 0 ³i 23. Valorile scrise pe aceea³i linie sunt separate prin câte un spaµiu.
Comenzile se consider numerotate de la 1 la N în ordinea din ³ierul de intrare.
Date de ie³ire
Fi³ierul de ie³ire venus.out va conµine pe prima linie num rul natural pmin, reprezentând
pierderea minim . Pe a doua linie vor scrise N numere naturale distincte cuprinse între 1 ³i N,
separate prin câte un spaµiu, reprezentând o planicare optimal .
Restricµii ³i preciz ri
a 1 & N & 1000
a 1 & T & 500
a 1 & V & 10000
a Numele lunilor vor scrise cu litere mici. Anul 2020 este an bisect, adic luna februarie are
29 de zile.
a Dac exist mai multe planic ri optimale, se va accepta orice soluµie corect .
a Se acord 50% din punctajul pentru ecare test pentru determinarea valorii pmin. Punctajul
integral pentru ecare test se acord pentru rezolvarea ambelor cerinµe (pmin ³i o planicare
optimal ).
Exemple
venus.in venus.out Explicaµii
4 25 50 Începând cu 1 ianuarie ora 0, Vasile execut
90 10 ianuarie 20 4 1 3 2 comanda 4 ³i termin pe 2 ianuarie la ora 1.00.
50 2 ianuarie 8 Execut apoi comanda 1 pe care o termin pe 3
20 4 ianuarie 3 ianuarie la ora 2.00.
70 2 ianuarie 9 Execut apoi comanda 3 pe care o termin pe 4
ianuarie la ora 3.00.
Execut apoi comanda 2 pe care o termin pe 5
ianuarie la ora 4.00, ceea ce înseamn c a dep ³it
termenul de predare, deci pierde valoarea ei (50).
Exist ³i alte planic ri optimale posibile.
De exemplu, 4 3 1 2.
Toate subiectele sunt obligatorii. Timpul de lucru efectiv alocat probei este de 4 ore.
Punctajul maxim cumulat pentru cele trei probleme este de 300 de puncte.
Solutie alternativa,
66 j--);
67
68 ///putem insera comanda i pe pozitia j+1?
69 if (j==0&&C[i].p>=t || C[L[j]].p<=C[i].p && C[L[j]].tc+t<=C[i].p)
70 //onorez comanda i
71 {
72 for (k=lg; k>j; k--) {C[L[k]].tc+=t; L[k+1]=L[k];}
73 lg++;
74 L[j+1]=i;
75 C[i].tc=C[L[j]].tc+t;
76 }
77 else C[i].tc=-1;
78 }
79 }
80
81 pmin=0;
82 for (i=1; i<=n; i++)
83 if (C[i].tc==-1) pmin+=C[i].v;
84 fout<<pmin<<’\n’;
85
86 for (i=1; i<=lg; i++) fout<<C[L[i]].nr<<’ ’;
87 for (i=1; i<=n; i++)
88 if (C[i].tc==-1) fout<<C[i].nr<<’ ’;
89
90 fout<<’\n’;
91 fout.close();
92 return 0;
93 }
45 v[i].nr=i;
46 cin>>v[i].v>>zi>>luna>>v[i].h;
47 l=lunaZ(luna);
48 v[i].h+=(l+zi-1)*24;
49 if(v[i].h<t)v[i].nt=0;
50 else v[i].nt=v[i].h/t;
51 tot+=v[i].v;
52 }
53
54 sort(v+1,v+n+1,comp);
55
56 mg=0;
57 tlm=366*24;
58 p[0]=1;
59 for(i=1;i<=n;++i)
60 if(!p[v[i].nt])
61 {
62 p[v[i].nt]=v[i].nr;
63 b[i]=true;
64 mg+=v[i].v;
65 }
66 else
67 {
68 j=v[i].nt;
69 while(j>0&&p[j])
70 j--;
71 if(j)
72 {
73 p[j]=v[i].nr;
74 b[i]=true;
75 mg+=v[i].v;
76 }
77 }
78
79 cout<<tot-mg<<’\n’;
80 for (i=1; i<=tlm; ++i)
81 if (p[i])
82 cout << p[i]<<’ ’;
83
84 for (int i=1;i<=n;++i)
85 if(!b[i])
86 cout << v[i].nr<<’ ’;
87
88 return 0;
89 }
Capitolul 14
ONI 2018
14.1 evip
Problema 1 - evip 100 de puncte
Un num r natural n se nume³te num r VIP dac este format din cel puµin dou cifre, conµine
cel puµin o cifr impar ³i cel puµin o cifr par , iar toate cifrele impare sunt scrise înaintea tuturor
celor pare. (VIP=Valori Impare Pare). De exemplu, 352, 7546 sunt numere VIP, iar 35, 468, 5483,
387 nu sunt numere VIP. Se nume³te SECVEN VIP într-un ³ir de cifre, o succesiune de cifre
(aate pe poziµii consecutive în ³ir) care formeaz , în ordine, un num r VIP.
Cerinµe
Pentru un ³ir de cifre nenule, se cere s se determine:
1. Num rul de SECVENE VIP din ³ir.
2. Lungimea minim a unui ³ir de cifre care conµine acela³i num r de SECVENE VIP ca
³irul dat ³i are toate cifrele impare situate înaintea celor pare.
3. Suma tuturor numerelor ce se pot forma, astfel încât ecare num r s conµin toate cifrele
distincte ale celui mai mare num r VIP din ³irul dat, ecare cifr ind folosit exact o dat , ³i
nicio alt cifr diferit de acestea.
Date de intrare
Fi³ierul evip.in conµine pe prima linie un num r natural c reprezentând cerinµa care trebuie
s e rezolvat (1, 2 sau 3). Pe cea de a doua linie se a un ³ir de cifre nenule, neseparate prin
spaµiu, reprezentând, în ordine, elementele ³irului.
Date de ie³ire
Dac cerinµa este c 1, atunci, pe prima linie a ³ierului evip.out va scris un num r natural
reprezentând num rul de SECVENE VIP din ³ir.
Dac cerinµa este c 2, atunci, pe prima linie a ³ierului evip.out va scris un num r natural
reprezentând lungimea minim a unui ³ir de cifre care conµine acela³i num r de SECVENE VIP
ca ³irul dat ³i are toate cifrele impare situate înaintea celor pare.
Dac cerinµa este c 3, atunci, pe prima linie a ³ierului evip.out va scris un num r natural
reprezentând suma tuturor numerelor ce se pot forma, astfel încât ecare num r s conµin toate
cifrele distincte ale celui mai mare num r VIP din ³irul dat, ecare cifr ind folosit exact o dat ,
³i nicio alt cifr diferit de acestea.
Restricµii ³i preciz ri
a Num rul de cifre de pe linia a doua a ³ierului de intrare este cel puµin 2 ³i cel mult 10 000.
a ³irul conµine cel puµin o SECVEN VIP.
a Pentru teste valorând 30% din punctaj cerinµa este 1. Pentru teste valorând 30% din punctaj
cerinµa este 2. Pentru teste valorând 40% din punctaj cerinµa este 3.
161
CAPITOLUL 14. ONI 2018 162
Exemple
evip.in evip.out Explicaµii
1 6 Sunt 6 SECVENE VIP în ³irul dat:
413643623 136 (4 136 43623), 1364 (4 1364 3623), 36 (41364 36 23),
364 (41 364 3623), 36(41364 36 23), 362 (41364 362 3).
2 5 irul dat conµine 6 SECVENE VIP. Cel mai mic num r de cifre
413643623 dintr-un ³ir care conµine 6 SECVENE VIP ³i are toate cifrele impare
situate înaintea celor pare, este 5. Un exemplu de astfel de ³ir este
13246
3 1776 Cel mai mare num r VIP din ³ir este 1344. Cifrele distincte ale
413443623 acestui num r sunt {1,3,4}. Suma tuturor numerelor ce se pot scrie,
folosind, o singur dat , toate cifrele {1,3,4}, ³i nicio alt cifr diferit
de acestea, este 1776. 134+143+314+341+413+431=1776
Cerinµa 1)
Se identic secvenµele maximale, de cifre impare (impark ).
Fiecare astfel de secvenµ conµine impark park numere VIP.
Fie m num rul acestor secvenµe. Se calculeaz ³i se a³eaz < m
k 1 impark park .
Cerinµa 2)
Fie v num rul numerelor VIP aate în ³irul dat.
Lungimea celui mai scurt ³ir ce are toate cifrele impare înaintea celor pare ³i conµine axact
Ó
v numere VIP este dk
v
dk
, unde dk reprezint cel mai mare divizor al lui v, 1 & dk & v,
v dk dv
k
Demonstraµie: ...
Cerinµa 3)
Se identic cel mai mare num r VIP din ³ir ³i se determin mulµimea cifrelor distincte utilizate
în scrierea acestuia rx1 , x2 , ..., xk x. în ecare num r, trebuie s apar ecare dintre cele k cifre
distincte.
Fiecare dintre cifrele acestei mulµimi se poate aa pe oricare dintre cele k poziµii.
Mai întâi se calculeaz câte numere se pot forma cu cele k cifre. Dac x m prima cifr pe
una dintre cele k poziµii, atunci cea de-a doua cifr poate ocupa oricare dintre cele k1 poziµii
r mase ³.a.m.d. Penultimei cifre îi r mân dou poziµii, iar ultima cifr se a³eaz pe ultimul loc
r mas.
Notam acest num r cu nr k k 1 k 2 ... 2 1
A³ezând numerele unele sub altele, se observ c suma cifrelor de pe ecare ordin este aceea³i.
Not m aceast sum cu s. Mai mult, toate cele k cifre apar de acela³i num r de ori pe oricare
ordin (al unit µilor, al zecilor, al sutelor, etc). Fiind nr numere în total ecare cifr va ap rea
nr
de
k
ori în s.
A³adar
=x s s
k
=x
k
=x
k
nr k k 1 ... 2 1
s k k k 1 ... 2 1 k
k i 1
k i 1 i 1
s
distincte (201599999798400)
14.2 nxy
Problema 2 - nxy 100 de puncte
Se consider N , un num r natural nenul. Dorim s -l scriem pe N ca suma a dou numere
naturale nenule x ³i y , astfel încât suma cifrelor numerelor x ³i y s e maxim .
Cerinµe
Scrieµi un program care s rezolve urm toarele cerinµe:
1. s determine suma maxim a cifrelor a dou numerex ³i y cu proprietatea c x y N ;
xmax ³i ymax cu proprietatea c xmax ' ymax,
2. s determine dou numere naturale nenule
xmax ymax N , suma cifrelor lor este maxim , iar diferenµa xmax ymax este maxim ;
3. s determine dou numere naturale nenule xmin ³i ymin cu proprietatea c xmin ' ymin,
xmin ymin N , suma cifrelor lor este maxim , iar diferenµa xmin ymin este minim .
Date de intrare
Fi³ierul de intrare nxy.in conµine pe prima linie num rul natural c, reprezentând cerinµa (1,
2 sau 3). Pe cea de a doua linie se a num rul natural N.
Date de ie³ire
Fi³ierul de ie³ire nxy.out va conµine o singur linie. Dac c 1, pe prima linie va scris
un num r natural s, reprezentând suma maxim a cifrelor a dou numere naturale nenule x ³i y
pentru care xy N. Dac c 2 sau c 3, pe prima linie vor scrise dou numere naturale
nenule separate printr-un singur spaµiu, reprezentând soluµia pentru cerinµa respectiv (xmax
ymax pentru c 2, respectiv xmin ymin pentru c 3).
Restricµii ³i preciz ri
a 1$N & 1018
a Pentru teste valorând 20% din punctaj cerinµa este 1. Pentru teste valorând 40% din punctaj
cerinµa este 2. Pentru teste valorând 40% punctaj cerinµa este 3.
Exemple
nxy.in nxy.out Explicaµii
1 16 Suma maxim care se poate obµine adunând cifrele a dou numere x
25 ³i y pentru care x+y=25 este 16.
2 19 6 Suma maxim care se poate obµine adunând cifrele a dou numere x ³i
25 y pentru carex y 25 este 16. Perechea de numere xmax ' ymax
pentru care xmax ymax este maxim (13) ³i pentru care suma
cifrelor este maxim este xmax 19 ³i ymax 6.
3 16 9 Suma maxim care se poate obµine adunând cifrele a dou numere x
25 ³i y pentru care x y 25 este 16. Perechea de numere xmin ' ymin
pentru care xmin ymin este minim (7) ³i pentru care suma cifrelor
este maxim este xmin 16 ³i ymin 9.
14.3 viitor
Problema 3 - viitor 100 de puncte
Staµiunea Xoni de pe insula Ixos are N magazine de îngheµat , a³ezate unul lâng altul, pe
aceea³i parte a str zii pietonale. Acestea sunt numerotate cu valori naturale de la 1 la N, în
ordinea a³ez rii pe strad .
Magazinele sunt deµinute de K acµionari (numerotaµi de la 1 la K ), ecare dintre ace³tia ind
proprietarul unor magazine numerotate consecutiv. Un magazin poate avea mai mulµi acµionari.
Odat cu venirea verii, începe ³i perioada concediilor, toµi acµionarii luându-³i concediul îm-
preun , timp de M zile. înainte de a pleca în concediu, ei au discutat cu Transportel pentru a se
ocupa de aprovizionarea cu îngheµat a magazinelor lor. Acesta a decis, singur, s fac în ecare
dintre cele M zile aprovizionarea unor magazine, numerotate ³i acestea cu numere consecutive.
Cerinµe
Determinaµi, pentru ecare acµionar num rul de magazine deµinute de c tre acesta care nu au
fost aprovizionate cu îngheµat în nicio zi din concediu.
Date de intrare
Prima linie a ³ierului viitor.in conµine trei numere naturale N , M ³i K separate prin câte
un spaµiu, cu semnicaµia de mai sus.
Fiecare dintre urm toarele M x ³i y , separate printr-un
linii conµine câte dou numere naturale
spaµiu. Numerele xy aate pe cea de a i-a linie dintre cele M i sunt
semnic faptul c în ziua
aprovizionate cu îngheµat toate magazinele cu numerele de ordine x, x 1, ..., y .
Fiecare dintre urm toarele K linii conµine câte dou numere naturale a ³i b, separate printr-un
spaµiu. Numerele a b situate pe a i-a linie dintre cele K semnic faptul c proprietarul i este
acµionar la magazinele cu numerele a, a 1, a 2, ..., b.
Date de ie³ire
Fi³ierul viitor.out va conµine K linii. Pe cea de a i-a linie se a num rul de magazine
deµinute de c tre acµionarul i, care nu au fost aprovizionate cu îngheµat în nicio zi din concediu.
Restricµii ³i preciz ri
CAPITOLUL 14. ONI 2018 165
Exemple
viitor.in viitor.out Explicaµii
10 3 2 1 Magazinul 7 nu a fost aprovizionat în nicio zi, ind singurul
1 4 2 dintre cele deµinute de primul acµionar care nu prime³te înghe-
9 10 µat în nicio zi.
3 6 Dintre magazinele deµinute de acµionarul 2, cele cu numerele 7
1 7 ³i 8 nu primesc îngheµat în nicio zi.
4 10
Formal, problema spune c se d un prim set de intevale pe axa Ox (ecare dintre ele acoper
valori naturale consecutive) ³i se cer apoi informatii despre intervale dintr-un alt set: câte numere
naturale de pe axa Ox, incluse în intervalul dat, nu se a în niciun interval din primul set.
O soluµie poate urm toarea: odat cu citirea unui interval din primul set, se marcheaz
într-un vector valorile naturale care se a în acel interval. Când avem intervale din al doilea
set, putem e parcurge element cu element pentru a determina câte valori sunt nemarcate, e
putem aa direct dac în prealabil folosim un vector de sume parµiale pentru intervalul în care
am marcat. Aceast soluµie obµine punctaj parµial pentru c nu se încadreaz nici în timp nici în
memorie pentru datele maxime de la intrare.
O alta optimizare poate utilizarea tehnicii numit ³menul lui Mars pentru evitarea par-
curgerii tuturor numerelor dintr-un interval dat din primul set.
O alt soluµie care permite obµinerea punctajului maxim este urm toarea: Dupa ce intervalele
din primul set se sorteaz dup extremitatea stâng , se poate determina unui alt ³ir de intervale,
disjuncte, reunind pe cele care se intersecteaz . Pentru aceasta se folose³te un algoritm simplu:
avem setat un interval curent, iar intervalul la care am ajuns (în ordinea dat la intrare) produce
urm toarele cazuri:
- intersecteaz intervalul curent ³i nu îl extinde la dreapta (doar acolo se poate extinde) - în
acest caz trecem la urm torul interval;
- intersecteaz intervalul curent ³i îl extinde la dreapta - actualiz m extremitatea dreapt a
intervalului curent ³i trecem la urm torul interval;
- nu intersecteaz intervalul curent (automat începe dup extremitatea dreapt a acestuia),
caz în care trecem în soluµie (reuniune) intervalul curent ³i reiniµializ m intervalul curent cu acela
la care am ajuns cu parcurgerea.
Având intervalele disjuncte din reuniune, la ecare interval din al doilea set putem localiza
intervalele din reuniune în jurul c rora se a extremit µile celui de la interogarea curent prin
c ut ri binare. Folosindu-ne ³i de un vector de sume parµiale, putem r spunde apoi direct la ecare
interogare.
ONI 2017
15.1 carte
Problema 1 - carte 100 de puncte
În timpul activit µilor din "S pt mâna Altfel" elevii clasei a VII-a doresc s ajute la organizarea
c rµilor din biblioteca ³colii. Fiecare carte este etichetat cu un cod care este exprimat printr-
un un ³ir de caractere distincte. Acestea pot cifrele 0, 1, ..., 9 ³i primele zece litere mici ale
alfabetului englez a, b, ..., j.
Codul identic în mod unic ecare carte, adic nu vor exista dou c rµi cu acela³i cod, dar
³i genul literar din care acestea face parte. C rµile din acela³i gen literar au codul de identicare
format din acelea³i caractere, distincte, dispuse în alt ordine.
Numim coduri pereche dou coduri de identicare care au acela³i num r de caractere ³i care
difer printr-un caracter. De exemplu, codurile 42a8 ³i 2c8a sunt coduri pereche. Pe de alt parte,
codurile 42a8 ³i 248a, respectiv 42ab ³i 248c, nu sunt coduri pereche.
Cerinµe
Fiind dat ³irul celor N coduri de identicare, scrieµi un program care s rezolve urm toarele
cerinµe:
1) determin num rul de c rµi din cel mai numeros gen literar ³i num rul de genuri literare
care au acest num r maxim de c rµi.
2) determin num rul de coduri, din ³irul celor N, care sunt coduri pereche cu ultimul cod din
³ir.
Date de intrare
Fi³ierul de intrare carte.in conµine pe prima linie un num r natural C . Pentru toate testele,
C poate lua numai valorile 1 sau 2. Pe a doua linie se a num rul N de c rµi din biblioteca ³colii,
iar pe urm toarele N linii, câte un ³ir de caractere pe ecare linie, ce reprezint codul pentru
identicarea unei c rµi.
Date de ie³ire
Dac valoarea lui C este 1, se va rezolva numai cerinµa 1. în acest caz, ³ierul de ie³ire
carte.out conµine pe prima linie num rul maxim de c rµi de acela³i gen literar, M AX , iar pe a
doua linie num rul de genuri literare care au exact M AX c rµi.
Dac valoarea lui C este 2, se va rezolva numai cerinµa 2. în acest caz, ³ierul de ie³ire
carte.out conµine pe prima linie num rul de coduri pereche cu ultimul cod din ³irul celor N .
Restricµii ³i preciz ri
a 1&N & 1 000 000
a Pentru rezolvarea corect a primei cerinµe se obµin 60 de puncte, iar pentru rezolvarea corect
a celei de a doua cerinµe se acord 40 de puncte
Exemple
167
CAPITOLUL 15. ONI 2017 168
Pentru ecare cod de identicare se construie³te un num r natural în care pentru ecare
caracter din codul de identicare se ia poziµia p din ³irul 0123456789abcdefghij ³i se adaug
p
la num r valoarea 2 , astfel codurile de identicare care sunt formate din acelea³i caractere vor
avea asociat acela³i num r ³i în continuare se folose³te un vector de frecvenµe [0, 1, ..., 1 100 000],
1.100.000 % 2
20
.
2 12 3
De exemplu, pentru codul 2b3 se formeaz num rul 2 2 2 4 4096 8 4108 (în
baza 2 este 1000000001100), deci codurile 2b3 ³i 23b au asociat acela³i num r.
Cerinta 1
Se parcurge vectorul de frecvente, se g se³te valoarea maxim ³i la nal printr-o parcurgere
liniara a acestui vector se num r pe câte poziµii apare valoarea maxim .
Cerinta 2
Pentru ultimul cod de identicare se construie³te num rul asociat conform preciz rilor descrise
anterior ³i comparând acest num r cu celelalte numere asociate celorlalte coduri se veric dac
sunt coduri pereche cu ultimul cod (au aceea³i lungime ³i difer prin exact un caracter).
1 #include <cstdio>
CAPITOLUL 15. ONI 2017 169
2 #include <cstdlib>
3 #include <cassert>
4 #include <cstring>
5 #include <cctype>
6
7 #define Nmax 1300000
8
9 using namespace std;
10
11 int A[Nmax], poz, j, P, N, K, l, k, x,Max, nMax, y, S=0;
12 int i, mx, n, cx, ed, nrC=0, C, mp, np, ngen, nm, Vmax, nr, nc, cmx, mu, nu;
13 char s[25];
14
15 int main()
16 {
17 freopen("carte.in", "r", stdin);
18 freopen("carte.out","w", stdout);
19
20 scanf("%d\n%d\n",&C,&N);
21
22 assert(0 < N && N<=1000000);
23
24 for( i = 1; i <= N; i++)
25 {
26 scanf("%s\n", &s);
27 n = strlen(s);
28 assert(0 < n && n <= 20);
29
30 mx = 0;
31 j = 0;
32 while(j < n)
33 {
34 assert(isdigit(s[j]) || isalpha(s[j]) && s[j]<=’j’);
35 if(isdigit(s[j]))
36 x=s[j]-’0’;
37 else
38 x=s[j]-’a’ + 10;
39 mx |= 1<<x;
40 ++j;
41 }
42
43 A[mx]++;
44 if(A[mx]==1)
45 ngen++;
46
47 if(A[mx] > Max)
48 Max = A[mx], nMax=1;
49 else
50 if(A[mx] == Max)
51 nMax++;
52
53 if(i==N) {mu = mx; nu = n;}
54 if(mx>Vmax) Vmax=mx;
55 }
56
57 if(C==1)
58 printf("%d\n%d\n", Max, nMax);
59 else
60 {
61 for(mx = 0; mx <= Vmax; mx++)
62 if(A[mx])
63 {
64 ed = mu ^ mx;
65 nc=0;
66 do
67 {
68 ed &= ed-1;
69 nc++;
70 } while (ed);
71
72 nr=0;
73 cmx = mx;
74 do
75 {
76 cmx&= cmx-1;
77 nr++;
CAPITOLUL 15. ONI 2017 170
78 } while (cmx);
79
80 if(nr==nu && nc==2)
81 nrC+=A[mx];
82 }
83
84 printf("%d\n", nrC);
85 }
86
87 return 0;
88 }
15.2 ghinde
Problema 2 - ghinde 100 de puncte
Scrat ³i Scratte sunt dou veveriµe devoratoare de ghinde. Ele tr iesc într-un stejar înalt ³i
culeg ghinde din cele N ramuri ale acestuia. Veveriµele vor organiza un concurs: cine culege cele
mai multe ghinde în K ture. într-o tur , ecare veveriµ se va deplasa de la vizuin pân la o
ramur a stejarului, de unde va culege cât mai multe ghinde, dar nu mai mult de M ghinde, dup
care va reveni în vizuin . Veveriµele vor efectua alternativ ecare câte K ture, prima care începe
ind Scratte.
Sup rat c la concurs nu va începe primul, Scrat decide s se antreneze separat ³i s vad câte
ghinde ar culege în K ture, dac ar singur.
Cerinµe
S se realizeze un program care determin :
1) Câte ghinde culege Scrat în timpul antrenamentului;
2) Câte ghinde a cules ecare veveriµ pe durata concursului.
Date de intrare
Pe prima linie a ³ierului ghinde.in se a un num r natural C . Pentru toate testele, C poate
lua numai valorile 1 sau 2.
Pe a doua linie se g sesc numerele N, M ³i K reprezentând num rul de ramuri ale stejarului,
num rul maxim de ghinde culese la o tur , respectiv num rul de ture.
Pe urm toarele N linii se g sesc num rul de ghinde de pe ecare ramur în parte.
Date de ie³ire
Dac valoarea lui C este 1, se va rezolva numai punctul 1) din cerinµe. în acest caz, ³ierul de
ie³ire ghinde.out va conµine num rul total de ghinde cules în timpul antrenamentului de Scrat.
Dac valoarea lui C este 2, se va rezolva numai punctul 2) din cerinµe. în acest caz, ³ierul
de ie³ire ghinde.out va conµine pe aceea³i linie dou numere naturale, separate printr-un spaµiu,
reprezentând în ordine, num rul de ghinde culese de Scratte respectiv Scrat, pe durata concursului.
Restricµii ³i preciz ri
a 1 & N & 500 000
a 1 & K & 2 000 000 000
a 1 & M & 500 000
a 0 & num rul de ghinde de pe o ramur & 500 000
a Pentru rezolvarea corect a primei cerinµe se obµin 20 de puncte, iar pentru rezolvarea corect
a celei de a doua cerinµe se obµin 80 puncte.
Exemple
CAPITOLUL 15. ONI 2017 171
26 if(C == 1)
27 {
28 if(nr>=K)
29 {
30 g<<1LL*K*M<<’\n’ ;
31 return 0;
32 }
33
34 K -= nr;
35 rez =1LL * nr * M;
36
37 for(j= M-1; j && K;)
38 if(a[j])
39 rez += j, K--, a[j]--;
40 else
41 j--;
42
43 g<< rez <<’\n’ ;
44 return 0;
45 }
46
47 if(nr >= 2*K)
48 {
49 g<< 1LL*K*M <<" "<< 1LL*K*M <<’\n’ ;
50 return 0;
51 }
52
53 rez1 = (nr+1)/2*M;
54 rez2 = nr/2*M;
55 K = 2*K - nr;
56
57 for(j=M-1; j>0 && K;)
58 if(K%2==0)
59 if(a[j])
60 rez1 += j, a[j]--, K--;
61 else
62 j--;
63 else
64 if(a[j])
65 rez2 += j, a[j]--, K--;
66 else
67 j--;
68
69 g<< rez1 <<" "<< rez2 <<’\n’ ;
70
71 return 0;
72 }
15.3 submat
Problema 3 - submat 100 de puncte
Se consider o matrice A având N linii ³i N coloane. Elementele acesteia aparµin mulµimii
r0, 1, 2x. Pe ecare linie ³i pe ecare coloan valorile elementelor sunt dispuse cresc tor.
Fie dou elemente din matrice situate pe linia i1 ³i coloana j1 respectiv i2 ³ij2 , unde i1 & i2
³i j1 & j2 . O submatrice a lui A, având colµurile stânga-sus ³i dreapta-jos în i1 , j1 ³i i2 , j2 ,
este format din toate elementele situate pe linii cuprinse între i1 ³i i2 , inclusiv, ³i coloane între
j1 ³i j2 , inclusiv. Numim submatrice constant o submatrice a matricei A, având toate elementele
egale.
Cerinµe
Realizaµi un program care determin num rul maxim K de elemente pe care îl are o submatrice
constant a lui A ³i num rul submatricilor constante formate din K elemente.
Date de intrare
În ³ierul submat.in pe prima linie se g se³te num rul natural N. Pe urm toarele N linii
câte o pereche de numere naturale, desp rµite printr-un spaµiu:
- Primul num r de pe linia i1 din ³ier reprezint num rul de ordine al primei coloane de
pe linia i din matricea A, unde elementul este egal cu 1. Dac pe linia i nu apare niciun element
egal cu 1, acest num r are valoarea 0.
CAPITOLUL 15. ONI 2017 173
- Al doilea num r de pe linia i1 din ³ier reprezint num rul de ordine al primei coloane de
pe linia i din matricea A, unde elementul este egal cu 2. Dac pe linia i nu apare niciun element
egal cu 2, acest num r are valoarea 0.
Date de ie³ire
Fi³ierul de ie³ire submat.out va conµine pe prima linie o pereche de numere naturale separate
printr-un spaµiu, reprezentând, în ordine, num rul maxim de elemente pe care îl are o submatrice
constant a lui A, respectiv num rul submatricilor constante formate din acest num r maxim de
elemente determinat.
Restricµii ³i preciz ri
a 1&N & 5 000
a Consider m liniile ³i coloanele matricei A numerotate de la 1 la N.
Exemple
submat.in submat.out Explicaµii
8 12 6 Matricea corespunz toare ³iereului de intrare este:
4 0 0 0 0 1 1 1 1 1
4 8 0 0 0 1 1 1 1 2
4 8 0 0 0 1 1 1 1 2
3 7 0 0 1 1 1 1 2 2
3 6 0 0 1 1 1 2 2 2
3 5 0 0 1 1 2 2 2 2
2 3 0 1 2 2 2 2 2 2
0 2 0 2 2 2 2 2 2 2
Num rul maxim de elemente al unei submatrici constante este
12.
Sunt 6 submatricile constante formate din 12 elemente, respec-
tiv cele având colµurile în: (1,1) ³i (6,2); (1,4) ³i (4,6); (1,4) ³i
(3,7); (5,6) ³i (8,8); (7,3) ³i (8,8); (6,5) ³i (8,8).
Stelian Ciurea
Pentru început determin m submatricea cu num r maxim de elemente egale cu 2, apoi subma-
tricea cu num r maxim de elemente egale cu 0. Datorit particularit µii matricei (valori cresc toare
pe ecare linie ³i pe ecare coloan ), aceste determin ri se pot face în O n, parcurgând cele dou
³iruri de intrare.
1 //#include <cstdio>
2 #include <fstream>
3 #include <algorithm>
4
5 #define nmax 5002
6
7 using namespace std;
8
9 ifstream f("submat.in");
10 //FILE * f = fopen("submat.in","rt");
11
12 ofstream g("submat.out");
13 //FILE * g = fopen("submat.out","wt");
14
15 int primacoloana1[nmax];
16 int primacoloana2[nmax];
17
18 int n,nrelemax=1,i,ctmax,nrelemcrt,j,poz;
19 int inaltime,latime;
20 int xi1, xi2, xj1, xj2;
21
22 int main()
23 {
24 f >> n;
25 //fscanf(f,"%ld",&n);
26
27 for (i=1;i<=n;i++)
28 f >> primacoloana1[i] >> primacoloana2[i];
29 //fscanf(f,"%ld%ld",&primacoloana1[i],&primacoloana2[i]);
30
31 for (i=1;i<=n;i++)
32 {
33 if (primacoloana2[i]==0)
34 continue;
35
36 latime = n - primacoloana2[i] + 1;
37 inaltime = n - i + 1;
38 nrelemcrt = inaltime * latime;
39
40 if (nrelemcrt > nrelemax)
41 {
42 nrelemax = nrelemcrt;
43 ctmax=0;
44 }
45
46 if (nrelemcrt == nrelemax)
47 {
48 ctmax++;
49 }
50 }
51 //cout << nrelemax << ’ ’ << ctmax << endl;
52
53 for (i=n; i>=1;i--)
54 {
55 if (primacoloana1[i]==0 && primacoloana2[i]==0)
56 latime = n;
57 else
58 if (primacoloana1[i]==0 && primacoloana2[i]!=0)
59 latime = primacoloana2[i]-1;
60 else
61 latime = primacoloana1[i]-1;
62
63 inaltime = i;
64 nrelemcrt = inaltime * latime;
65 //cout << i << ’ ’ << nrelemcrt << endl;
66
67 if (nrelemcrt > nrelemax)
68 {
69 nrelemax = nrelemcrt;
70 poz = i;
CAPITOLUL 15. ONI 2017 175
71 ctmax=0;
72 }
73
74 if (nrelemcrt == nrelemax)
75 {
76 ctmax++;
77 }
78 }
79 //cout << nrelemax << ’ ’ << ctmax << endl;
80
81 primacoloana1[i]=0;
82 for (i=1;i<=n;i++)
83 {
84 if (primacoloana1[i]==primacoloana1[i-1])
85 continue;
86
87 if (primacoloana1[i]==0)
88 continue;
89
90 xi1 = primacoloana1[i];
91
92 if (primacoloana2[i]!=0)
93 xi2 = primacoloana2[i] - 1;
94 else
95 xi2 = n;
96
97 int hmin = nrelemax / (xi2 - xi1 + 1);
98 // cout << i << ’ ’ << hmin << endl;
99
100 for (j=max(i,i+hmin-1);j<=n;j++)
101 {
102 if (primacoloana1[j]==0)
103 break;
104
105 inaltime = j - i + 1;
106 xj1 = primacoloana1[j];
107 if (primacoloana2[j]!=0)
108 {
109 if (primacoloana2[j]<primacoloana1[i])
110 break;
111 xj2 = primacoloana2[j] - 1;
112 }
113 else
114 xj2 = n;
115
116 //cout << i << ’ ’ << j << ’ ’<< xi1 << ’ ’<< xi2 << ’ ’
117 // << xj1 << ’ ’ << xj2 <<endl;
118
119 latime = min(xi2,xj2) - max (xi1, xj1) + 1;
120 //cout << inaltime << ’ ’<< latime << endl;
121
122 nrelemcrt = inaltime * latime;
123 if (nrelemcrt > nrelemax)
124 {
125 nrelemax = nrelemcrt;
126 ctmax=0;
127 }
128 if (nrelemcrt == nrelemax)
129 {
130 ctmax++;
131 }
132 }
133 }
134
135 //cout << nrelemax << ’ ’ << ctmax << endl;
136 g << nrelemax << ’ ’ << ctmax << endl;
137 //fprintf(g,"%ld %ld\n",nrelemax,ctmax);
138 }
Capitolul 16
ONI 2016
16.1 birouri
Problema 1 - birouri 100 de puncte
Arhi ³i-a propus s extind cl direa de birouri pe care a proiectat-o
iniµial pe un singur nivel numerotat cu 1, împ rµit în n n zone p tra-
tice de latur 1, ecare corespunzând unui birou, prin construirea mai
multor niveluri. În colµurile tuturor birourilor se construiesc grinzi de
rezistenµ . Pentru a asigura rezistenµa întregii cl diri, Arhi va proiecta
niveluri noi, numerotate cu 2, 3, ... atât timp cât conµin cel puµin un
birou ³i sunt respectate urm toarele patru reguli:
R1: ecare nivel nou va proiectat sub forma unui dreptunghi sau Figura 16.1: birouri
p trat de arie maxim pentru nivelele cu num r impar, respectiv, sub forma unui p trat de arie
maxim pentru nivelele cu num r par;
R2: ecare dintre colµurile zidurilor unui nivel nou trebuie plasat pe câte o grind de rezistenµ
dintre dou sau mai multe birouri de pe nivelul precedent;
R3: oricare dou dintre colµurile zidurilor unui nivel nou vor plasate pe ziduri diferite (un
zid nu se poate suprapune în totalitate pe alt zid) ³i cel puµin dou vârfuri opuse ale unui nivel
nou se vor aa pe ziduri opuse ale nivelului precedent;
R4: orice porµiune de zid de pe nivelul k (k % 1), construit deasupra unui birou de pe nivelul
k 1, se va suprapune exact peste una dintre laturile biroului, sau îl va str bate în diagonal .
Birourile de pe nivelul k (k % 1), vor construite exact deasupra celor de pe nivelul precedent,
astfel, nivelurile 2, 4 etc. vor avea lâng ziduri spaµii triunghiulare care nu vor aparµine niciunui
birou.
Numerele inscripµionate pe birouri în imaginea de mai sus, indic nivelul corespunz tor biro-
urilor vizibile de deasupra cl dirii.
Cerinµe
Cunoscându-se lungimea n a laturii primului nivel al cl dirii, s se determine:
1. num rul maxim de niveluri pe care le poate avea cl direa;
2. num rul total de birouri ale cl dirii cu num r maxim de niveluri.
Date de intrare
Fi³ierul de intrare birouri.in conµine pe prima linie una dintre valorile 1 sau 2, reprezentând
cerinµa 1, dac se cere determinarea num rului maxim de niveluri pe care le poate avea cl direa,
respectiv cerinµa 2, dac se cere determinarea num rului total de birouri al cl dirii cu num r
maxim de niveluri.
Linia a doua conµine un num r natural n (reprezentând lungimea ec rui zid al primului nivel
al cl dirii).
Date de ie³ire
176
CAPITOLUL 16. ONI 2016 177
Fi³ierul de ie³ire birouri.out conµine pe prima linie un num r natural reprezentând num rul
maxim de niveluri pe care le poate avea cl direa, dac cerinµa a fost 1, respectiv un num r natural
reprezentând num rul total de birouri ale cl dirii cu num r maxim de niveluri, dac cerinµa a fost
2.
Restricµii ³i preciz ri
a 3 & n & 32768
a Pentru rezolvarea corect a cerinµei 1 se acord 30% din punctaj, iar pentru rezolvarea
corect a cerinµei 2 se acord 70% din punctaj.
Exemple
birouri.in birouri.out Explicaµii
1 5 Exemplul corespunde imaginii de mai sus. Cl direa cu nivelul
10 de la baz de latur 10 va avea 5 niveluri.
Nivelul 6 nu se mai construie³te, deoarece nu ar conµine niciun
birou.
2 172 Cl direa cu 5 niveluri ³i latura de la baz de lungime 10 are:
10 - pe primul nivel 100 birouri;
- pe nivelul doi 40 birouri;
- pe nivelul trei 24 birouri;
- pe nivelul patru 4 birouri;
- pe nivelul cinci 4 birouri.
100 + 40 + 24 + 4 + 4 = 172
1 #include <iostream>
2 #include <fstream>
3
4 #define in "birouri.in"
5 #define ou "birouri.out"
6
7 using namespace std;
8
CAPITOLUL 16. ONI 2016 178
1 #include <fstream>
2
3 using namespace std;
4
5 ifstream f("birouri.in");
6 ofstream g("birouri.out");
7
8 int n,v,h,m;
9 long long p;
10
11 int main()
12 {
CAPITOLUL 16. ONI 2016 179
13 f>>v>>n;
14 m=n;
15 if(n&1)
16 {
17 h=1;
18 p=n*n;
19 }
20 else
21 while((n&1)+(m&1)<2)
22 {
23 p+=n*m;
24 h++;
25 n=min(n,m);
26 m=n=n/2;
27 if(n>=2)
28 {
29 p+=2*(n-1)*n;
30 h++;
31 if(n&1)
32 { m=n+1;
33 n--;
34 }
35 }
36 }
37
38 if(v==1)
39 g<<h<<’\n’;
40 else
41 g<<p<<’\n’;
42
43 f.close();
44 g.close();
45 return 0;
46 }
1 #include <fstream>
2
3 using namespace std;
4
5 int n,m,k, c, niv, b,p;
6
7 ifstream in("birouri.in");
8 ofstream out("birouri.out");
9
10 int main()
11 {
12 in>>c>>n;m=n;
13 do
14 {
15 niv++;
16 if(niv%2)
17 b+=n*m;
18 else
19 {
20 k=n>m?m:n;
21 p=k*k/2-k;b+=p;
22 if(!p)niv--;
23 if (k%4==0)
24 n=m=k/=2;
25 else
26 {
27 n=n/2-1;
28 m=n+2;
29 }
30 }
31 } while(n&&n%2==0);
32
33 if(c==1)
34 out << niv << endl;
35 else
36 out << b << endl;
37
38 return 0;
CAPITOLUL 16. ONI 2016 180
39 }
16.2 cristale
Problema 2 - cristale 100 de puncte
Pietrele preµioase au fascinat omenirea înc din timpuri str vechi iar cele mai
renumite dintre ele, cristalele, au devenit atât simbolul durit µii cât ³i al eternit -
µii. În urma unui studiu ³tiinµic, pe un e³antion de form dreptunghiular se pot
observa diferite tipuri de molecule, dispuse într-o geometrie perfect , pe M rânduri
a câte N molecule ecare, aliniate una lâng alta. O formaµiune cristalizabil este
alc tuit din 3 molecule de acela³i tip, învecinate dou câte dou , având una dintre cele patru
forme din imaginea al turat (g.1).
Cerinµe
1. Determinaµi num rul formaµiunilor cristalizabile ce pot identicate pe e³an-
tionul analizat.
2. A³aµi e³antionul rezultat dup cristalizare.
Date de intrare
Fi³ierul de intrare cristale.in conµine pe prima linie un num r natural c reprezentând cerinµa
care trebuie s e rezolvat (1 sau 2). Pe cea de-a doua linie se a dou numere naturale M ³i
N, separate printr-un spaµiu, având semnicaµia din enunµ. Pe urm toarele M linii se a câte N
numere naturale, separate prin câte un spaµiu, reprezentând moleculele din e³antionul analizat.
Date de ie³ire
Dac valoarea lui c este 1, atunci se va rezolva numai cerinµa 1, caz în care pe prima linie a ³i-
erului cristale.out va scris un num r natural reprezentând num rul formaµiunilor cristalizabile
identicate pe e³antionul analizat.
Dac valoarea lui c este 2, atunci se va rezolva numai cerinµa 2. în acest caz, ³ierul de ie³ire
cristale.out va conµine pe ecare dintre primele M linii, câte N numere naturale separate prin
câte un spaµiu, reprezentând moleculele e³antionului rezultat dup cristalizare.
Restricµii ³i preciz ri
a 4 & M, N & 800 ³i tipul ec rei molecule este exprimat printr-un num r natural din intervalul
1, 16;
a pe marginea e³antionului nu pot identicate formaµiuni cristalizabile;
a exist cel puµin o formaµiune cristalizabil pe e³antionul analizat;
a e³antionul nu conµine formaµiuni cristalizabile lipite (cu celule vecine pe una din cele patru
direcµii);
a pentru rezolvarea corect a cerinµei 1 se acord 30% din punctaj, iar pentru rezolvarea corect
a cerinµei 2 se acord 70% din punctaj.
Exemple
CAPITOLUL 16. ONI 2016 181
Pentru ecare dintre cele patru tipuri de formaµiuni posibil cristalizabile, se veric dac cele
³apte molecule care formeaz înveli³ul sunt de acela³i tip, diferit de cel al formaµiunii pe care o
înconjoar .
A³area tabloului se realizeaz succesiv, linie cu linie, pe m sur ce sunt actualizate valorile
acestuia.
1 #include <iostream>
2 #include <fstream>
3
4 #define Nmax 1501
5 #define in "cristale.in"
6 #define ou "cristale.out"
7
8 using namespace std;
9
10 short A[5][Nmax], m, n, c, i, j, tmp;
11 int NrC;
CAPITOLUL 16. ONI 2016 182
12
13 int main()
14 {
15 ifstream f(in);
16 ofstream g(ou);
17
18 int cate;
19 f>>c>>m>>n;
20 for(i=1; i<=4; ++i)
21 for(j=1; j<=n; ++j)
22 f>>A[i][j];
23
24 cate = m-4;
25 /*
26 if(c == 2)
27 {
28 for(j=1; j<=n; ++j)
29 g<<A[1][j]<<’ ’;
30 g<<’\n’;
31 }
32 */
33 while(cate>=0)
34 {
35 for(i=2; i<=3; ++i)
36 for(j=2; j<=n-2; ++j)
37 {
38 if( A[i][j] == A[i][j+1] &&
39 A[i][j] == A[i+1][j+1] &&
40 A[i][j] != A[i-1][j] ) //1
41 {
42 tmp = A[i-1][j];
43 if(A[i-1][j+1] == tmp && A[i][j-1] == tmp &&
44 A[i][j+2] == tmp && A[i+1][j] == tmp &&
45 A[i+1][j+2] == tmp && A[i+2][j+1] == tmp )
46 {
47 NrC++;
48 if(c <= 2) A[i][j] = A[i][j+1] = A[i+1][j+1] = tmp;
49 }
50
51 }
52 else
53 if( A[i][j] == A[i][j+1] && A[i][j] == A[i+1][j] &&
54 A[i][j] != A[i-1][j] ) //2
55 {
56 tmp = A[i-1][j];
57 if(A[i-1][j+1] == tmp && A[i][j-1] == tmp &&
58 A[i][j+2] == tmp && A[i+1][j-1] == tmp &&
59 A[i+1][j+1] == tmp && A[i+2][j] == tmp )
60 {
61 NrC++;
62 if(c <= 2) A[i][j] = A[i][j+1] = A[i+1][j] = tmp;
63 }
64 }
65 else
66 if( A[i][j] == A[i+1][j] && A[i][j] == A[i+1][j+1] &&
67 A[i][j] != A[i-1][j] ) //3
68 {
69 tmp = A[i-1][j];
70 if(A[i][j-1] == tmp && A[i][j+1] == tmp &&
71 A[i+1][j-1] == tmp && A[i+1][j+2] == tmp &&
72 A[i+2][j] == tmp && A[i+2][j+1] == tmp )
73 {
74 NrC++;
75 if(c <= 2) A[i][j] = A[i+1][j] = A[i+1][j+1] = tmp;
76 }
77 }
78 else
79 if( A[i][j+1] == A[i+1][j+1] && A[i][j+1] == A[i+1][j] &&
80 A[i][j+1] != A[i-1][j+1] ) //4
81 {
82 tmp = A[i-1][j+1];
83 if(A[i][j] == tmp && A[i][j+2] == tmp &&
84 A[i+1][j-1] == tmp && A[i+1][j+2] == tmp &&
85 A[i+2][j] == tmp && A[i+2][j+1] == tmp )
86 {
87 NrC++;
CAPITOLUL 16. ONI 2016 183
1 #include <fstream>
2
3 #define ML 801
4 #define MC 801
5
6 using namespace std;
7
8 short int p[5][MC],lc[MC],lu[MC];
9 int m,n,np;
10
11 ifstream f("cristale.in");
12 ofstream g("cristale.out");
13
14 int f1(int li, int co)
15 {
16 int cp,cf;
17 cp=p[li][co];
18 cf=p[li][co-1];
19 if((cp==p[li][co+1])&&
20 (cp==p[li+1][co+1])&&
21 (cp!=cf)&&
22 (cf==p[li-1][co])&&
23 (cf==p[li-1][co+1])&&
24 (cf==p[li][co+2])&&
25 (cf==p[li+1][co+2])&&
26 (cf==p[li+2][co+1])&&
27 (cf==p[li+1][co]) )
28 {
29 p[li][co]=p[li][co+1]=p[li+1][co+1]=cf;
30 return 1;
31 }
32
33 return 0;
34 }
35
CAPITOLUL 16. ONI 2016 184
112 }
113 }
114
115 void copiere_linii_peste_cele_vechi()
116 {
117 int j;
118 for(j=1;j<=n;j++)
119 {
120 p[1][j]=p[2][j];
121 p[2][j]=p[3][j];
122 p[3][j]=p[4][j];
123 }
124 }
125
126 int main()
127 {
128 int i,j,idf,k,c;
129
130 f>>c>>m>>n;
131 for(i=1;i<=4;i++)
132 for(j=1;j<=n;j++)
133 f>>p[i][j];
134
135 int nr_linii=3;
136
137 if(c==2)
138 {
139 for(j=1;j<=n-1;j++)
140 g<<p[1][j]<<’ ’;
141 g<<p[1][n];
142 }
143
144 do
145 {
146 i=2;
147 for (k=2;k<=n-1;k++) lu[k]=1;
148 {
149 for (k=2;k<=n-1;k++)
150 {
151 lc[k]=lu[k];
152 lu[k]=1;
153 }
154
155 for(j=2;j<=n-1;j++)
156 {
157 if(lc[j])
158 {
159 idf=1;
160 if(idf&&(j<n-1)&&f1(i,j))
161 {
162 np++;
163 lu[j]=lu[j+1]=lu[j+2]=0;
164 j+=2;
165 idf=0;
166 }
167
168 if(idf&&(j<n-1)&&f2(i,j))
169 {
170 np++;idf=0;
171 lu[j-1]=lu[j]=lu[j+1]=0;
172 j+=2;
173 }
174
175 if(idf&&(j<n-1)&&f3(i,j))
176 {
177 np++;idf=0;
178 lu[j-1]=lu[j]=lu[j+1]=lu[j+2]=0;
179 j+=1;
180 }
181
182 if(idf&&(j>2)&&f4(i,j))
183 {
184 np++;idf=0;
185 lu[j-2]=lu[j-1]=lu[j]=lu[j+1]=0;
186 j+=1;
187 }
CAPITOLUL 16. ONI 2016 186
188 }
189 }
190 }
191
192 if(c==2)
193 afis4_linii();
194
195 copiere_linii_peste_cele_vechi();
196
197 for(j=1;j<=n;j++)
198 f>>p[4][j];
199
200 nr_linii++;
201 i=1;
202 } while(nr_linii<m);
203
204 if(c==2)
205 {
206 for(i=2;i<=3;i++)
207 {
208 g<<’\n’;
209 for(j=1;j<=n-1;j++)
210 g<<p[i][j]<<’ ’;
211 g<<p[i][n];
212 }
213
214 g<<’\n’;
215 }
216 else
217 if(c==1)
218 g<<np<<’\n’;
219
220 return 0;
221 }
1 #include <iostream>
2 #include <fstream>
3
4 using namespace std;
5
6 char a[805][805],val;
7 int n,m,rez1,p;
8
9 ifstream f("cristale.in");
10 ofstream g("cristale.out");
11
12 void citeste()
13 {
14 f>>p>>n>>m;
15 int i,j,x;
16 for(i=1; i<=n;i++)
17 for(j=1;j<=m;j++)
18 {
19 f>>x;
20 a[i][j]=char(x+’0’);
21 }
22 }
23
24 int tip1( int i, int j)
25 { /// y y
26 /// y x x y
27 /// y x y
28 /// y
29
30 //short int val;
31 val=a[i+1][j];
32 if(a[i][j]!=val && a[i][j]==a[i][j+1] && a[i][j]==a[i+1][j+1]
33 && a[i-1][j]==val && a[i-1][j+1]==val && a[i][j-1]==val
34 && a[i][j+2]==val && a[i+1][j+2]==val && a[i+2][j+1]==val)
35 {
36 a[i][j]=a[i][j+1]=a[i+1][j+1]=a[i+1][j]=val;
37 return 1;
38 }
CAPITOLUL 16. ONI 2016 187
39
40 return 0;
41 }
42
43 int tip2( int i, int j)
44 { /// y y
45 /// y x x y
46 /// y x y
47 /// y
48
49 // short int
50 val=a[i+1][j+1];
51 if ( a[i][j]==a[i][j+1] && a[i][j]==a[i+1][j] && a[i][j]!=val
52 && a[i-1][j]==val && a[i-1][j+1]==val && a[i][j-1]==val
53 && a[i][j+2]==val && a[i+1][j-1]==val && a[i+2][j]==val )
54 {
55 a[i][j]=a[i][j+1]=a[i+1][j+1]=a[i+1][j]=val;
56 return 1;
57 }
58
59 return 0;
60 }
61
62 int tip3( int i, int j)
63 { /// y
64 /// y x y
65 /// y x x y
66 /// y y
67
68 // short int
69 val=a[i][j-1];
70 if ( a[i][j]==a[i+1][j-1] && a[i][j]==a[i+1][j] && a[i][j]!=val
71 && a[i-1][j]==val && a[i][j+1]==val&& a[i+1][j-2]==val
72 && a[i+1][j+1]==val && a[i+2][j]==val && a[i+2][j-1]==val )
73 {
74 a[i][j]=a[i+1][j]=a[i][j-1]=a[i+1][j-1]=val;
75 return 1;
76 }
77
78 return 0;
79 }
80
81 int tip4( int i, int j)
82 { /// y
83 /// y x y
84 /// y x x y
85 /// y y
86
87 // short int
88 val=a[i][j+1];
89 if ( a[i][j]==a[i+1][j+1] && a[i][j]==a[i+1][j] && a[i][j]!=val
90 && a[i-1][j]==val && a[i][j-1]==val && a[i+1][j-1]==val
91 && a[i+1][j+2]==val && a[i+2][j]==val && a[i+2][j+1]==val )
92 {
93 a[i][j]=a[i][j+1]=a[i+1][j+1]=a[i+1][j]=val;
94 return 1;
95 }
96
97 return 0;
98 }
99
100 void sol()
101 {
102 int i,j;
103 citeste();
104
105 for(i=2; i<=n-1;i++)
106 for(j=2;j<=m-1;j++)
107 if(tip1(i,j))
108 rez1++;
109 else
110 if(tip2(i,j))
111 rez1++;
112 else
113 if(tip3(i,j))
114 rez1++;
CAPITOLUL 16. ONI 2016 188
115 else
116 if(tip4(i,j))
117 rez1++;
118
119 if(p==1)
120 g<<rez1<<endl;
121 else
122 for(i=1; i<=n;i++)
123 {
124 for(j=1;j<=m;j++)
125 g<<a[i][j]-’0’<<" ";
126 g<<endl;
127 }
128 }
129
130 int main()
131 {
132 sol();
133 return 0;
134 }
1 #include <fstream>
2
3 using namespace std;
4
5 int v,m,n,i,j,cr;
6
7 ifstream f("cristale.in");
8 ofstream g("cristale.out");
9
10 short a[4][1502];
11
12 void muta()
13 {
14 int i,j;
15
16 for(i=0;i<4;i++)
17 for(j=0;j<n;j++)
18 a[i][j]=a[i+1][j];
19
20 for(j=0;j<n;j++)
21 f>>a[3][j];
22 }
23
24 void afis(int i)
25 {
26 for(int j=0;j<n;j++)
27 g<<a[i][j]<<’ ’;
28 g<<’\n’;
29 }
30
31 int este_cristal(int i, int j, int k)
32 {
33 int x=a[i-1][j];
34
35 switch(k)
36 {
37 case 1: return (j<n-2 && a[i][j]!=x && a[i-1][j+1]==x &&
38 a[i][j+2]==x && a[i+1][j+1]==x && a[i+2][j]==x &&
39 a[i+1][j-1]==x && a[i][j-1]==x);
40 case 2: return (j<n-2 && a[i][j]!=x && a[i-1][j+1]==x &&
41 a[i][j+2]==x && a[i+1][j+2]==x && a[i+2][j+1]==x &&
42 a[i+1][j]==x && a[i][j-1]==x);
43 case 3: return (j<n-2 && a[i][j]!=x && a[i][j+1]==x &&
44 a[i+1][j+2]==x && a[i+2][j+1]==x && a[i+2][j]==x &&
45 a[i+1][j-1]==x && a[i][j-1]==x);
46 case 4: return (j>1 && a[i][j]!=x && a[i][j+1]==x &&
47 a[i+1][j+1]==x && a[i+2][j]==x && a[i+2][j-1]==x &&
48 a[i+1][j-2]==x && a[i][j-1]==x);
49 }
50
51 return -1; // !!!
52 }
CAPITOLUL 16. ONI 2016 189
53
54 void numara(int i)
55 {
56 for(int j=1;j<n-1;j++)
57 if(a[i][j]-a[i][j+1]==0&&a[i][j]-a[i+1][j]==0)
58 cr+=este_cristal(i,j,1);
59 else
60 if(a[i][j]-a[i][j+1]==0 && a[i][j]-a[i+1][j+1]==0)
61 cr+=este_cristal(i,j,2);
62 else
63 if(a[i][j]-a[i+1][j]==0 && a[i][j]-a[i+1][j+1]==0)
64 cr+=este_cristal(i,j,3);
65 else
66 if(a[i][j]-a[i+1][j]==0 && a[i][j]-a[i+1][j-1]==0)
67 cr+=este_cristal(i,j,4);
68 }
69
70 void cristalizare(int i, int j, int k)
71 {
72 int x=a[i-1][j];
73
74 switch(k)
75 {
76 case 1:
77 {
78 if(j<n-2 && a[i][j]!=x && a[i-1][j+1]==x && a[i][j+2]==x &&
79 a[i+1][j+1]==x && a[i+2][j]==x && a[i+1][j-1]==x && a[i][j-1]==x)
80 a[i][j]=a[i][j+1]=a[i+1][j]=x;
81 break;
82 }
83 case 2:
84 {
85 if(j<n-2 && a[i][j]!=x && a[i-1][j+1]==x && a[i][j+2]==x &&
86 a[i+1][j+2]==x && a[i+2][j+1]==x && a[i+1][j]==x && a[i][j-1]==x)
87 a[i][j]=a[i][j+1]=a[i+1][j+1]=x;
88 break;
89 }
90 case 3:
91 {
92 if(j<n-2 && a[i][j]!=x && a[i][j+1]==x && a[i+1][j+2]==x &&
93 a[i+2][j+1]==x && a[i+2][j]==x && a[i+1][j-1]==x && a[i][j-1]==x)
94 a[i][j]=a[i+1][j]=a[i+1][j+1]=x;
95 break;
96 }
97 case 4:
98 {
99 if (j>1 && a[i][j]!=x && a[i][j+1]==x && a[i+1][j+1]==x &&
100 a[i+2][j]==x && a[i+2][j-1]==x && a[i+1][j-2]==x && a[i][j-1]==x)
101 a[i][j]=a[i+1][j]=a[i+1][j-1]=x;
102 break;
103 }
104 }
105 }
106
107 void cristalizeaza(int i)
108 {
109 for(int j=1;j<n-1;j++)
110 if(a[i][j]-a[i][j+1]==0&&a[i][j]-a[i+1][j]==0)
111 cristalizare(i,j,1);
112 else
113 if(a[i][j]-a[i][j+1]==0 && a[i][j]-a[i+1][j+1]==0)
114 cristalizare(i,j,2);
115 else
116 if(a[i][j]-a[i+1][j]==0 && a[i][j]-a[i+1][j+1]==0)
117 cristalizare(i,j,3);
118 else
119 if(a[i][j]-a[i+1][j]==0 && a[i][j]-a[i+1][j-1]==0)
120 cristalizare(i,j,4);
121 }
122
123 void solve1()
124 {
125 int i,j;
126
127 for(i=0;i<4;i++) for(j=0;j<n;j++)
128 f>>a[i][j];
CAPITOLUL 16. ONI 2016 190
129
130 numara(1);
131
132 while(i<m)
133 {
134 muta();
135 numara(1);
136 i++;
137 }
138
139 g<<cr<<’\n’;
140 }
141
142 void solve2()
143 {
144 int i, j;
145
146 for(i=0;i<4;i++)
147 for(j=0;j<n;j++)
148 f>>a[i][j];
149
150 cristalizeaza(1);
151 afis(0);
152 afis(1);
153
154 while(i<m) // i = ??? !!!
155 {
156 muta();
157 cristalizeaza(1);
158 afis(1);
159 i++;
160 }
161
162 afis(2);
163 afis(3);
164 }
165
166 int main()
167 {
168 f>>v>>m>>n;
169
170 if(v==1)
171 solve1();
172 else
173 solve2();
174
175 f.close();
176 g.close();
177 return 0;
178 }
16.3 parchet
Problema 3 - parchet 100 de puncte
Meseria de parchetar a devenit mai u³oar de când a ap rut parchetul laminat. Acesta se
2
livreaz în pl ci p tratice de câte 1 m ³i montarea lui este destul de u³oar . Gigel este convins
c este sucient de priceput s fac aceast operaµie în propria locuinµ . El dispune de planul
2
locuinµei ³i a cump rat o anumit cantitate reprezentând X m de parchet laminat. Planul
locuinµei este descris printr-un tablou bidimensional de dimensiuni N x M, ecare element al
2
tabloului reprezentând exact 1 m . Pereµii sunt reprezentaµi prin caracterul 'P' iar suprafeµele
camerelor prin caracterul 'S' (spaµiu).
În planul din gura al turat este descris o locuinµ cu 5 camere acestea având
2
respectiv, suprafeµele de 10, 2, 1, 3, 5 m .
Gigel nu este sigur de faptul c parchetul cump rat îi ajunge. Din aceast
cauz a hot rât iniµial s pun parchetul începând cu camera cea mai mare, apoi
în urm toarea, în ordinea descresc toare a suprafeµei ³i a³a mai departe, pân în
momentul în care parchetul r mas nu mai este sucient pentru acoperirea suprafeµei
urm toarei camere. Nu va l sa neparchetat o camer pentru a parcheta una cu
o suprafaµ mai mic . Gigel se mai gânde³te ³i la posibilitatea de a acoperi complet un num r
CAPITOLUL 16. ONI 2016 191
Cerinµe
Fiind date N , M , X ³i planul locuinµei s se determine:
2
1. num rul C de camere pe care a reu³it s le acopere Gigel ³i num rul R de m de parchet
care îi r mân, procedând a³a cum a hot rât iniµial;
2. num rul de posibilit µi de parchetare a unui num r maxim de camere, folosind întreaga
cantitate de parchet.
Date de intrare
Fi³ierul de intrare parchet.in conµine pe prima linie un num r natural p reprezentând cerinµa
care trebuie s e rezolvat (1 sau 2). Linia a doua a ³ierului de intrare conµine numerele naturale
N ³i M separate printr-un spaµiu. Pe linia a treia se a num rul natural X. Urm toarele N linii
¬ ¬ ¬ ¬
conµin câte M caractere P ³i S descriind planul locuinµei.
Date de ie³ire
Dac valoarea lui p este 1, atunci ³ierul de ie³ire parchet.out conµine pe prima linie dou
numere naturale C ³i R separate printr-un spaµiu, reprezentând respectiv num rul de camere
2
acoperite cu parchet ³i cantitatea de parchet r mas , exprimat în m . Dac valoarea lui p este
2, atunci pe prima linie a ³ierului de ie³ire se va scrie num rul de posibilit µi de parchetare a
unui num r maxim de camere folosind întreaga cantitate de parchet, respectiv valoarea 0 în cazul
în care acest lucru nu este posibil.
Restricµii ³i preciz ri
a 2 & N, M & 250
a În cas sunt maxim 20 de camere ³i casa are pereµi spre exterior.
2
a Suprafaµa unei camere nu dep ³e³te N 2 M 2 m .
a Pentru rezolvarea corect a cerinµei 1 se acord 50% din punctaj, iar pentru rezolvarea
corect a cerinµei 2 se acord 50% din punctaj.
Exemple
parchet.in parchet.out Explicaµii
1 3 1 Se va rezolva doar cerinµa 1.
2
7 9 Locuinµa are 5 camere având suprafeµele de 10, 2, 1, 3, 5 m .
19 Pot parchetate complet 3 camere consumând 18 = 10+5+3
2 2
PPPPPPPPP m . R mâne 1 m de parchet nefolosit.
PSSSPSPSP
PSSSPSPPP
PSSPPPPSP
PSPPSSPSP
PSPSSSPSP
PPPPPPPPP
2 1 Se va rezolva doar cerinµa 2.
7 9 Dac se aleg camerele cu suprafeµele 10, 1, 3, 5 va folosit
19 întreaga suprafaµ de parchet. Exist o singur posibilitate de
PPPPPPPPP a selecta un num r maxim de camere.
PSSSPSPSP
PSSSPSPPP
PSSPPPPSP
PSPPSSPSP
PSPSSSPSP
PPPPPPPPP
Se procedeaz la fel ca la soluµia 1, dar determinarea suprafeµei ec rei camere se face astfel:
Vom memora într-un tablou bidimensional A, pentru ecare poziµie liber , num rul camerei
din care face parte acea poziµie.
În cazul în care o camer are o form neregulat (nu este un simplu dreptunghi), constat m c
aceasta va conµine mai multe zone, marcate cu numere diferite. Va trebui s realiz m o operaµie
de lipire a acestor zone pentru a calcula suprafaµa total a camerei.
Putem utiliza un tablou unidimensional C, unde C i reprezint valoarea folosit la marcarea
camerei i, iniµial C i i.
Printr-o simpl parcurgere a elementelor tabloului A, dac identic m în aceea³i camer dou
poziµii vecine marcate diferit, atunci vom trece la comasarea celor dou zone, modicând valorile
corespunz toare din tabloul C.
Procedeul se realizeaz în complexitate p tratic ³i nu necesit utilizarea unor structuri de
date complexe ori a unor algoritmi de umplere recursivi.
92 ok = k;
93 }
94
95 A[ii][jj] = NrCam;
96 sup++;
97 ii++;
98 jj = ok;
99 }
100
101 S[NrCam] = sup;
102 }
103
104 ofstream g(ou);
105
106 //unesc camerele
107 for(i=1; i<=NrCam; ++i)
108 C[i] = i;
109 for(i=2; i<n; ++i)
110 for(j=2; j<m; ++j)
111 {
112 if( A[i][j] != -1 && A[i-1][j] != -1 &&
113 A[i][j] != A[i-1][j] && C[ A[i][j] ] != C [ A[i-1][j] ] )
114 uneste( C[ A[i][j] ], C[ A[i-1][j] ]);
115
116 if( A[i][j] != -1 && A[i][j+1] != -1 &&
117 A[i][j] != A[i][j+1] && C[ A[i][j] ] != C [ A[i][j+1] ] )
118 uneste( C[ A[i][j] ], C[ A[i][j+1] ]);
119
120 if( A[i][j] != -1 && A[i+1][j] != -1 &&
121 A[i][j] != A[i+1][j] && C[ A[i][j] ] != C [ A[i+1][j] ] )
122 uneste( C[ A[i][j] ], C[ A[i+1][j] ]);
123
124 if( A[i][j] != -1 && A[i][j-1] != -1 &&
125 A[i][j] != A[i][j-1] && C[ A[i][j] ] != C [ A[i][j-1] ] )
126 uneste( C[ A[i][j] ], C[ A[i][j-1] ]);
127 }
128
129 for(i=1; i<=1000; ++i)
130 ST[i] = 0;
131 for(i=1; i<=NrCam; ++i)
132 ST[C[i]] = S[i];
133
134 //sortez descrescator
135 for(i=1; i<1000; ++i)
136 for(j=i+1; j<=1000; ++j)
137 if(ST[i]<ST[j])
138 t = ST[i], ST[i] = ST[j], ST[j] = t;
139
140 while( ST[NrCam] == 0)
141 NrCam--;
142
143 for(i=1; i<=NrCam; ++i)
144 S[i] = ST[i];
145
146 //cerinta 1
147 pus = 0;
148 cam = 0;
149 while(pus <= p && S[cam+1] <= p-pus)
150 pus +=S[cam+1], cam++;
151
152 if( v == 1)
153 {
154 if(NrCam == 1 && S[1]<=p)
155 g<<1<<’ ’<<p-pus<<’\n’;
156 else
157 g<<cam<<’ ’<<p-pus<<’\n’;
158 }
159
160 if( v == 2)
161 {
162 //cerinta 2
163 putere = 1;
164 pus = 0;
165 for(i=1; i<=NrCam; ++i)
166 x[i] = 0, putere *=2, pus +=S[i] ;
167
CAPITOLUL 16. ONI 2016 195
168 putere/=2;
169
170 if(pus == p)
171 g<<"1\n";
172 else
173 {
174 maxim = 0; nrmaxim = 0;
175 for(k = 1; k<putere; ++k)
176 {
177 t = 1;
178 pus = 0;
179 for(j=1; j<=NrCam && t; ++j)
180 ii = x[j] + t, x[j] = ii % 2, t = ii / 2;
181
182 nr = 0;
183 for(j=NrCam; j>=1; --j)
184 if(x[j]==1)
185 pus += S[j], nr++;
186
187 if(pus == p)
188 if(nr > maxim)
189 maxim = nr, nrmaxim = 1;
190 else
191 if(nr == maxim)
192 nrmaxim++;
193
194 nr = 0;
195 pus = 0;
196 for(j=NrCam; j>=1; --j)
197 if(x[j]==0)
198 pus += S[j], nr++;
199
200 if(pus == p)
201 if(nr > maxim)
202 maxim = nr, nrmaxim = 1;
203 else
204 if(nr == maxim)
205 nrmaxim++;
206 }
207
208 g<<nrmaxim<<endl;
209 }
210 }
211
212 g.close();
213 return 0;
214 }
26 }
27
28 void numara(int t)
29 {
30 for(int v=0;v<=1;v++)
31 {
32 nr[t]=nr[t-1]+v;
33 sum[t]=sum[t-1]+v*c[t];
34 if(sum[t]==P)
35 if(nr[t]>numar)
36 {
37 numar=nr[t];
38 cate=1;
39 }
40 else
41 {
42 if(nr[t]==numar)
43 cate++;
44 }
45 else
46 if(t<k && sum[t]<P)
47 numara(t+1);
48 }
49 }
50
51 int main()
52 {
53 f>>cer>>n>>m>>P;
54
55 for(i=0;i<n;i++)
56 {
57 f>>a[i];
58 for(j=1;j<m-1;j++)
59 if(a[i][j]==’S’)
60 nrp++;
61 }
62
63 if(nrp==(n-2)*(m-2))
64 if(cer==1)
65 {
66 g<<1<<’ ’;
67 if(P>=nrp)
68 g<<P-nrp<<’\n’;
69 else
70 g<<P<<’\n’;
71 }
72 else
73 if(P!=nrp)
74 g<<0<<’\n’;
75 else
76 g<<1<<’\n’;
77 else
78 {
79 for(i=1;i<n-1;i++)
80 for(j=1;j<m-1;j++)
81 if(a[i][j]==’S’)
82 {
83 cate=0;
84 sterge(i,j);
85 c[++k]=cate;
86 }
87
88 sort(c+1,c+k+1);
89
90 i=k;
91 while(i>0 && p+c[i]<=P)
92 {
93 p=p+c[i];
94 i--;
95 }
96
97 if(cer==1)
98 g<<k-i<<’ ’<<P-p<<’\n’;
99 else
100 {
101 cate=0;
CAPITOLUL 16. ONI 2016 197
62
63 return S;
64 }
65
66 void Suprafete_camere()
67 {
68 int i, j;
69 for (i = 2; i < N; ++i)
70 for (j = 2; j < M; ++j)
71 if (Casa[i][j] == 0) //camera goala - inca neprelucrata
72 {
73 nr_camere++;
74 Camere[nr_camere] = Suprafata(i, j, nr_camere);
75 }
76 }
77
78 int Criteriu(int A, int B)
79 {
80 return A > B;
81 }
82
83 void Cerinta_a()
84 {
85 int SS = S, i = 1;
86 int Cate_se_parcheteaza = 0;
87
88 sort(Camere + 1, Camere + nr_camere + 1, Criteriu);
89
90 while (i <= nr_camere && SS >= Camere[i])
91 {
92 Cate_se_parcheteaza++;
93 SS -= Camere[i];
94 i++;
95 }
96
97 fout << Cate_se_parcheteaza << ’ ’ << SS << ’\n’;
98 }
99
100 void Cerinta_b()
101 {
102 int Contor = 0, nrsel, NRSEL = 0, Suprafata, i;
103 int b2 = 0, b2max = 1 << nr_camere;
104
105 while (b2 < b2max)
106 {
107 b2++;
108 Suprafata = 0;
109 nrsel = 0;
110
111 for (i = 0; i < nr_camere; i++)
112 if (b2 & (1 << i))
113 {
114 Suprafata += Camere[i + 1];
115 nrsel++;
116 }
117
118 if (Suprafata == S)
119 {
120 if (nrsel > NRSEL)
121 {
122 NRSEL = nrsel;
123 Contor = 1;
124 }
125 else
126 if (nrsel == NRSEL)
127 Contor++;
128 }
129 }
130
131 fout << Contor << ’\n’;
132 }
133
134 int main()
135 {
136 Citire();
137 Suprafete_camere();
CAPITOLUL 16. ONI 2016 199
138 if (Cerinta == 1)
139 Cerinta_a();
140 else
141 Cerinta_b();
142 return 0;
143 }
67 {
68 int i, j;
69 for (i = 2; i < N; ++i)
70 for (j = 2; j < M; ++j)
71 if (Casa[i][j] == 0) // camera goala - inca neprelucrata
72 {
73 nr_camere++;
74 Camere[nr_camere] = Suprafata(i, j, nr_camere);
75 }
76 }
77
78 int Criteriu(int A, int B)
79 {
80 return A > B;
81 }
82
83 void Cerinta_a()
84 {
85 int SS = S, i = 1;
86 int Cate_se_parcheteaza = 0;
87
88 sort(Camere + 1, Camere + nr_camere + 1, Criteriu);
89
90 while (i <= nr_camere && SS >= Camere[i])
91 {
92 Cate_se_parcheteaza++;
93 SS -= Camere[i];
94 i++;
95 }
96
97 if (Cerinta == 1)
98 fout << Cate_se_parcheteaza << ’ ’ << SS << ’\n’;
99 }
100
101 void Cerinta_b()
102 {
103 int Contor = 0, nrsel, NRSEL = 0, Suprafata, i;
104 int b2[100] = {0};
105
106 while (!b2[0])
107 {
108 i = nr_camere;
109
110 while (b2[i])
111 b2[i--] = 0;
112
113 b2[i] = 1;
114 Suprafata = 0;
115 nrsel = 0;
116 for (i = 1; i <= nr_camere; i++)
117 if (b2[i])
118 {
119 Suprafata += Camere[i];
120 nrsel++;
121 }
122
123 if (Suprafata == S)
124 {
125 if (nrsel > NRSEL)
126 {
127 NRSEL = nrsel;
128 Contor = 1;
129 }
130 else
131 if (nrsel == NRSEL)
132 Contor++;
133 }
134 }
135
136 if (Cerinta == 2)
137 fout << Contor << ’\n’;
138 }
139
140 int main()
141 {
142 Citire();
CAPITOLUL 16. ONI 2016 201
143 Suprafete_camere();
144
145 Cerinta_a();
146 Cerinta_b();
147
148 return 0;
149 }
Capitolul 17
ONI 2015
17.1 cript
Problema 1 - cript 100 de puncte
Ilinca a citit despre criptarea mesajelor, acum dore³te s comunice cu prietena ei Miruna numai
prin mesaje criptate folosind un sistem propriu de criptare.
Ilinca ³tie c ecare caracter se reprezint în memoria calculatorului pe 8 biµi, în care se
memoreaz scrierea în baza 2 a codului ASCII al caracterului respectiv.
Pentru a cripta caracterul, Ilinca folose³te o matrice p tratic având 8 linii (numerotate de la
0 la 7 de sus în jos) ³i 8 coloane (numerotate de la 0 la 7 de la stânga la dreapta). Pe prima linie
a matricei Ilinca scrie cei 8 biµi reprezentând scrierea în baza 2 a codului ASCII al caracterului,
pe poziµia 0 ind scris cifra cea mai semnicativ (corespunz toare lui 27). Pe ecare dintre
urm toarele 7 linii din matrice scrie permutarea circular cu o poziµie la stânga a liniei anterioare.
Ordoneaz lexicograc liniile matricei formate ³i dene³te cript-ul caracterului ca ind succesiunea
de biµi reprezentat de ultima coloan din matrice, parcurs de sus în jos, urmat de indicele liniei
din matrice pe care a ajuns dup ordonarea lexicograc reprezentarea în baza 2 a codului ASCII
al caracterului. Dac exist linii egale în matrice, dup ordonarea lexicograc acestea î³i vor
p stra ordinea relativ iniµial , astfel c linia conµinând reprezentarea în baza 2 a codului ASCII
al caracterului va prima dintre acestea.
Pentru a cripta un mesaj, Ilinca scrie în ordine cript-urile caracterelor din mesajul respectiv.
Miruna cunoa³te sistemul de criptare al Ilinc i, ca urmare ³tie s decripteze mesajele primite.
Cerinµe
Scrieµi un program care s rezolve urm toarele dou cerinµe:
1. cite³te un mesaj ³i a³eaz mesajul criptat conform sistemului Ilinc i;
2. cite³te un mesaj criptat conform sistemului Ilinc i ³i determin mesajul decriptat.
Date de intrare
Fi³ierul de intrare cript.in conµine pe prima linie un num r natural c, care poate 1 sau
2, reprezentând cerinµa ce urmeaz a rezolvat . Pe a doua linie a ³ierului se a un ³ir de
caractere.
Date de ie³ire
Fi³ierul de ie³ire cript.out va conµine o singur linie pe care va scris criptarea ³irului din
³ierul de intrare (dac c 1), respectiv decriptarea ³irului din ³ierul de intrare (dac c 2).
Restricµii ³i preciz ri
a Lungimea mesajului necriptat este nenul ³i nu dep ³e³te 30000.
a Caracterele din ³irul citit au coduri cuprinse între 32 ³i 127.
a Spunem c ³irul s1 preced în ordinea lexicograc ³irul s2 dac exist o poziµie k astfel
încât s1i s2i pentru orice i$k ³i s1k $ s2k .
a Pentru teste valorând 50% din punctaj cerinµa este 1.
202
CAPITOLUL 17. ONI 2015 203
Exemple
cript.in cript.out Explicaµii
1 100010004101000004 Caracterul 'A' are codul ASCII 65 reprezentarea
AB pe 8 biµi ind 01000001
Matricea permut rilor circulare este în stânga, iar
în dreapta este matricea cu liniile ordonate lexi-
cograc
Rezolvarea celei de a doua cerinµe presupune determinarea codului binar al unui caracter pe
baza informaµiilor primite: ultima coloana a matricei permutarilor circulare ordonate lexicograc
³i poziµia liniei pe care se a codul binar al caracterului în cadrul acestei matrice.
Pasul 1: Vom determina prima coloan din matricea obµinut : este evident c prima coloana
este ultima coloan ordonat lexicograc, pentru ordonare determin num rul de elemente 0 de pe
ultima coloan ³i num rul de elemente 1 de pe ultima coloan . Primul 0 de pe prima coloan va
primul 0 de pe ultima coloan , al doilea 0 de pe prima coloan va al doilea 0 de pe ultima coloan ,
³amd, la fel procedam cu elementele 1, astfel putem determina un vector p, cu proprietatea c
pi=poziµia celei de a i-a valori din coloana 1 în ultima coloana
Pasul 2: Pe baza vectorului p, determinat anterior vom determina linia din matricea ordonat
lexicograc al c rui indice l-am primit în ultimul caracter din cript, e acest indice t, parcurgem
ultima coloan în ordinea pt, ppt, pppt, ³amd.
Soluµia 2 - Octavian Dumitra³cu (100 puncte)
Vom determina codic rile pentru cele 96 de caractere (de la 32 la 127) ³i memor m într-un
vector de cuvinte solc hari codicarea caracterului din codul ASCII i ³i în soli memor m un
num r unic conform codic rii, mai exact primele 8 caractere ale codului sunt în ordine ultimii 8
biµi (poziµiile 0, 1, ..., 7) ³i caracterul de pe poziµia 9 este reprezentat în baza 2 ³i ocup poziµiile
8, 9, 10, 11.
La citirea textului necriptat, pentru ecare caracter vom a³a direct criptul acestuia. Pentru
decodicare, vom c uta caracterul având criptul egal cu cel citit.
CAPITOLUL 17. ONI 2015 204
66 {assert(s[i]==’0’|| s[i]==’1’);
67 uc[j]=s[i]; nr0+=(s[i]==’0’);}
68 q=uc;
69 for (j=0; j<nr0; j++)
70 {ord[j]=strchr(q,’0’)-uc; q=ord[j]+1+uc;}
71 q=uc;
72 for (j=nr0; j<8; j++)
73 {ord[j]=strchr(q,’1’)-uc; q=ord[j]+1+uc; }
74 assert(s[i]>=’0’ && s[i]<=’7’);
75 poz=s[i]-’0’;
76 for (j=0; j<8; j++)
77 {poz=ord[poz];
78 cod=(cod<<1)|(uc[poz]-’0’);
79 }
80 fout<<(char)cod;
81 }
82 }
56 strcpy(s[j],aux);
57 ax=ord[i];
58 ord[i]=ord[j];
59 ord[j]=ax;
60 }
61
62 for(i=0; i<=7; i++)
63 cod[i]=s[i][7];
64
65 for(i=0; i<=7; i++)
66 if(ord[i]==0)
67 break;
68
69 cod[8]=’0’+i;
70 cod[9]=’\0’;
71 }
72
73 void decript(char ss[10], char & css)
74 {
75 int p[10],i,k=0,n0=0,n1=0,j=0,t,cod=0,a[10];
76 char ds[10];
77
78 for(i=0; i<=7; i++)
79 if(ss[i]==’0’)
80 n0++;
81 else
82 n1++;
83
84 for(i=0; i<=7; i++)
85 if(ss[i]==’0’)
86 a[k++]=i;
87 else
88 a[n0+j++]=i;
89
90 t=ss[8]-’0’;
91 j=a[t];
92 for(i=0; i<=7; i++)
93 {
94 ds[i]=ss[j];
95 j=a[j];
96 }
97
98 for(i=0; i<=7; i++)
99 cod=cod*2+(ds[i]-’0’);
100
101 css=(char)cod;
102 }
103
104 int main()
105 {
106 fin>>c;
107
108 if(c==1)
109 {
110 fin.get();
111 fin.getline(s,40001);
112 for(i=0; s[i]; i++)
113 {
114 cript(s[i],ss);
115 fout<<ss;
116 }
117 }
118 else
119 {
120 fin>>t;
121 for(i=0; t[i]; i=i+9)
122 {
123 for(j=0;j<=8;j++)
124 ss[j]=t[i+j];
125 ss[9]=’\0’;
126 decript(ss,css);
127 fout<<css;
128 }
129 }
130
131 return 0;
CAPITOLUL 17. ONI 2015 207
132 }
72 else
73 {
74 fin.getline(cript, LGMAX);
75 n = strlen(cript);
76 s = 0;
77 for (i = 0; i < n; i++ )
78 if (i % 9 < 8)
79 s = s * 2 + cript[ i ] - 48;
80 else
81 {
82 z = cript[ i ] - 48;
83 z = (z << 8);
84 s += z;
85 for ( j = 32 ; j <= 127; j++)
86 if (s == sol[ j ] )
87 fout<<(char)j;
88 s = 0;
89 }
90 }
91
92 fout<<’\n’;
93 fout.close();
94 return 0;
95 }
49
50 for(i=0;i<8;i++)
51 nr[i]=i;
52
53 for(i=0;i<7;i++)
54 for(j=i+1; j<=7; j++)
55 if(cmp(a[i], a[j])>0)
56 {
57 for(k=0;k<=7;k++)
58 {
59 aux=a[i][k];
60 a[i][k]=a[j][k];
61 a[j][k]=aux;
62 }
63
64 aux=nr[i];
65 nr[i]=nr[j];
66 nr[j]=aux;
67 }
68
69 for(i=0;i<7;i++)
70 for(j=i+1; j<=7; j++)
71 if(cmp(a[i], a[j])==0 && nr[i]>nr[j])
72 {
73 for(k=0;k<=7;k++)
74 {
75 aux=a[i][k];
76 a[i][k]=a[j][k];
77 a[j][k]=aux;
78 }
79
80 aux=nr[i];
81 nr[i]=nr[j];
82 nr[j]=aux;
83 }
84
85 //g<<’\n’;
86 // for(i=0;i<=7;i++)
87 // {for(j=0;j<8;j++)g<<a[i][j];g<<’\n’;}
88
89 for(j=0;j<=7;j++)
90 cod[j]=a[j][7];
91
92 for(i=0;i<=7;i++)
93 if(nr[i]==0)
94 cod[8]=i;
95 }
96
97 char decodific(int cod[10])
98 {
99 int i;
100
101 for(i=32;i<=127;i++)
102 if(cmp(codif[i], cod)==0 && codif[i][8]==cod[8])
103 return i;
104 return -1; // ... !!!
105 }
106
107 int main()
108 {
109 f>>c;
110 f.get();
111 f.getline(s,9*30001);
112
113 if(c==1)
114 {
115 int i, j, cod[10];
116 char codul[10];
117
118 for(i=32; i<=127; i++)
119 {
120 codific(char(i), cod);
121 for(j=0;j<9;j++)
122 codif[i][j]=cod[j];
123 }
124
CAPITOLUL 17. ONI 2015 210
17.2 scadere
Problema 2 - scadere 100 de puncte
Fie n un num r natural nenul.
S consider m o expresie de forma: x1 x2 x3 ... xn
Se ³tie c sc derea nu este o operaµie asociativ , adic x1 x2 x3 j x1 x2 x3 .
Ca urmare, prin plasarea unor perechi de paranteze în expresie, putem obµine diferite valori.
Pentru problema noastr , vom denumi sc dere o expresie de forma de mai sus în care pot ap rea
³i paranteze rotunde care se închid corect. Valoarea unei sc deri se obµine efectuând operaµiile de
sc dere în ordine de la stânga la dreapta; dac apar paranteze, se efectueaz mai întâi operaµiile
din paranteze.
Cerinµe
Date ind valorile variabilelor x1 , x2 , ..., xn care intervin în sc dere, scrieµi un program care s
rezolve urm toarele dou cerinµe:
1. s se determine valoarea maxim a unei sc deri (obµinut prin inserarea convenabil a unor
paranteze rotunde în expresia x1 x2 x3 ... xn ), precum ³i o sc dere având valoare maxim .
2. s se determine valoarea unei sc deri specicate.
Date de intrare
Fi³ierul de intrare scadere.in conµine pe prima linie un num r natural c indicând cerinµa care
trebuie s e rezolvat (1 sau 2).
Pe a doua linie este scris num rul natural n, care reprezint num rul de variabile care intervin
în sc dere. Variabilele sunt numerotate de la 1
la n în ordinea în care intervin în sc dere. Pe
urm toarele n linii sunt scrise în ordine valorile variabilelor x1 , x2 , ..., xn , câte o valoare pe o linie.
Dac cerinµa este 2, ³ierul mai conµine o linie pe care este scris un ³ir de caractere reprezentând
o sc dere.
Date de ie³ire
CAPITOLUL 17. ONI 2015 211
Fi³ierul de ie³ire scadere.out va conµine pentru c 1 dou linii; pe prima linie va scris un
num r întreg reprezentând valoarea maxim a unei sc deri (obµinut prin inserarea convenabil
a unor paranteze rotunde în expresia x1 x2 x3 ... xn ), iar pe a doua linie o sc dere având
valoare maxim . Dac c 2 ³ierul de ie³ire va conµine o singur linie pe care va scris un num r
întreg reprezentând valoarea sc derii specicate pe ultima linie a ³ierului de intrare.
Restricµii ³i preciz ri
a 3 & n & 5000
a Valorile variabilelor x1 , x2 , ..., xn sunt numere întregi din intervalul 100, 100.
a Sc derea din ³ierul de intrare, respectiv sc derea de valoare maxim a³at în ³ierul de
¬ ¬
ie³ire vor avea maxim 40000 de caractere care pot doar cifre, litera mic x, paranteze rotunde
¬ ¬
³i operatorul (minus).
a Pentru teste valorând 50% din punctaj cerinµa va 1. Pentru a³area corect a valorii
maxime se acord 40% din punctajul pe test. Punctajul integral se acord pentru a³area corect
a valorii maxime ³i a unei sc deri de valoare maxim .
Exemple
scadere.in scadere.out Explicaµii
1 17 Parantezarea care conduce la valoarea maxim este:
4 x1-x2-(x3-x4) x1-x2-(x3-x4)=-7-5-(-10-19)=-12-(-29)=-12+29=17
-7
5
-10
19
2 -3 x1-((x2-x3)-x4)=
4 -7-((5-10)-19)=
-7 -7-(15-19)=-7-(-4)=
5 -7+4=-3
-10
19
x1-((x2-x3)-x4)
Observ m c prin parantezare nu putem schimba semnul termenului x1, iar semnul termenului
x2 va întotdeauna schimbat.
Pentru orice alt termen, plasând o parantez în faµa termenului precedent p str m semnul
acestuia.
x1 x2 x3
x1 x2 x3 x1 x2 x3
Pentru a obµine suma maxim intenµion m s schimb m semnul termenilor negativi ³i s
p str m semnul termenilor pozitivi.
Pentru cerinta 2 trebuie s evalu m o expresie dat . Acest lucru se poate realiza în mai multe
moduri.
O varianta ar de a utiliza o stiv (implementat ca un vector: inserarea se realizeaz la vârful
stivei, adic la sfâr³itul vectorului, iar extragerea se realizeaz de asemenea de la vârful stivei, adic
se elimin ultimul element din vector). în acest vector se vor reµine rezultatele parµiale obµinute
pe parcursul evalu rii expresiei.
Parcurgem ³irul care conµine expresia.
În cazul în care caracterul curent este '(', inser m la sfâr³itul vectorului valoarea INFINIT
pentru a marca faptul c nu am plasat înc pe stiv nicio valoare pe acel nivel.
În cazul în care caracterul curent este ')', vom elimina ultimul element din vector (adic vom
coborî în stiv ), transmiµând pe nivelul precedent valoarea elementului eliminat (aceast valoare
CAPITOLUL 17. ONI 2015 212
va sc zut din nivelul precedent sau copiat pe nivelul precedent, în funcµie de caz - dac pe
nivelul precedent se a o valoare sau nu).
În caz contrar, determin num rul variabilei care urmeaz în ³ir, au valoarea acestei variabile
³i o scad din valoarea aat la vârful stivei (dac exist o astfel de valoare) sau o copiez la vârful
stivei (dac la vârful stivei este plasat valoarea INFINIT).
58
59 int evalexp()
60 {int vf=0, i, nr;
61 st[0]=INF;
62 for (i=0; s[i]; )
63 if (s[i]==’(’)
64 {st[++vf]=INF; i++;}
65 else
66 if (s[i]==’)’)
67 {if (st[vf-1]==INF) st[vf-1]=st[vf];
68 else st[vf-1]-=st[vf];
69 vf--;i++;}
70 else
71 {
72 if (s[i]==’-’)i++;
73 if (s[i]==’x’)
74 {i++;//sar x
75 nr=0;
76 while (s[i]>=’0’&& s[i]<=’9’) {nr=nr*10+s[i]-’0’; i++;}
77 if (st[vf]==INF) st[vf]=x[nr];
78 else st[vf]-=x[nr];
79 }
80 }
81 return st[0];
82 }
48 {
49 if (j == 2)
50 s = s - x[ 2 ],j++ ;
51 else
52 if (j > 2)
53 {
54 s = s - (s1 + 2 * x[ 2 ]);
55 semn [ start ] = 1;
56 semn [ stop - 1 ] = -1;
57 j++;
58 };
59
60 if ( j == 1)
61 s += x[2];
62
63 start = stop = j ;
64 s1 = 0;
65 for (i = j ; i <= n; i++)
66 if (x[ i ] >= 0)
67 {
68 s1 += x[ i ];
69 stop ++;
70 }
71 else
72 {
73 if (stop - start >= 1)
74 {
75 s += s1;
76 semn[ start ] = 1;
77 semn[ stop ] = -1;
78 }
79 else
80 s += s1;
81
82 s1 = -x[ i ];
83 start = stop = i;
84 }
85
86 if (stop - start >= 1)
87 {
88 semn[ start ] = 1;
89 semn[ stop ] = -1;
90 }
91
92 s = s + s1;
93 }
94
95 printf("%d\n", s);
96 if (semn[1] == 1)
97 printf("(");
98 printf("x1-");
99
100 for (i = 2; i < n; i++)
101 {
102 if (semn[ i ] == 1 )
103 printf("(");
104 printf("x%d",i);
105 if (semn [ i ] !=- 1)
106 printf("-");
107 if (semn[ i ] == -1)
108 printf(")-");
109 }
110
111 printf("x%d",n);
112 if (semn[ n ] == -1 || semn[ n + 1 ] == -1)
113 printf(")");
114 }
115 else
116 {
117 gets ( sir );
118 m = strlen(sir);
119 y[ 1 ] = 1;
120 t = 1;
121 paranteze = 0;
122 q = 0;
123 nr_minus = 0;
CAPITOLUL 17. ONI 2015 215
124
125 for ( i = 0; i < m; i++)
126 if (sir[ i ] == ’(’ )
127 q++,st[q]=nr_minus;
128 else
129 if (sir[ i ] == ’)’)
130 q--,nr_minus = st[q];
131 else
132 if (sir[ i ] ==’-’ )
133 nr_minus =st[q], nr_minus++;
134 else
135 if (sir[ i ] == ’x’)
136 if (nr_minus % 2 == 0)
137 y[ t++ ] = 1;
138 else
139 y[ t++ ] = -1;
140 else
141 while(i+1<m && sir[i+1]>=’0’ && sir[i+1]<=’9’)
142 i++;
143 s = 0;
144 for (i = 1;i <= n; i++)
145 s = s + y[ i ] * x[ i ];
146
147 printf("%d\n",s);
148 }
149
150 return 0;
151 }
17.3 tv
Problema 3 - tv 100 de puncte
Comisia Naµional a Audiovizualului (CNA) este autoritatea care coordoneaz activitatea
posturilor media din România. ³eful CNA-ului dore³te o statistic referitoare la publicitatea
transmis de posturile de televiziune. în acest scop, el prime³te pentru ecare zi informaµii în
urm torul format:
d hh mm ss
unde d este durata exprimat în secunde a publicit µii, iar hh mm ss este momentul de start
al publicit µii (hh este ora, mm este minutul, iar ss este secunda). Observaµi c d este separat de
hh printr-un singur spaµiu, iar urm toarele valori sunt separate prin caracterul ':'.
De exemplu o linie de forma:
150 05 02 45
se interpreteaz astfel: exist un post TV care a transmis publicitate cu durata de 150 secunde,
ora de început ind 5, 2 minute ³i 45 de secunde.
Secunda de aur este o secund în care se difuzeaz cât mai mult publicitate, adic pe un
num r maxim de posturi în acea secund se transmite publicitate. Dac sunt mai multe astfel
de secunde, "secunda de aur" este considerat prima secund cu aceast proprietate în derularea
zilei.
eful CNA prime³te în ecare dimineaµ lista cu activitatea din ziua anterioar ca o succesiune
de linii, ecare linie având forma descris mai sus.
Cerinµe
Scrieµi un program care, cunoscând lista din ziua anterioar , s rezolve urm toarele cerinµe:
1. s determine durata total în care niciun post de televiziune nu a difuzat publicitate;
2. s determine care este "secunda de aur".
Date de intrare
Fi³ierul de intrare tv.in conµine pe prima linie num rul natural c, care poate 1 sau 2,
reprezentând cerinµa care urmeaz s e rezolvat . Pe a doua linie se a num rul natural N,
reprezentând num rul de linii din lista cu informaµii primit de ³ef. Pe urm toarele N linii sunt
descrise informaµiile, în formatul specicat în enunµ.
Date de ie³ire
CAPITOLUL 17. ONI 2015 216
Fi³ierul de ie³ire tv.out va conµine o singur linie pe care vor scrise 3 numere naturale
separate prin caracterul ':' în formatul urm tor:
hh mm ss
semnicând durata total exprimat în ore (hh), minute (mm) ³i secunde (ss) pe parcursul
c reia niciun post de televiziune nu a difuzat publicitate în ziua respectiv (dac c 1), respectiv
"secunda de aur" (dac c 2).
Restricµii ³i preciz ri
a 1 & N & 100000
a hh va un num r de exact dou cifre, cuprins între 00 ³i 23
a mm, respectiv ss vor numere de exact dou cifre, cuprinse între 00 ³i 59
a Durata d este nenul ³i sfâr³itul transmisiei publicit µii se a în cadrul zilei curente.
a Pentru teste valorând 60% din punctaj cerinµa este 1.
Exemple
tv.in tv.out Explicaµii
1 23:18:40 Pentru exemplul 1, cerinµa este 1.
6 Pe parcursul zilei, timp de 23 de ore, 18 minute ³i 40 de secunde
120 12:00:00 nu s-a difuzat publicitate.
200 12:01:50
1000
13:00:00
2000
13:01:00
100 14:05:05
10 23:59:49
2 12:01:50 Pentru exemplul 2, cerinµa este 2.
6 Secunda de aur este 12:01:50 pentru c exist un num r maxim
1200 posturi care difuzeaz publicitate (3 posturi).
12:00:00
2000
12:01:50
1000
12:00:00
2000
13:01:00
100 14:05:05
10 23:59:49
ONI 2014
18.1 codat
Problema 1 - codat 100 de puncte
Se consider un ³ir de N numere naturale, notate x1 , x2 , x3 , ..., xN . Denim pentru orice
pereche de indici i, j , 1 & i & j & N , distanµa între elementele xi ³i xj ca ind egal cu j i.
Acest ³ir va codicat dup urm toarele reguli:
a ecare element din ³ir este înlocuit cu indicele celui mai apropiat element din ³ir (cel faµ de
care distanµa este minim ) strict mai mare decât el;
a dac pentru un element din ³ir exist dou elemente care respect regula de mai sus, atunci
el va înlocuit cu indicele mai mare, adic al elementului strict mai mare decât el, aat în dreapta
lui;
a elementele de valoare maxim din ³ir vor înlocuite cu -1.
Cerinµe
Scrieµi un program care codic un ³ir de N valori, dup regulile descrise.
Date de intrare
Fi³ierul codat.in conµine:
- pe prima linie num rul natural N
- pe urm toarea linie N numere naturale nenule, separate prin câte un spaµiu, reprezentând
³irul x1 , x2 , x3 , ..., xN
Date de ie³ire
Fi³ierul codat.out va conµine pe prima linie N numere întregi nenule, separate prin câte un
spaµiu, reprezentând ³irul codicat.
Restricµii ³i preciz ri
a 1&N & 1000000
a 1 & xi & 2000000000, 1 & i & N
Exemple
codat.in codat.out Explicaµii
7 2 -1 4 2 4 7 4 x1 2: cel mai apropiat element strict mai mare decât el este x2
2 9 3 5 1 1 4 x2 9: nu are nici un element mai mare decât el
x3 3: elementele mai mari strict decât el, sunt aate la distanµ
egal , deci va înlocuit cu indicele mai mare adic 4
x4 5: cel mai apropiat element strict mai mare decât el este x2
x5 1: cel mai apropiat element strict mai mare decât el este x4
x6 1: cel mai apropiat element strict mai mare decât el este x7
x7 4: cel mai apropiat element strict mai mare decât el este x4
???-???
Pentru ecare element Ai soluµia o reprezint cel cel mai apropiat dintre indicii elementului
maxim aat în stânga, salvat în Sti, ³i cel mai mare element aat în dreapta lui, salvat în Dr i.
Pentru construcµia vectorului St elementele lui A sunt parcurse de la stânga la dreapta. Vom
folosi un vector suplimentar Cnd pentru pastrarea doar a elementelor ce candideaz la a maxime
pentru unul dintre elementele urm toare. În fapt în vectorul Cnd vom plasa indicii acestora.
A2 7 Elementul ACndnr ind mai mic decât A2, este scos din ³irul canditaµilor ³i
înlocuit cu indicele acestuia (Cndnr 2), nr 1.
Deasemenea, St2 1 deoarece nu are element mai mare situat în stanga lui A3 4.
Acesta poate reprezenta maximul unui element aat în vectroul A dup el, deci este salvat în
vectorul Cnd pe poziµia a doua.
1 #include <fstream>
2
3 #define DIM 1000002
4
5 using namespace std;
6
7 ifstream fin("codat.in");
8 ofstream fout("codat.out");
9
10 int v[DIM], s[DIM], L[DIM], R[DIM], minim, k, n, i, maxim, pminim;
11
12 int main()
13 {
CAPITOLUL 18. ONI 2014 220
14 fin>>n;
15 for (i=1;i<=n;i++)
16 {
17 fin>>v[i];
18 if (v[i] > maxim)
19 maxim = v[i];
20 while (k!=0 && v[i] >= v[s[k]])
21 {
22 k--;
23 }
24 L[i] = s[k];
25 s[++k] = i;
26 }
27
28 k = 0;
29 s[k] = n+1;
30 for (i=n;i>=1;i--)
31 {
32 while (k!=0 && v[i] >= v[s[k]])
33 {
34 k--;
35 }
36 R[i] = s[k];
37 s[++k] = i;
38
39 }
40
41 for (i=1;i<=n;i++)
42 {
43 if (v[i] == maxim)
44 {
45 v[i] = -1;
46 continue;
47 }
48
49 minim = n+2;
50 if (L[i] != 0 && i-L[i]<minim)
51 {
52 minim = i-L[i];
53 pminim = L[i];
54 }
55 if (R[i]!=n+1 && R[i]-i <= minim)
56 {
57 minim = R[i]-i;
58 pminim = R[i];
59 }
60 v[i] = pminim;
61 }
62
63 for(i=1;i<=n;i++)
64 fout<<v[i]<<" ";
65
66 return 0;
67 }
1 #include <fstream>
2
3 #define MAXN 100002
4
5 using namespace std;
6
7 ifstream in("codat.in");
8 ofstream out("codat.out");
9
10 int v[MAXN];
11 int idx[MAXN];
12
13 int abs(int x)
14 {
15 if(x<0) x*=-1;
16 return x;
17 }
18
CAPITOLUL 18. ONI 2014 221
19 int main()
20 {
21 int N;
22 in>>N;
23
24 for(int i=1;i<=N;++i)
25 in>>v[i];
26
27 for(int i=1;i<=N;++i)
28 {
29 idx[i]=-1;
30 for(int j=i-1;j>=1;--j)
31 if(v[j]>v[i])
32 {
33 idx[i]=j;
34 break;
35 }
36
37 for(int j=i+1;j<=N;++j)
38 if(v[j]>v[i])
39 {
40 if(idx[i]==-1||abs(idx[i]-i)>=abs(j-i))
41 idx[i]=j;
42 break;
43 }
44 }
45
46 for(int i=1;i<=N;++i)
47 out<<idx[i]<<’ ’;
48
49 out<<’\n’;
50
51 in.close();
52 out.close();
53
54 return 0;
55 }
1 #include <fstream>
2 #include <stack>
3
4 #define MAXN 100001
5
6 using namespace std;
7
8 ifstream in("codat.in");
9 ofstream out("codat.out");
10
11 int abs(int x)
12 {
13 if(x<0) x*=-1;
14 return x;
15 }
16
17 stack <int> st;
18
19 int v[MAXN];
20 int idx[MAXN];
21
22 int main()
23 {
24 int N;
25 in>>N;
26
27 for(int i=1;i<=N;++i) in>>v[i];
28
29 for(int i=1;i<=N;++i)
30 {
31 while(!st.empty()&&v[st.top()]<=v[i])
32 st.pop();
33
34 if(st.empty())
35 idx[i]=-1;
CAPITOLUL 18. ONI 2014 222
36 else
37 idx[i]=st.top();
38
39 st.push(i);
40 }
41
42 while(!st.empty())
43 st.pop();
44
45 for(int i=N;i>=1;--i)
46 {
47 while(!st.empty()&&v[st.top()]<=v[i])
48 st.pop();
49
50 if(!st.empty())
51 if(idx[i]==-1||abs(idx[i]-i)>=abs(st.top()-i))
52 idx[i]=st.top();
53
54 st.push(i);
55 }
56
57 for(int i=1;i<=N;++i)
58 out<<idx[i]<<’ ’;
59 out<<’\n’;
60
61 in.close();
62 out.close();
63
64 return 0;
65 }
18.2 nod
Problema 2 - nod 100 de puncte
Pe vremea maurilor, transmiterea unor mesaje codicate între dou persoane se f cea folosind
un cifru numit nod.
Cele dou persoane alegeau în secret o poveste. Aceasta era scris într-o carte folosind litere
mici ³i mari ale alfabetului englez, pe P pagini, numerotate de la 1 la P, ecare conµinând exact
R rânduri, numerotate în cadrul ec rei pagini de la 1 la R, iar ecare rând ind format din exact
C cuvinte, numerotate în cadrul ec rui rând de la 1 la C .
Un cuvânt al mesajului de transmis era codicat prin poziµia sa în povestea aleas de cei
doi, folosind trei numere scrise cu cifre romane, ce indicau în ordine: num rul paginii, num rul
rândului în cadrul paginii, respectiv al cuvântului în cadrul rândului.
Mesajul astfel codicat era scris pe trei linii. Pe prima linie erau scrise numerele paginilor, pe
a doua linie numerele rândurilor, iar pe a treia linie erau scrise numerele de ordine ale cuvintelor.
Presupunem c mesajul este format din primul cuvânt de pe al cincilea rând al celei de a doua
pagini ³i din al patrulea cuvânt de pe rândul al doilea al primei pagini. Mesajul putea transmis
pe trei linii în modul urm tor:
II I (numerele paginilor)
V II (numerele rândurilor)
I IV (numerele cuvintelor)
De exemplu pentru num rul MCDXLVI scris cu cifre romane, se obµine valoarea 1446 în sistem
zecimal, astfel: 1000-100+500-10+50+5+1, iar pentru num rul XXI scris cu cifre romane se obµine
valoarea 21 în sistemul zecimal astfel: 10+10+1.
CAPITOLUL 18. ONI 2014 223
Cerinµe
Cunoscându-se textul pove³tii ales de cei doi ³i mesajul codicat de ei scrieµi un program care
rezolv urm toarele dou cerinµe:
a) Rescrie mesajul codicat folosind scrierea cu cifre din sistemul zecimal.
b) A³eaz toate cuvintele mesajului decodicat în ordinea în care acestea apar în poveste.
Date de intrare
Fi³ierul nod.in conµine:
a pe prima linie num rul 1, dac se cere rezolvarea doar a cerinµei a) sau num rul 2, dac se
cere rezolvarea cerinµei b);
a pe urm toarele trei linii mesajul codicat dup regulile descrise în enunµ;
a dac primul num r din ³ier este 2 atunci a cincea linie conµine trei numere naturale P, R
³i C, separate între ele prin câte un spaµiu, cu semnicaµia din enunµ;
a pe urm toarele P R linii este scris textul pove³tii, ecare linie conµinând C cuvinte, separate
prin câte un spaµiu.
Date de ie³ire
Dac primul num r din ³ierul de intrare este 1 atunci ³ierul nod.out va conµine, în aceea³i
ordine, pe trei linii, numerele din mesajul codicat scrise în sistem zecimal. Numerele vor
desp rµite în cadrul liniilor prin câte un spaµiu.
Dac primul num r din ³ierul de intrare este 2 atunci ³ierul nod.out va conµine pe o singur
linie cuvintele mesajului decodicat, în ordinea din poveste. Cuvintele vor separate prin câte
un spaµiu.
Restricµii ³i preciz ri
a 1 & P & 2000; 1 & R & 25; 1 & C & 15
a 1 & lungimea unui cuvânt din poveste & 12
Exemplul 1:
nod.in nod.out Explicaµii
1 3 2 1 Testul de intrare indic rezolvarea primei cerinµe, adic cerinµa a).
III II I 2 5 2 Numerele de pe ecare linie sunt scrise în aceea³i ordine, în sistemul
II V II 6 1 4 zecimal.
VI I IV
Exemplul 2:
nod.in nod.out
2 La Olimpiada comisia decide prima
I III II I II
I I II I II
I II II II IV
3 2 4
La Olimpiada problemele pot
avea una sau mai
multe cerinte Pentru unele
probleme comisia poate decide
ca prima cerinta sa
e evaluata si separat
Explicaµii:
Testul de intrare indic rezolvarea celei de a doua cerinµe, adic cerinµa b).
Cuvintele identicate în poveste sunt:
La - prin (I,I,I)
prima - prin (III,I,II)
comisia - prin (II,II,II)
Olimpiada - prin (I,I,II)
decide - prin (II,II,IV)
??? - ???
Pentru cerinµa 1
De pe ecare linie separ m câte un cuvânt, care reprezint un num r scris cu cifre romane ³i
transform m num rul scris cu cifre romane în num r întreg scris în sistem zecimal:
Parcurgem cifrele num rului de la stânga la dreapta câte una, o transform m în sistem zecimal
³i
daca(cif[i]<cif[i+1])
nr=nr-cif[i];
else
nr=nr+cif[i+1];
Scriem tripletele pagin , rând, num r caracter pe câte un rând în ³ierul de ie³ire.
Pentru cerinµa 2
Dup parcurgerea etapelor de la cerinµa 1.
Ordon m tabloul obµinut, cresc tor, dup trei criterii: pagin , rând ³i num rul cuvântului.
Citim din ³ier cele trei valori P, R, C, respectiv num rul paginilor c rµii, num rul de rânduri
de pe o pagin ³i num rul de cuvinte de pe un rând.
Citim textul linie cu linie, separ m cuvintele ³i le num r m. Calcul m pentru ecare cod
transmis poziµia pe care o ocup cuvântul în text, respectiv: (pagina-1)*R+(rând-1)*C+cuvânt.
În momentul în care ajungem la cuvântul din text, cu num rul de ordine egal cu num rul
calculat pentru codul transmis, scriem cuvântul în ³ierul de ie³ire.
1 #include <iostream>
2 #include <fstream>
3 #include <string.h>
4
5 using namespace std;
6
7 ifstream f("nod.in");
8 ofstream g("nod.out");
9
10 struct cuvinte
11 {
12 int pag, rand, cuv;
CAPITOLUL 18. ONI 2014 225
13 };
14
15 char sir[600]="", numar[11]="",*p, sep[]=" ";
16 int n,k,P,R,C;
17 cuvinte t[26];
18
19 void extrage_nr();
20 int calculeaza(int x);
21 void transforma(char numar[11],int k);
22 void ordonare();
23 void cauta_cuvinte();
24 void afisare();
25
26 int main()
27 {
28 f>>k; f.get();
29 extrage_nr();
30 if(k==1)
31 {
32 for(int d=1;d<=3;d++)
33 for(int i=1; i<=n;i++)
34 {
35 switch (d)
36 {
37 case 1:g<<t[i].pag; break;
38 case 2:g<<t[i].rand; break;
39 case 3:g<<t[i].cuv; break;
40 }
41
42 if(i<n)
43 g<<" ";
44 else
45 g<<’\n’;
46 }
47 }
48 else
49 {
50 ordonare();
51 cauta_cuvinte();
52 }
53
54 f.close();
55 g.close();
56 return 0;
57 }
58
59 void extrage_nr()
60 {
61 int i;
62 for(i=1;i<=3;i++)
63 {
64 n=0;
65 f.getline(sir,600);//cout<<sir<<endl;
66 p=strtok(sir,sep);
67 while (p)
68 {
69 n++;
70 strcpy(numar, p);
71 transforma(numar,i);
72 p=strtok(NULL,sep);
73 }
74 }
75 }
76
77 void transforma(char numar[11],int d)
78 {
79 int i,l,cif1,cif2,nr=0;
80 l=strlen(numar);
81 for(i=0;i<l-1;i++)
82 {
83 cif1=calculeaza(numar[i]);
84 cif2=calculeaza(numar[i+1]);
85 if(cif1<cif2)
86 nr=nr-cif1;
87 else
88 nr=nr+cif1;
CAPITOLUL 18. ONI 2014 226
89 }
90
91 if(l==1)
92 nr=calculeaza(numar[i]);
93 else
94 nr=nr+cif2;
95
96 switch (d)
97 {
98 case 1:t[n].pag=nr;break;
99 case 2:t[n].rand=nr;break;
100 case 3:t[n].cuv=nr;break;
101 }
102 }
103
104 int calculeaza(int x)
105 {
106 int cif;
107 switch (x)
108 {
109 case ’M’:cif=1000;break;
110 case ’D’:cif=500;break;
111 case ’C’:cif=100;break;
112 case ’L’:cif=50;break;
113 case ’X’:cif=10;break;
114 case ’V’:cif=5; break;
115 case ’I’:cif=1;break;
116 }
117
118 return cif;
119 }
120
121 void ordonare()
122 {
123 int i,sw; cuvinte aux;
124 do
125 {
126 sw=1;
127 for(i=1;i<n;i++)
128 if(t[i].pag>t[i+1].pag ||
129 (t[i].pag==t[i+1].pag && t[i].rand>t[i+1].rand) ||
130 (t[i].pag==t[i+1].pag &&
131 t[i].rand==t[i+1].rand &&
132 t[i].cuv>t[i+1].cuv))
133 {
134 aux=t[i];
135 t[i]=t[i+1];
136 t[i+1]=aux;
137 sw=0;
138 }
139 } while (sw==0);
140 }
141
142 void cauta_cuvinte()
143 {
144 int i=1,nrct=0, nrc=0;
145 char *p;
146
147 f>>P>>R>>C;
148 f.get();
149
150 nrct=(t[1].pag-1)*R*C + (t[1].rand-1)*C + t[1].cuv;
151
152 while(f.getline(sir,600) && i<=n)
153 {
154 p=strtok(sir,sep);
155 while (p)
156 {
157 nrc++;
158
159 if(nrc==nrct)
160 {
161 if (i<n)
162 g<<p<<" ";
163 else
164 g<<p;
CAPITOLUL 18. ONI 2014 227
165
166 i++;
167 nrct=(t[i].pag-1)*R*C+(t[i].rand-1)*C + t[i].cuv;
168 }
169
170 p=strtok(NULL,sep);
171 }
172 }
173 }
174
175 void afisare()
176 {
177 int i;
178 for(i=1;i<=n;i++)
179 {
180 g<<t[i].pag<<" "<<t[i].rand<<" "<<t[i].cuv<<’\n’;
181 }
182 }
1 #include <iostream>
2 #include <cstdio>
3 #include <algorithm>
4 #include <cstring>
5 #include <cctype>
6 #include <cassert>
7
8 #define Pmax 2010
9 #define Rmax 300
10 #define Cuvmes 30
11
12 using namespace std;
13
14 struct tag
15 {
16 short int pg,rd,cv;
17 };
18
19 char s[Rmax],Pag[Rmax], Rand[Rmax], Cuv[Rmax],romane[10]="MDCLXVI ";
20
21 tag L[Cuvmes];
22
23 int p, r, c, P[Cuvmes], C[Cuvmes], R[Cuvmes], np, nc, nr;
24 int i, j, k, test, ii=1;
25
26 int cif(char x)
27 {
28 if(x==’M’) return 1000;
29 if(x==’D’) return 500;
30 if(x==’C’) return 100;
31 if(x==’L’) return 50;
32 if(x==’X’) return 10;
33 if(x==’V’) return 5;
34 if(x==’I’) return 1;
35
36 return -1; // ... !!!
37 }
38
39 int NrRo(char s[])
40 {
41 int n=strlen(s);
42 int Nr=cif(s[n-1]);
43
44 for(int i=0; i<n-1; i++)
45 if (cif(s[i])>=cif(s[i+1]))
46 Nr+=cif(s[i]);
47 else
48 Nr-=cif(s[i]);
49
50 return Nr;
51 }
52
53 void PuneNr(int V[], int &n, char s[1000])
54 {
CAPITOLUL 18. ONI 2014 228
131 }
132
133 for(i=1; i<=np;i++)
134 {
135 printf("%d", L[i].cv);
136 if(i<np)
137 printf(" ");
138 else
139 printf("\n");
140 }
141 }
142 else
143 {
144 scanf("%d %d %d\n", &p, &r, &c);
145 assert(p>=1&&p<=2000&&r>=1&&r<=25&&c>=1&&c<=15);
146
147 for(i=1; i<=np; i++)
148 {
149 assert(L[i].pg<=p && L[i].pg>=1);
150 assert(test==1 || L[i].rd<=r && L[i].rd>=1);
151 assert(test==1 || L[i].cv<=c && L[i].cv>=1);
152 }
153
154 sort(L + 1, L + np + 1, cmp);
155
156 for(i=1; i<=p; i++)
157 for(j=1; j<=r; j ++)
158 {
159 for(k=1; k<=c; k++)
160 {
161 scanf("%s", &s);
162 x=strlen(s);
163 assert(x<=12);
164
165 for(int t=0; t<x; t++)
166 assert(isalpha(s[t])||s[t]==’ ’);
167
168 if(L[ii].pg==i && L[ii].rd==j && L[ii].cv==k)
169 {
170 if(ii<np)
171 printf("%s ", s);
172 else
173 printf("%s\n", s);
174 ii++;
175 }
176 }
177
178 scanf("\n");
179 }
180 }
181
182 return 0;
183 }
1 #include <fstream>
2 #include<string.h>
3
4 using namespace std;
5
6 ifstream f("nod.in");
7 ofstream g("nod.out");
8
9 int p[256],r[30],c[25],poz[100103];
10 char *q1,*q2,*q, sir[]="MDCLXVI",b[256],w[256],s[256],x[2];
11 int nr_pag=1,nr_r=1,nr_c=1,v[8]={1000, 500, 100, 50, 10, 5,1};
12
13 void citire_pagini()
14 {
15 int i,j,k;
16
17 f.getline(b,255);
18 q=strtok(b," ");
19
CAPITOLUL 18. ONI 2014 230
20 while(q)
21 {
22 strcpy(w,q);
23 q1=strchr(sir,w[0]);
24 i=q1-sir;
25 if(strlen(w)==1)
26 p[nr_pag]=v[i];
27 else
28 {
29 for(k=1;k<strlen(w);k++)
30 {
31 q2=strchr(sir,w[k]);
32 j=q2-sir;
33
34 if(j>=i)
35 p[nr_pag]=p[nr_pag]+v[i];
36 else
37 p[nr_pag]=p[nr_pag]-v[i];
38
39 q1=q2;i=j;
40 }
41
42 q1=strchr(sir,w[strlen(w)-1]);
43 i=q1-sir;
44 p[nr_pag]=p[nr_pag]+v[i];
45 }
46
47 nr_pag++;
48 q=strtok(NULL," ");
49 }
50
51 nr_pag--;
52 if(x[0]==’1’)
53 {
54 for(i=1;i<=nr_pag;i++)
55 g<<p[i]<<’ ’;
56 g<<’\n’;
57 }
58 }
59
60 void citire_randuri()
61 {
62 int i,j,k;
63
64 f.getline(b,255);
65 q=strtok(b," ");
66
67 while(q)
68 {
69 strcpy(w,q);
70 q1=strchr(sir,w[0]);
71 i=q1-sir;
72
73 if(strlen(w)==1)
74 r[nr_r]=v[i];
75 else
76 {
77 for(k=1;k<strlen(w);k++)
78 {
79 q2=strchr(sir,w[k]);
80 j=q2-sir;
81
82 if(j>=i)
83 r[nr_r]=r[nr_r]+v[i];
84 else
85 r[nr_r]=r[nr_r]-v[i];
86
87 q1=q2;i=j;
88 }
89
90 q1=strchr(sir,w[strlen(w)-1]);
91 i=q1-sir;
92 r[nr_r]=r[nr_r]+v[i];
93 }
94
95 nr_r++;
CAPITOLUL 18. ONI 2014 231
96 q=strtok(NULL," ");
97 }
98
99 nr_r--;
100 if(x[0]==’1’)
101 {
102 for(i=1;i<=nr_r;i++)
103 g<<r[i]<<’ ’;
104 g<<’\n’;
105 }
106 }
107
108 void citire_cuv()
109 {
110 int i,j,k;
111 f.getline(b,255);
112 q=strtok(b," ");
113
114 while(q)
115 {
116 strcpy(w,q);
117 q1=strchr(sir,w[0]);
118 i=q1-sir;
119
120 if(strlen(w)==1)
121 c[nr_c]=v[i];
122 else
123 {
124 for(k=1;k<strlen(w);k++)
125 {
126 q2=strchr(sir,w[k]);
127 j=q2-sir;
128
129 if(j>=i)
130 c[nr_c]=c[nr_c]+v[i];
131 else
132 c[nr_c]=c[nr_c]-v[i];
133
134 q1=q2;i=j;
135 }
136
137 q1=strchr(sir,w[strlen(w)-1]);
138 i=q1-sir;
139 c[nr_c] =c[nr_c]+v[i];
140 }
141
142 nr_c++;
143 q=strtok(NULL," ");
144 }
145
146 nr_c--;
147 if(x[0]==’1’)
148 {
149 for(i=1;i<=nr_c;i++)
150 g<<c[i]<<’ ’;
151 g<<’\n’;
152 }
153 }
154
155 int main()
156 {
157 int i,P,R,C,nr=0,j,aux;
158
159 f.getline(x,2);
160 citire_pagini();
161 citire_randuri();
162 citire_cuv();
163
164 if(x[0]==’2’)
165 {
166 f>>P>>R>>C;
167
168 for(i=1;i<=nr_pag;i++)
169 poz[i]=(p[i]-1)*R*C+(r[i]-1)*C+c[i];
170
171 for(i=1;i<=nr_pag-1;i++)
CAPITOLUL 18. ONI 2014 232
172 for(j=i+1;j<=nr_pag;j++)
173 if(poz[i]>poz[j])
174 {
175 aux=poz[i];
176 poz[i]=poz[j];
177 poz[j]=aux;
178 }
179
180 j=1;
181 nr=1;
182 for(i=1;i<=R*P;i++)
183 {
184 f.getline(b,255);
185 q=strtok(b," ");
186 while(q)
187 {
188 strcpy(w,q);
189 if(nr==poz[j])
190 {
191 g<<w<<’ ’;j++;
192 }
193 nr++;
194 q=strtok(NULL," ");
195 }
196 }
197 }
198
199 f.close();
200 g.close();
201 return 0;
202 }
18.3 placa
Problema 3 - placa 100 de puncte
Un gard este format din mai multe pl ci dreptunghiulare. Fiecare plac este, la rândul ei,
construit din N M c r mizi. Una dintre pl ci ridic o problem , deoarece este deteriorat .
Placa este reprezentat pe hârtie cu ajutorul unei matrice cu N linii ³i M coloane, numerotate
de la 1 la N, respectiv de la 1 la M. Matricea conµine doar valori 0 ³i 1, ³i respect urm toarele
reguli:
- un element egal cu 1 indic prezenµa în aceea poziµie a unei c r mizi, iar un element egal cu
0 indic absenµa ei;
- linia 1 ³i linia N conµin numai valori egale cu 1, pentru c marginea de sus ³i cea de jos a
pl cii este intact ;
- din orice element egal cu 1, situat în interiorul matricei, se poate ajunge pe linia 1 sau pe
linia N sau pe amândou , mergând doar în sus sau doar în jos, parcurgând numai valorile egale
cu 1;
- exist cel puµin o coloan stabil (format numai din elemente egale cu 1).
Se dore³te modicarea pl cii ³i pentru aceasta se pot ³terge din matrice maximum K coloane
al turate. Dup ³tergere se alipesc coloanele r mase ³i se deplaseaz pe vertical partea de sus a
pl cii spre cea de jos, pân când se va forma o coloan stabil .
Cerinµe
S se determine în lµimea minim Hmin pe care o poate avea placa ³tergând cel mult K
coloane al turate. Identicaµi num rul minim de coloane al turate care trebuie ³terse pentru a
obµine în lµimea Hmin.
Date de intrare
Din ³ierul placa.in se citesc de pe prima linie 3 numere naturale N , M , K separate prin câte
un spaµiu, având semnicaµia din enunµ.
Pe ecare dintre urm toarele M linii ale ³ierului se g sesc perechi de numere naturale N 1,
N 2, separate printr-un spaµiu. Astfel pe linia i1 a ³ierului de intrare num rul N1 reprezint
num rul de elemente de 1 situate pe coloana i, începând cu linia 1, deplasându-ne în jos pân la
CAPITOLUL 18. ONI 2014 233
întâlnirea unei valori egale cu 0, sau pân se ajunge pe linia N ; num rul N 2 reprezint num rul de
elemente de 1 situate pe coloana i, începând cu linia N, deplasândune în sus pân la întâlnirea
unei valori egale cu 0, sau pân se ajunge pe linia 1.
Date de ie³ire
În ³ierul placa.out se va scrie pe prima linie în lµimea minim cerut Hmin, iar pe a doua
linie num rul minim de coloane ce trebuie eliminate pentru a obµine în lµimea Hmin.
Restricµii ³i preciz ri
a 1&N & 100000; 1 & M & 100000; 1 & K $ M ;
a se garanteaz c pe liniile ce conµin informaµii referitoare la cele M coloane ale matricei
exist cel puµin o linie pe care se a valoarea N de 2 ori, în rest suma celor dou valori este strict
mai mic decât N;
a toate valorile din ³ier sunt strict pozitive;
a se acord 30% din punctajul pe test dac doar prima valoare e corect ³i 70% din punctajul
pe test dac doar a doua valoare e corect .
Exemple
placa.in placa.out Explicaµii
5 6 3 3 Matricea iniµial :
1 1 2 1 1 1 1 1 1
2 1 0 1 0 1 0 0
1 2 0 0 0 1 1 0
5 5 0 0 1 1 1 0
1 3 1 1 1 1 1 1
1 1 în lµimea minim este 3 ³i se poate obµine eliminând, de exemplu,
coloanele 3, 4, 5 rezultând matricea:
1 1 1
0 1 0
1 1 1
O alt modalitate de a obµine aceea³i în lµime dar prin ³tergerea
unui num r minim de coloane (4 ³i 5) conduce la:
1 1 1 1
0 1 1 0
1 1 1 1
Pentru a calcula num rul minim de coloane pentru care obµinem aceast valoare în timp liniar
putem proceda astfel: determin m cea mai din dreapta poziµie pentru care maxS i <= Hmin ³i
cea mai din stânga poziµie pentru care maxDi <= Hmin; acestea sunt prima ³i ultima coloan
a zonei care poate eliminat pentru a obµine o soluµie optim pentru a doua cerinµ .
Alt posibilitate pentru a rezolva a doua cerinµ este s c ut m binar valoarea cerut iar în
timpul veric rii se procedeaz ca la determinarea primei cerinµe.
CAPITOLUL 18. ONI 2014 234
1 #include <fstream>
2 #define DIM 1000002
3
4 using namespace std;
5
6 int v[DIM], a[DIM], b[DIM], c[DIM], d[DIM];
7 int n, m, k, x, y, i, j, sol, solc, p, u, mid;
8
9 int main()
10 {
11 ifstream fin("placa.in");
12 ofstream fout("placa.out");
13
14 fin>>n>>m>>k;
15 for (i=1;i<=m;i++)
16 {
17 fin>>x>>y;
18 if (x!=n)
19 v[i] = x+y;
20 else
21 v[i] = n;
22 }
23
24 a[1] = v[1];
25 for (i=2;i<=m;i++)
26 if (a[i-1] > v[i])
27 a[i] = a[i-1];
28 else
29 a[i] = v[i];
30
31 b[m] = v[m];
32 for (i=m-1;i>=1;i--)
33 if (v[i] > b[i+1])
34 b[i] = v[i];
35 else
36 b[i] = b[i+1];
37
38 sol = m+2;
39 for (i=1,j=k;j<=m;i++,j++)
40 {
41 if (a[i-1] > b[j+1])
42 x = a[i-1];
43 else
44 x = b[j+1];
45
46 if (x < sol)
47 sol = x;
48 }
49
50 fout<<sol<<"\n";
51
52 for (i=1;i<=m;i++)
53 {
54 if (a[i] > sol)
55 c[i] = 1;
56 else
57 c[i] = c[i-1];
58 }
59
60 for (i=m;i>=1;i--)
61 {
62 if (b[i] > sol)
63 d[i] = 1;
64 else
65 d[i] = d[i+1];
CAPITOLUL 18. ONI 2014 235
66
67 c[i] = c[i] && d[i];
68 if (c[i] == 1)
69 p++;
70 }
71
72 fout<<p<<"\n";
73
74 return 0;
75 }
1 #include <fstream>
2 #define DIM 1000002
3
4 using namespace std;
5
6 int v[DIM], a[DIM], b[DIM];
7 int n, m, k, x, y, i, j, sol, solc, p, u, mid;
8
9 int main()
10 {
11 ifstream fin("placa.in");
12 ofstream fout("placa.out");
13
14 fin>>n>>m>>k;
15 for (i=1;i<=m;i++)
16 {
17 fin>>x>>y;
18 if (x!=n)
19 v[i] = x+y;
20 else
21 v[i] = n;
22 }
23
24 a[1] = v[1];
25 for (i=2;i<=m;i++)
26 if (a[i-1] > v[i])
27 a[i] = a[i-1];
28 else
29 a[i] = v[i];
30
31 b[m] = v[m];
32 for (i=m-1;i>=1;i--)
33 if (v[i] > b[i+1])
34 b[i] = v[i];
35 else
36 b[i] = b[i+1];
37
38 sol = m+2;
39 for (i=1,j=k;j<=m;i++,j++)
40 {
41 if (a[i-1] > b[j+1])
42 x = a[i-1];
43 else
44 x = b[j+1];
45
46 if (x < sol)
47 sol = x;
48 }
49
50 fout<<sol<<"\n";
51 if (sol == n)
52 {
53 fout<<"0\n";
54 return 0;
55 }
56
57 p = 1;
58 u = k;
59 while (p<=u)
60 {
61 mid = (p+u)/2;
62
CAPITOLUL 18. ONI 2014 236
63 solc = m+2;
64 for (i=1,j=mid;j<=m;i++,j++)
65 {
66 if (a[i-1] > b[j+1])
67 x = a[i-1];
68 else
69 x = b[j+1];
70
71 if (x < solc)
72 solc = x;
73 }
74
75 if (solc == sol)
76 u = mid-1;
77 else
78 p = mid+1;
79 }
80
81 fout<<p<<"\n";
82
83 return 0;
84 }
1 #include <fstream>
2
3 using namespace std;
4
5 ifstream f("placa.in");
6 ofstream g("placa.out");
7
8 int s[300003],d[300003],m,n;
9
10 int calcul(int k)
11 {
12 int i,x=n+1,max;
13
14 for(i=1;i+k<=m;i++)
15 {
16 if(s[i]>d[i+k])
17 max=s[i];
18 else
19 max=d[i+k];
20 if(x>max)
21 x=max;
22 }
23
24 return x;
25 }
26
27 int minim(int k, int p)
28 {
29 int min1=p;
30
31 for(int i=1;i+k<=m;i++)
32 if(s[i]<=d[i+k] &&min1<=s[i])
33 min1=s[i];
34 else
35 if(s[i]>=d[i+k]&&min1<=d[i+k])
36 min1=d[i+k];
37
38 return min1;
39 }
40
41 int main()
42 {
43 int i,j,k,x,min,y,v[300003],st,dr,mij;
44
45 f>>n>>m>>k;
46
47 for(i=1;i<=m;i++)
48 {
49 f>>x>>y;
50
CAPITOLUL 18. ONI 2014 237
51 if(x+y>n)
52 v[i]=x;
53 else
54 v[i]=x+y;
55 }
56
57 s[1]=v[1];
58 for(j=2;j<=m;j++)
59 if(v[j]<s[j-1])
60 s[j]=s[j-1];
61 else
62 s[j]=v[j];
63
64 d[m]=v[m];
65 for(j=m-1;j>=1;j--)
66 if(v[j]<d[j+1])
67 d[j]=d[j+1];
68 else
69 d[j]=v[j];
70
71 min=minim(k,s[1]);
72 g<<min<<’\n’;
73
74 //a doua cerinta
75
76 st=1;dr=k;
77 mij=(st+dr)/2;
78 while(st<dr)
79 {
80 if(calcul(mij)>min)
81 st=mij+1;
82 else
83 dr=mij;
84
85 mij=(st+dr)/2;
86 }
87
88 g<<st-1<<’\n’;
89 f.close();
90 g.close();
91 return 0;
92 }
1 #include <iostream>
2 #include <fstream>
3
4 #define MAXN 100003
5 #define MAXM 500003
6 #define INF 100000000
7
8 using namespace std;
9
10 int n,m,k;
11 int hmin,kmin;
12 int nr1[MAXM]; //numarul de 1 de pe fiecare coloana
13 int x,y;
14 int maxS[MAXM];
15 int maxD[MAXM];
16
17 void solve_good()
18 {
19 maxS[0] = 0;
20 for(int i=1; i<=m; i++)
21 maxS[i] = max(maxS[i-1],nr1[i]);
22
23 maxD[m+1] = 0;
24 for(int i=m; i>=1; i--)
25 maxD[i] = max(maxD[i+1],nr1[i]);
26
27 for(int i=1; i<=m-k; i++)
28 hmin = min(hmin,max(maxS[i-1],maxD[i+k]));
29
30 int lb=0,ub=k; //lower_bound, upper_bound pentru BinarySearch
CAPITOLUL 18. ONI 2014 238
31 int kt;
32 int hcmin;
33 while (lb<=ub)
34 {
35 hcmin = INF;
36 kt = (lb+ub)/2;
37
38 for(int i=1; i<=m-kt; i++)
39 hcmin = min(hcmin,max(maxS[i-1],maxD[i+kt]));
40
41 if (hcmin==hmin)
42 kmin = min(kmin,kt);
43
44 if (hcmin>hmin)
45 lb = kt+1;
46 else
47 if (hcmin==hmin)
48 ub = kt-1;
49 }
50 }
51
52 int main()
53 {
54 ifstream fin("placa.in");
55 ofstream fout("placa.out");
56
57 fin>>n>>m>>k;
58
59 for(int j=1; j<=m; j++)
60 {
61 fin>>x>>y;
62 nr1[j]=x+y;
63 }
64
65 fin.close();
66
67 hmin = INF;
68 kmin = INF;
69
70 solve_good();
71
72 fout<<hmin<<"\n"<<kmin<<"\n";
73
74 fout.close();
75 return 0;
76 }
1 #include <fstream>
2 #define DIM 1000010
3
4 using namespace std;
5
6 int a[DIM], b[DIM], v[DIM];
7
8 int n, m, k, i, j, x, y, sol, solc, aux;
9
10 ifstream fin("placa.in");
11 ofstream fout("placa.out");
12
13 int main()
14 {
15 fin>>n>>m>>k;
16
17 for (i=1;i<=m;i++)
18 {
19 fin>>x>>y;
20 if (x == n)
21 v[i] = n;
22 else
23 v[i] = x+y;
24 }
25
26 a[1] = v[1];
CAPITOLUL 18. ONI 2014 239
27 for (i=2;i<=m;i++)
28 if (a[i-1] > v[i])
29 a[i] = a[i-1];
30 else
31 a[i] = v[i];
32
33 b[m] = v[m];
34 for (i=m-1;i>=1;i--)
35 if (v[i] > b[i+1])
36 b[i] = v[i];
37 else
38 b[i] = b[i+1];
39
40 sol = m+2;
41
42 for (i=1, j=k; j<=m; i++, j++)
43 {
44 if (a[i-1] > b[j+1])
45 x = a[i-1];
46 else
47 x = b[j+1];
48
49 if (x < sol)
50 sol = x;
51 }
52
53 aux = k;
54 for (k=1;k<=aux;k++)
55 {
56 solc = m+2;
57
58 for (i=1, j=k; j<=m; i++,j++)
59 {
60 if (a[i-1] > b[j+1])
61 x = a[i-1];
62 else
63 x = b[j+1];
64
65 if (x < solc)
66 solc = x;
67 }
68
69 if (solc == sol)
70 break;
71 }
72
73 fout<<sol<<"\n"<<k<<"\n";
74
75 return 0;
76 }
1 #include <fstream>
2 #define DIM 1000002
3
4 using namespace std;
5
6 ifstream fin("placa.in");
7 ofstream fout("placa.out");
8
9 int a[DIM];
10 int x, y, n, m, k, i, st, dr, maximst, maximdr, sol1;
11
12 int main()
13 {
14 fin>>n>>m>>k;
15
16 for(i=1;i<=m;i++)
17 {
18 fin>>x>>y;
19 if (x == n)
20 {
21 a[i] = x;
22
CAPITOLUL 18. ONI 2014 240
23 if (st == 0)
24 st = i;
25
26 dr = i;
27 }
28 else
29 a[i] = x + y;
30 }
31
32 maximst = 0;
33 for (i=1;i<st;i++)
34 if (a[i] > maximst)
35 maximst = a[i];
36
37 maximdr = 0;
38 for (i=m;i>dr;i--)
39 if (a[i] > maximdr)
40 maximdr = a[i];
41
42 if (maximst > maximdr)
43 sol1 = maximst;
44 else
45 sol1 = maximdr;
46
47 fout<<sol1<<"\n"<<dr-st+1;
48
49 return 0;
50 }
1 #include <fstream>
2 #define DIM 1000002
3
4 using namespace std;
5
6 int v[DIM], a[DIM], b[DIM];
7 int n, m, k, x, y, i, j, sol, solc, p, u, mid;
8
9 int main()
10 {
11 ifstream fin("placa.in");
12 ofstream fout("placa.out");
13
14 fin>>n>>m>>k;
15 for (i=1;i<=m;i++)
16 {
17 fin>>x>>y;
18 if (x!=n)
19 v[i] = x+y;
20 else
21 v[i] = n;
22 }
23
24 a[1] = v[1];
25 for (i=2;i<=m;i++)
26 if (a[i-1] > v[i])
27 a[i] = a[i-1];
28 else
29 a[i] = v[i];
30
31 b[m] = v[m];
32 for (i=m-1;i>=1;i--)
33 if (v[i] > b[i+1])
34 b[i] = v[i];
35 else
36 b[i] = b[i+1];
37
38 sol = m+2;
39 for (i=1,j=k;j<=m;i++,j++)
40 {
41 if (a[i-1] > b[j+1])
42 x = a[i-1];
43 else
44 x = b[j+1];
CAPITOLUL 18. ONI 2014 241
45
46 if (x < sol)
47 sol = x;
48 }
49
50 fout<<sol<<"\n";
51 fout<<k<<"\n";
52
53 return 0;
54 }
1 #include <iostream>
2 #include <fstream>
3
4 using namespace std;
5
6 ifstream f("placa.in");
7 ofstream g("placa.out");
8
9 int c[300000],m,n,k;
10
11 void maxcol(int &max,int &colmax1,int &colmax2)
12 {
13 int i;max=0;
14 for(i=1;i<=m;i++)
15 if(c[i]>max)
16 {
17 max=c[i];
18 colmax1=i;
19 colmax2=i;
20 }
21 else
22 if(c[i]==max)
23 colmax2=i;
24 }
25
26 void sterge(int k1,int k2)
27 {
28 int i;
29 for(i=k1;i<=k2;i++)
30 c[i]=0;
31 }
32
33 void afi(int m)
34 {
35 int i;
36
37 for(i=1;i<=m;i++)
38 cout<<c[i]<<" ";
39
40 cout<<endl;
41 }
42
43 int main()
44 {
45 int hmin,max,colmax1=3000000,colmax2=0,i,x,y,cm1,cm2;
46
47 f>>n>>m>>k;
48
49 hmin=n;
50 for(i=1;i<=m;i++)
51 {
52 f>>x>>y;
53 if(x==n)
54 c[i]=n;
55 else
56 c[i]=x+y;
57 }
58
59 // afi(m);
60 maxcol(max,colmax1,colmax2);
61 while(colmax2-colmax1+1<=k)
62 {
CAPITOLUL 18. ONI 2014 242
63 sterge(colmax1,colmax2);
64 hmin=colmax2-colmax1+1;
65
66 //afi(m);
67 maxcol(max,cm1,cm2);
68 if(colmax1>cm1) colmax1=cm1;
69 if(colmax2<cm2) colmax2=cm2;
70 }
71
72 g<<max<<endl;
73 g<<hmin<<endl;
74
75 return 0;
76 }
1 #include <fstream>
2 #define DIM 1000010
3
4 using namespace std;
5
6 int a[DIM], b[DIM], v[DIM];
7
8 int n, m, k, i, j, x, y, sol, solc, aux;
9
10 ifstream fin("placa.in");
11 ofstream fout("placa.out");
12
13 int main()
14 {
15 fin>>n>>m>>k;
16
17 for (i=1;i<=m;i++)
18 {
19 fin>>x>>y;
20 if (x == n)
21 v[i] = n;
22 else
23 v[i] = x+y;
24 }
25
26 a[1] = v[1];
27 for (i=2;i<=m;i++)
28 if (a[i-1] > v[i])
29 a[i] = a[i-1];
30 else
31 a[i] = v[i];
32
33 b[m] = v[m];
34 for (i=m-1;i>=1;i--)
35 if (v[i] > b[i+1])
36 b[i] = v[i];
37 else
38 b[i] = b[i+1];
39
40 sol = m+2;
41
42 for (i=1, j=k; j<=m; i++, j++)
43 {
44 if (a[i-1] > b[j+1])
45 x = a[i-1];
46 else
47 x = b[j+1];
48
49 if (x < sol)
50 sol = x;
51 }
52
53 aux = k;
54 for (k=aux;k>=1;k--)
55 {
56 solc = m+2;
57
58 for (i=1, j=k; j<=m; i++,j++)
CAPITOLUL 18. ONI 2014 243
59 {
60 if (a[i-1] > b[j+1])
61 x = a[i-1];
62 else
63 x = b[j+1];
64
65 if (x < solc)
66 solc = x;
67 }
68
69 if (solc != sol)
70 break;
71 }
72
73 fout<<sol<<"\n"<<k+1<<"\n";
74
75 return 0;
76 }
Capitolul 19
ONI 2013
19.1 secvp
Problema 1 - secvp 100 de puncte
Se consider un ³ir cu N numere naturale a1 , a2 , ..., aN . Asupra unui element ai , din ³ir, se
pot efectua operaµii de incrementare (adunare cu 1: ai ai 1) sau decrementare (sc dere cu 1:
ai ai 1). Fiecare element din ³ir poate incrementat sau decrementat de oricâte ori.
Cerinµe
Dat ind ³irul celor N numere naturale, s se determine:
a. num rul total minim de operaµii necesare pentru a transforma toate numerele din ³ir în
numere prime;
b. num rul minim de operaµii (increment ri ³i decrement ri) ce trebuie s e efectuate asupra
elementelor ³irului astfel încât s existe o secvenµ de lungime K format numai din numere prime.
Date de intrare
Fi³ierul de intrare secvp.in conµine pe prima linie numerele naturale N ³i K , iar pe urm toarea
linie N numere naturale. Numerele scrise pe aceea³i linie sunt separate prin spaµii.
Date de ie³ire
Fi³ierul de ie³ire secvp.out conµine pe prima linie un num r natural T , reprezentând num rul
total minim de operaµii necesare pentru a transforma toate numerele din ³ir în numere prime.
Pe a doua linie vor scrise dou numere naturale separate prin spaµiu minK nrsK , unde minK
reprezint num rul minim de operaµii ce trebuie s e efectuate asupra elementelor ³irului astfel
încât s existe o secvenµ de lungime K format numai din numere prime, iar nrsK reprezint
num rul de secvenµe de lungime K care se pot obµine cu acela³i num r minK de operaµii de
incrementare/decrementare.
Restricµii ³i preciz ri
a 2 & K & N & 100 000
a 0 & ai & 1 000 000, pentru 1 & i & N
a O secvenµ din ³ir este format din elemente aate pe poziµii consecutive în ³irul dat.
a 1 nu este num r prim.
a Pentru determinarea corect a valorii T se acord 30% din punctajul pe test. Pentru deter-
minarea corect a valorilor T ³i minK se acord 70% din punctajul pe test. Punctajul integral se
acord pentru determinarea corect a tuturor celor 3 valori.
Exemple
244
CAPITOLUL 19. ONI 2013 245
https://infogenius.ro/problema-secvp-oni-2013-clasa-7/
Pentru prima cerinµ vom parcurge ³irul, iar pentru ecare num r, calcul m modulul diferenµei
dintre el ³i cel mai apropiat num r prim de acesta. Pentru asta vom folosi o funcµie minInc în
care iter m pe i de la 0 în sus pân când xi sau xi este prim. Reµinem valorile g site într-un
vector inc de dimensiune N M AX (pentru a doua cerinµ ). Pe parcurs, pentru a aa r spunsul
primei cerinµe, calcul m suma acestor rezultate.
La a doua cerinµ practic trebuie s determin m suma minim pe care o poate avea o secvenµ
de lungime k ³i câte astfel de secvenµe exist în vectorul nostru.
Vom folosi Ciurul lui Eratostene pentru a testa mai apoi în O 1 primalitatea numerelor.
https://infogenius.ro/problema-secvp-oni-2013-clasa-7/
1 #include <fstream>
2
3 #define NMAX 100005
4 #define NRMAX 1000050
5
6 std::ifstream fin("secvp.in");
7 std::ofstream fout("secvp.out");
8
9 int n, k;
10 bool sieve[NRMAX]; // ciurul
11 short int inc[NMAX];
12
13 /** Functia care determina cu cat trebuie incrementat
14 sau decrementat x-ul pentru a deveni prim */
15
16 int minInc(int x)
17 {
18 // Tratam separat cazul x == 0 deoarece
19 // nu putem accesa ciur[-1] \c si ciur[-2]:
20 if (!x)
21 return 2;
22
CAPITOLUL 19. ONI 2013 246
19.2 patrate2
Problema 2 - patrate2 100 de puncte
Bia ³i tefan joac un nou joc. Bia i-a cerut lui tefan s se gândeasc la un num r natural
n
nenul mai mic strict decât V M AX 2 . Apoi, ea a luat un pix ³i o foaie ³i a desenat n matrice
p tratice (denumite pe scurt p trate), pe care le-a numerotat de la 1 la n. Apoi a completat
p tratele în modul urm tor: în p tratul cu num rul i au fost scrise în ordine cresc toare toate
numerele naturale nenule mai mici decât V M AX , care, scrise în baza 2, au cifra corespunz toare
i1
lui 2 , egal cu 1; plasarea numerelor s-a f cut parcurgând coloanele de la stânga la dreapta ³i
completând ecare coloan de sus în jos.
Fiecare p trat are latura minim necesar pentru ca numerele pe care trebuie s le conµin s
încap .
Este posibil ca p tratele s nu se umple integral (în acest caz p tratul se va completa cu
valoarea 0).
Dup ce a desenat p tratele, Bia îl întreab pe tefan în care dintre p trate se a num rul
la care s-a gândit el. Apoi face o magie ³i ghice³te num rul la care s-a gândit tefan.
În plus, ca s -l impresioneze ³i mai tare pe tefan, Bia i-a spus linia ³i coloana pe care este
plasat acest num r în primul p trat spus de tefan.
Cerinµe
Fiindc voi nu credeµi în magie, scrieµi un program care s determine num rul la care s-a
gândit tefan, precum ³i poziµia acestui num r în primul p trat spus de tefan.
Date de intrare
Fi³ierul de intrare patrate2.in conµine pe prima linie numerele naturale n ³i m, separate prin
spaµiu, reprezentând num rul de p trate pe care le va desena Bia, respectiv în câte dintre p tratele
desenate se a num rul la care s-a gândit tefan. Pe al doilea rând se a , separate prin câte
un spaµiu, m numere naturale cuprinse între 1 ³i n, reprezentând cele m p trate în care se a
num rul la care s-a gândit tefan.
Date de ie³ire
Fi³ierul de ie³ire patrate2.out va conµine pe prima linie num rul la care s-a gândit tefan.
Pe a doua linie vor scrise dou numere naturale separate prin spaµiu L C, reprezentând, linia,
respectiv coloana pe care se a num rul respectiv în primul p trat menµionat de tefan.
Restricµii ³i preciz ri
a 1 $ m & n & 28
a în ecare matrice p tratic liniile sunt numerotate de sus în jos începând cu 1, iar coloanele
de la stânga la dreapta începând cu 1.
a Pentru teste valorând 50% din punctaj, n este & 14.
a Pentru determinarea corect a num rului la care s-a gândit tefan se acord 40% din punc-
tajul pe test. Punctajul integral se obµine pentru rezolvarea ambelor cerinµe.
Exemple
patrate2.in patrate2.out Explicaµii
4 3 13
1 4 3 1 3
19.3 cursa
Problema 3 - cursa 100 de puncte
O curs de ma³ini electrice prev zute cu panouri solare are loc pe un traseu care traverseaz
n localit µi, numerotate în ordinea de pe traseu de la 1 la n. Linia de start se a la kilometrul
zero ³i coincide cu începutul primei localit µi. Linia de sosire este la sfâr³itul ultimei localit µi.
Orice localitate, exceptând localitatea 1, începe la sfâr³itul localit µii precedente. Prin urmare,
pentru ecare localitate i se cunoa³te distanµa di de la linia de start pân la sfâr³itul localit µii,
exprimat în km.
În momentul începerii competiµiei, din ecare localitate exist exact o ma³in aliniat la linia
de start. Ma³inile au acelea³i caracteristici, ca urmare se deplaseaz cu aceea³i vitez , cu excepµia
travers rii localit µii din care provin unde, datorit avantajelor terenului propriu (suporteri dotaµi
cu oglinzi, l mpi, etc...), î³i dubleaz instantaneu viteza pân la ie³irea din localitate, apoi revin
la viteza iniµial .
La concurs sunt invitate ³i televiziunile locale, iar pentru telespectatori, sarea ³i piperul sunt
dep ³irile, de aceea este important s reµinem informaµii despre acestea, pentru a le putea viziona
în reluare. Se consider dep ³ire situaµia în care o ma³in ajunge din urm o alt ma³in , apoi
trece în faµa acesteia.
Cerinµe
Cunoscând localit µile de pe traseu, scrieµi un program care tip re³te ordinea sosirii ma³inilor
la linia de sosire, respectiv informaµii despre toate dep ³irile efectuate în timpul concursului.
Date de intrare
Fi³ierul de intrare cursa.in va conµine pe prima linie num rul de localit µi n. Urmeaz n linii
care descriu informaµii despre cele n localit µi. i 1 din ³ier se a dou numere naturale
Pe linia
c ³i d, separate prin spaµiu, cu semnicaµia c num rul de concurs al ma³inii din localitatea i este
c ³i c localitatea i se termin la d kilometri faµ de linia de start.
Date de ie³ire
Fi³ierul de ie³ire cursa.out va conµine pe prima linie numerele de concurs ale ma³inilor în
ordinea sosirii lor, separate prin câte un spaµiu. în cazul în care exist mai multe ma³ini care
sosesc simultan la linia de sosire, acestea vor a³ate în ordinea cresc toare a numerelor de
concurs.
Pe urm toarele linii sunt descrise dep ³irile, în ordinea cresc toare a localit µilor în care se
produc. O dep ³ire este descris printr-o succesiune de valori de forma L c k m1 m2 ... mk ,
cu semnicaµia c în localitatea L ma³ina cu num rul de concurs c dep ³e³tek ma³ini, ma³inile
dep ³ite ind, în ordinea în care sunt dep ³ite, m1 m2 ... mk . DacÇ sunt depdzite în acela³i
moment dou sau mai multe ma³ini, acestea se vor a³a în ordinea descrescÇtoare a numerelor
de concurs.
Restricµii ³i preciz ri
CAPITOLUL 19. ONI 2013 249
a 2 $ n & 500
a Numerele de concurs ale ma³inilor sunt numere naturale nenule distincte de maxim 3 cifre.
a Distanµa dintre linia de start ³i linia de sosire (sfâr³itul ultimei localit µi) & 30 000
a Dac prima cerinµ este rezolvat corect, se obµine 40% din punctajul pe test. Dac prima
cerinµ este rezolvat corect, dar la a³area dep ³irilor ma³inile dintr-o localitate nu sunt a³ate
în ordinea solicitat , se acord 70% din punctajul pe test. Punctajul integral se obµine pentru
rezolvarea corect a ambelor cerinµe.
Exemple
cursa.in cursa.out Explicaµii
5 70 35 99 10 66 Prima localitate începe de la km.0 ³i se termin la km.5 ³i are
10 5 3 99 2 66 10 ma³ina nr. 10.
66 7 4 35 2 66 10 A doua localitate se a între km 5-7 ³i are ma³ina nr. 66.
99 15 5 70 4 66 10 99 35 A treia localitatea se a între km 7-15 ³i are ma³ina nr. 99.
35 23 A patra între km 15-23 are ma³ina nr. 35 ³i ultima între km
70 34 23-34 are ma³ina 70.
Ordinea de sosire a ma³inilor este: 70 35 99 10 66.
Ma³inile 35 ³i 99 termin cursa deodat , se enumer în ordinea
cresc toare a numerelor.
Dep ³iri: Localitatea 3: ma³ina 99 va dep ³i 2 ma³ini, în or-
dine ma³inile 66 apoi 10.
Localitatea 4: ma³ina 35 dep ³e³te 2 ma³ini, pe 66 ³i 10 ³i
ajunge pe 99 f r s o dep ³easc .
Localitatea 5: ma³ina 70 dep ³e³te 4 ma³ini, în ordine pe 66,
10, apoi simultan pe 99 ³i 35 aate la egalitate (se enumer în
ordine descresc toare).
ONI 2012
20.1 bile
Problema 1 - bile 100 de puncte
Matei a inventat un nou joc cu bile. Terenul de joc este o tabl dreptunghiular a³ezat
vertical. Tabla este împ rµit în m n celule, a³ezate în m linii ³i n coloane. În unele dintre celule
se a obstacole.
De sus, din celulele aate pe prima linie, sunt l sate s cad bile. Bilele cad vertical pân
la întâlnirea unui obstacol sau pân în celula cea mai de jos din coloana pe care se a . Prima
bil care love³te un obstacol se deplaseaz pe orizontal în coloana al turat din stânga, apoi
î³i continu c derea. Fiecare dintre celelalte bile care lovesc acela³i obstacol se deplaseaz pe
orizontal , în coloana al turat , dar în direcµie opus faµ de bila care a lovit acest obstacol exact
înaintea lor, apoi î³i continu c derea.
Cerinµe
Cunoscând num rul de bile l sate s cad de pe ecare celul a primei linii ³i poziµia obsta-
colelor, determinaµi num rul de bile ajunse în ecare celul a ultimei linii. Poziµiile obstacolelor
sunt indicate prin linia ³i coloana lor (colµul din stânga sus corespunde liniei 1 ³i coloanei 1).
Date de intrare
Fi³ierul bile.in conµine pe prima linie, separate prin câte un spaµiu, numerele naturale m, n ³i
p (num rul de linii, num rul de coloane ³i num rul de obstacole). Urm toarele p linii conµin câte
dou numere, separate de câte un spaµiu, reprezentând poziµiile celor p obstacole. Ultimele n linii
conµin câte un num r natural, reprezentând num rul bilelor lansate din ecare celul a primei linii
(începând cu prima celul de pe linie).
Date de ie³ire
Fi³ierul de ie³ire bile.out va conµine n linii cu câte un num r, acesta reprezentând num rul
de bile din ecare celul a ultimei linii (începând cu prima celul de pe aceast linie).
Restricµii ³i preciz ri
a 2 & m, n & 2000;
a 0 & p & 10000;
a Se lanseaz maximum 1000 de bile din ecare celul ;
a Pe prima ³i ultima linie, respectiv prima ³i ultima coloan , nu exist obstacole;
a Nu exist dou obstacole al turate pe linie, coloan sau diagonal .
Exemple
250
CAPITOLUL 20. ONI 2012 251
Se poate simula c derea bilelor folosind o matrice mn în care punem, de exemplu, 1 în
celulele cu obstacole ³i un num r pozitiv - num rul de bile ajunse în celula respectiv . Soluµia nu
se va încadra în timp pentru dimensiuni mai mari.
Se poate încerca eliminarea liniilor care nu au obstacole, ceea ce nu va aduce un câ³tig sub-
stanµial de timp.
Soluµia optim presupune ordonarea poziµiilor obstacolelor cresc tor dup linii (pe aceea³i linie
nu conteaz ordinea obstacolelor, ele neinuenµându-se reciproc) apoi, considerând ³irul bilelor de
pe prima linie b1 , b2 , ..., bn , ecare obstacol de pe poziµia i, j va modica 3 termeni din acest
³ir: la bj 1 se adaug bj 1©2, la bj 1 se adaug bj ©2 iar bj devine 0.
Astfel complexitatea algoritmului va dat de complexitatea algoritmului de sortare, dup
care determinarea num rului de bile de pe ecare coloan se obµine în O p.
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 struct coord
5 {
6 int x;
7 int y;
8 } a[10002];
9
10 int fc(const void *a, const void *b)
11 {
12 return ((struct coord *)a)->x - ((struct coord *)b)->x;
13 }
14
15 int main()
16 {
17 FILE *fi, *fo;
18
19 int m,n,i,j,p,b[5002];
CAPITOLUL 20. ONI 2012 252
20 coord t;
21
22 fi=fopen("bile.in","r");
23
24 fscanf(fi,"%d %d %d",&m,&n,&p);
25
26 for(i=1;i<=p;i++)
27 fscanf(fi,"%d %d",&a[i].x,&a[i].y);
28 for(i=1;i<=n;i++)
29 fscanf(fi,"%d",&b[i]);
30
31 fclose(fi);
32
33 qsort(a+1,p,sizeof a[0],fc);
34
35 for(i=1;i<=p;i++)
36 {
37 j=a[i].y;
38 b[j-1]+=b[j]/2+b[j]%2;
39 b[j+1]+=b[j]/2;
40 b[j]=0;
41 }
42
43 fo=fopen("bile.out","w");
44 for(i=1;i<=n;i++)
45 fprintf(fo,"%d\n",b[i]);
46
47 fclose(fo);
48 return 0;
49 }
20.2 proiecte
Problema 2 - proiecte 100 de puncte
În ora³ul Ia³i, cele N rme IT deruleaz în prezent M proiecte din acest domeniu (printre
care ³i ONI 2012). Firmele sunt identicate prin numere naturale de la 1 la N, iar proiectele
sunt identicate prin numere naturale de la 1 la M. Fiecare proiect are una sau mai multe etape,
o etap ind executat de o singur rm IT. Spunem c o rm coordoneaz un proiect dac
execut mai mult de jum tate din etapele proiectului.
Cerinµe
Cunoscând num rul rmelor IT, num rul proiectelor, num rul de etape ale ec rui proiect
³i rmele ce execut ecare etap , s se determine rma/rmele care coordoneaz cel mai mare
num r de proiecte.
Date de intrare
Fi³ierul de intrare proiecte.in conµine, pe prima linie, numerele naturale N ³i M, separate
printr-un spaµiu, cu semnicaµia de mai sus. Pe ecare dintre urm toarele M linii se a in-
formaµii despre câte un proiect, în ordinea numerelor de identicare a acestora. Astfel, pe linia
corespunz toare proiectului i (1 & i & M ), se a un num r natural nri , urmat de nri numere
naturale f1 f2 ... fnri , reprezentând num rul de etape ale acestui proiect, respectiv rmele care
execut ecare etap din proiect (rma fk execut etapa k, 1 & k & nri ). Numerele de pe aceea³i
linie sunt separate prin câte un spaµiu.
Date de ie³ire
Fi³ierul de ie³ire proiecte.out va conµine o singur linie, pe care va scris num rul de iden-
ticare al rmei/rmelor care coordoneaz cel mai mare num r de proiecte. Dac sunt mai multe
astfel de rme, numerele de identicare ale acestora se vor a³a pe aceea³i linie, în ordine cresc -
toare, separate prin câte un spaµiu.
Restricµii ³i preciz ri
CAPITOLUL 20. ONI 2012 253
Exemple
proiecte.in proiecte.out Explicaµii
5 4 1 3 Num rul maxim de proiecte coordonate de aceea³i rm este 2:
2 3 3 rma 1 coordoneaz proiectele 2 ³i 4, iar rma 3 coordoneaz
3 1 2 1 proiectele 1 ³i 3.
5 3 4 3 3 1
1 1
a) Pentru început trebuie s determin m pentru ecare proiect, dac exist , rma care îl
coordoneaz ,
Vom citi pe rând, într-un vector datele corespunz toare unui proiect, pentru a rezolva prima
subproblem , trebuie s g sim dac exist un element majoritar în acest vector.
Iniµializ m candidatul la majoritate cu primul element, dac un element din vector este egal cu
candidatul increment m un contor, dac este diferit, decrement m contorul. Veric m contorul
la ecare pas, dac este 0, schimb m candidatul la majoritate cu elementul curent.
In nal vericam dac valoarea memorat în candidatul la majoritate este element majoritar,
num rând efectiv num rul de apariµii.
Ordon m vectorul V, apoi determinam maximul din vectorul NR ³i elementele din V pentru
care avem valoarea maxim în vectorul N R, datorit sort rii elementele vor a³ate în ordine
cerut .
1 #include<fstream>
2
3 using namespace std;
4
5 FILE * fin;
CAPITOLUL 20. ONI 2012 254
6 ofstream fout("proiecte.out");
7
8 int v[201], x[200001],Nr[201];
9 int n, m,cand,k;
10 int i,nr,j,nrmax,nrap,ok,aux;
11
12 int main()
13 {
14 fin=fopen("proiecte.in","r");
15 fscanf(fin,"%d%d",&n,&m);
16
17 for(i=1;i<=m;i++)
18 {
19 fscanf(fin,"%d",&nr);//fin>>nr;
20
21 for(j=1;j<=nr;j++)
22 fscanf(fin,"%d",&x[j]);
23
24 cand=x[1];nrap=1;
25 for(j=2;j<=nr;j++)
26 if(x[j]==cand)
27 nrap++;
28 else
29 if(nrap>0)nrap--;
30 else
31 {
32 nrap=1;
33 cand=x[j];
34 }
35
36 if(nrap>0)
37 {
38 nrap=0;
39 for(j=1;j<=nr;j++)
40 if(x[j]==cand)nrap++;
41 }
42
43 if(nrap>nr/2)
44 {
45 ok=0;
46 for(j=1;j<=k;j++)
47 if(v[j]==cand)
48 {
49 ++Nr[j];
50 ok=1;
51 break;
52 }
53
54 if(ok==0)
55 {
56 v[++k]=cand;
57 Nr[k]=1;
58 }
59 }
60 }
61
62 ok=0;
63 while(!ok)
64 {
65 ok=1;
66 for(j=1;j<=k-1;j++)
67 if(v[j]>v[j+1])
68 {
69 aux=v[j];
70 v[j]=v[j+1];
71 v[j+1]=aux;
72 aux=Nr[j];
73 Nr[j]=Nr[j+1];
74 Nr[j+1]=aux;
75 ok=0;
76 }
77 }
78
79 nrmax=Nr[1];
80 for(j=2;j<=k;j++)
81 if(nrmax<Nr[j])
CAPITOLUL 20. ONI 2012 255
82 nrmax=Nr[j];
83
84 for(j=1;j<=k;j++)
85 if(nrmax==Nr[j])
86 fout<<v[j]<<’ ’;
87
88 fout<<’\n’;
89 fout.close();
90 return 0;
91 }
1 #include<iostream>
2 #include<algorithm>
3
4 using namespace std;
5
6 int f[1000],pr[1000],N,c[210],K;
7 int a[200002];
8 int m,n,i,j,k,val,ap,p,q,r,max1;
9
10 void sortare()
11 {
12 int s;
13 do
14 {
15 s=1;
16 for(int i=1;i<N;i++)
17 if(f[i]>f[i+1])
18 swap(f[i],f[i+1]),s=0;
19 } while(!s);
20 }
21
22 int main()
23 {
24 freopen("proiecte.in","r",stdin);
25 freopen("proiecte.out","w",stdout);
26
27 cin>>n>>m;
28 for(i=1;i<=m;i++)
29 {
30 cin>>k;
31 for(j=1;j<=k;j++)
32 //cin>>a[j];
33 scanf("%d",&a[j]);
34
35 sort(a+1,a+k+1);
36
37 val=a[(k+1)/2];
38 a[0]=a[k+1]=0;
39 ap=1;
40 p=(k+1)/2;
41 q=p+1;
42 r=p-1;
43 while(a[q]==val)
44 ap++,q++;
45 while(a[r]==val)
46 ap++,r--;
47 if(ap>=k/2+1)
48 {
49 N++;
50 f[N]=val;
51 }
52 }
53
54 sortare();
55
56 //for(i=1;i<=N;i++) cout<<f[i]<<" ";
57 //cout<<endl<<N<<endl;
58 int nr;
59 f[N+1]=0;
60 max1=0;
61 for(i=2;i<=N+1;i++)
62 {
CAPITOLUL 20. ONI 2012 256
63 nr=1;
64 while(f[i]==f[i-1])
65 nr++,i++;
66 if(max1<nr)
67 max1=nr,K=1,c[K]=f[i-1];
68 else
69 if(max1==nr)
70 K++,c[K]=f[i-1];
71 }
72
73 for(i=1;i<=K;i++)
74 cout<<c[i]<<" ";
75
76 return 0;
77 }
20.3 zigzag
Problema 3 - zigzag 100 de puncte
Rail Fence Cipher, cunoscut sub numele de cifru zig-zag, este o metod de codicare a mesajelor
folosind un caroiaj în care textul este scris începând din colµul stânga-sus, diagonal de sus în jos,
iar apoi, dup ce s-a scris caracterul de pe ultima linie, se continu , diagonal de jos în sus, ca în
exemplu. Num rul de linii ale caroiajului este cheia de codicare. Dup ce textul a fost scris în
acest mod, mesajul codicat se obµine parcurgând liniile de sus în jos ³i preluând de pe ecare
linie toate caracterele de la stânga la dreapta. Dac vrem s codic m textul OLIMPIADA DE
INFORMATICA, cu cheia de codicare 6, atunci se procedeaz astfel:
1. Se scrie textul în zigzag în caroiaj
Cerinµe
Scrieµi un program care cite³te cheia de codicare ³i un text codicat ³i determin mesajul
decodicat.
Date de intrare
Pe prima linie a ³ierului zigzag.in se a dou numere naturale c ³i n, separate printr-
un spaµiu, unde c reprezint cheia de codicare, iar n num rul de caractere al mesajului, ³i pe
urm toarea linie un ³ir format din n caractere ce reprezint mesajul codicat.
Date de ie³ire
Fi³ierul zigzag.out va conµine o singur linie, pe care se a mesajul decodicat.
Restricµii ³i preciz ri
a 1 $ c $ 5000;
a 1 $ n $ 50000;
a în mesaj sunt doar caractere cu codul ASCII mai mic ca 127 ³i mai mare ca 31.
Exemple
zigzag.in zigzag.out Explicaµii
6 24 OLIMPIADA DE INFORMATICA
ODTL EAIIA MCMDIRAPANOIF
CAPITOLUL 20. ONI 2012 257
1 #include<fstream>
2 #include<string>
3
4 using namespace std;
5
6 FILE *fin;
7
8 ofstream fout("zigzag.out");
9
10 char s[100010], a[50010],chr;
11 int n,c,x,p,k,nr,m,i;
12
13 int main()
14 {
15 fin=fopen("zigzag.in","r");
16 fscanf(fin,"%d%d",&c,&n);
17 fscanf(fin,"%c",&chr);
18
19 for(i=1;i<=n;i++)
20 {
21 fscanf(fin,"%c",&chr);
22 a[i]=chr;
23 }
24
25 nr = (n%(2*c-2)==0 ? n/(2*c-2) : n/(2*c-2)+1);
26 m=nr*(2*c-2);
27
28 for(i=n+1;i<=m;i++)
29 s[i]=’X’;
30 k=1;
31
32 //rand 1
33 for(x=0;x<=nr-1;x++)
CAPITOLUL 20. ONI 2012 258
34 if(s[x*(2*c-2)+1]!=’X’)
35 s[x*(2*c-2)+1]=a[k++];
36
37 //randuri de la 2 la c-1
38 for(p=2;p<=c-1;p++)
39 for(x=0;x<=nr-1;x++)
40 {
41 if(s[x*(2*c-2)+p]!=’X’)
42 s[x*(2*c-2)+p]=a[k++];
43 if(s[x*(2*c-2)+2*c-p]!=’X’)
44 s[x*(2*c-2)+2*c-p]=a[k++];
45 }
46
47 //rand c
48 for(x=0;x<=nr-1;x++)
49 if(s[x*(2*c-2)+c]!=’X’)
50 s[x*(2*c-2)+c]=a[k++];
51
52 for(i=1;i<=n;i++)
53 fout<<s[i];
54
55 fout<<’\n’;
56 fout.close();
57 return 0;
58 }
Capitolul 21
ONI 2011
21.1 joc
Problema 1 - joc 100 de puncte
Georgel ³i Ionel au inventat un joc. Georgel scrie în ecare p tr µel pe o foaie de matematic ,
de forma unui tablou bidimensional cu n linii ³i m coloane, valori de 0 sau 1. Ionel stabile³te 3
forme distincte pe care Georgel trebuie s le identice pe foaia de matematic în poziµia dat sau
rotite ca în gura 1, 2 sau 3. Cele trei forme propuse sunt:
Pentru un joc, Georgel trebuie s le identice pe foaie sub forma de p tr µele pline cu 1.
Cerinµe
Scrieµi un program care s identice num rul de apariµii pentru toate formele precizate.
Date de intrare
Fi³ierul joc.in conµine pe prima linie valorile lui n ³i m separate printr-un spaµiu, pe urm -
toarele n linii ind valorile din p tr µelele de pe foaie (neseparate prin spaµii).
Date de ie³ire
Fi³ierul joc.out va conµine pe prima linie num rul total de forme identicate, de oricare din
cele trei tipuri.
Restricµii ³i preciz ri
a 0 $ m, n $ 100
a Un p tr µel se poate reg si în una sau mai multe forme.
259
CAPITOLUL 21. ONI 2011 260
Exemple
joc.in joc.out Explicaµii
5 5 7 Exist 2 forme de primul tip, 3 forme de tipul al doilea ³i 2 de al treilea tip,
00100 ca în desen.
00110
01111
00100
00100
Se încadreaz ecare form aat e în poziµia iniµial , e rotit într-o matrice cu 3 linii ³i 3
coloane, p tr µelele formei ind elemente egale cu 1. Se formeaz astfel 12 matrice. Se caut apoi
în matricea iniµial toate cele 12 matrice, vericându-se doar elementele egale cu 1. Se num r
formele g site ³i se a³eaz rezultatul obµinut.
21.2 mesaj
Problema 2 - mesaj 100 de puncte
Maria ³i Ionuµ doresc s comunice între ei prin bileµele. Pentru ca mesajele lor s nu e
înµelese ³i de ceilalµi colegi, ei se hot r sc s le codice. Pentru a codica un mesaj, Maria ³i Ionuµ
procedeaz astfel:
a aleg împreun un cuvânt s numit cheie format din p litere diferite dou câte dou ;
a împart mesajul pe care doresc s -l transmit între ei în secvenµe de caractere al turate de
lungime p, cu excepµia ultimei secvenµe care poate avea mai puµin de p caractere;
a scriu pe foaie cuvântul cheie ales;
a sub cuvântul cheie ales se scriu secvenµele de lungime p determinate anterior, în ordinea
obµinerii lor;
a mesajul codicat se obµine astfel:
` se parcurge tabelul obµinut anterior, pe coloane, de sus în jos;
` ordinea de parcurgere a coloanelor este ordinea alfabetic a literelor din cuvântul cheie;
Cerinµe
Scrieµi un program care s determine litera din mesajul codicat care apare de cele mai puµine
ori, iar dac sunt mai multe astfel de litere, prima dintre acestea în ordine alfabetic ³i s realizeze
decodicarea unui mesaj codicat în modul prezentat anterior.
Date de intrare
Fi³ierul de intrare mesaj.in conµine:
- pe prima linie num rul p de caractere din cheie;
- pe a doua linie cuvântul cheie ales de Maria ³i Ionuµ;
- pe a treia linie num rul n de caractere din mesajul codicat;
- pe a patra linie mesajul codicat.
CAPITOLUL 21. ONI 2011 261
Date de ie³ire
Fi³ierul de ie³ire mesaj.out va conµine:
- pe prima linie litera din mesajul codicat care apare de cele mai puµine ori în mesajul codicat;
dac sunt mai multe astfel de litere, prima dintre acestea în ordine alfabetic ;
- pe a doua linie mesajul decodicat.
Restricµii ³i preciz ri
a Cuvântul cheie conµine numai litere mari ale alfabetului englez (A, B, C,...,Z) ³i are maxim
26 de litere;
a Mesajul codicat conµine litere mari ale alfabetului englez, cuvintele sunt separate prin unul
sau mai multe spaµii;
a Lungimea mesajului codicat nu dep ³e³te 2000 de caractere.
a Se acord punctaje parµiale:
µ 20% pentru a³area valorii corecte pe prima linie a ³ierului mesaj.out (cerinµa a)
µ 80% pentru a³area corect a mesajului pe linia a doua a ³ierului mesaj.out (cerinµa
b)
Exemple
mesaj.in mesaj.out
8 COMPUTER F
44 SUCCES LA OLIMPIADA NATIONALA DE INFORMATICA
SAAO T PTDMCOAANCU DNIICL LFALIIEASMA REINAO
Explicaµii:
Maria ³i Ionuµ aleg cuvântul cheie COMPUTER
Mesajul pe care doresc s -l codice este:
SUCCES LA OLIMPIADA NATIONALA DE INFORMATICA
Tabelul obµinut este urm torul:
- Pentru determinarea literei care apare de cele mai puµine ori se construie³te un vector în care
se p streaz num rul de apariµii pentru ecare liter . Se identic apoi litera care apare în mesaj
³i are num r minim de apariµii.
- Se construie³te un vector v în care p streaz ordinea de parcurgere a coloanelor.
Se cite³te mesajul codicat ³i, folosind vectorul v, determinat la pasul anterior, se construie³te
matricea necesar pentru decodicare.
Textul decodicat se obµine prin parcurgerea matricei pe linii.
21.3 zar
Problema 3 - zar 100 de puncte
Maria a primit cadou un joc. Jocul are o tabl sub form de caroiaj dreptunghiular format
din p tr µele de latur 1 dispuse în L linii ³i C coloane. P tr µelele conµin primele LC numere
naturale nenule începând cu 1, reprezentând coduri.
9 10 11 12
Codicarea se face astfel: se începe cu valoarea 1 din p tr µelul din
8 7 6 5
stânga-jos, se continu cu valorile 2,3,...C de la stânga la dreapta, continu
1 2 3 4
pe rândul urm tor de la dreapta la stânga ³i a³a mai departe. în acest fel
ultimul p tr µel va codicat întotdeauna cu valoarea L*C, ca în exemplul din dreapta.
Jocul const în plasarea unui jeton în colµul din stânga jos ³i trebuie s se duc jetonul dincolo
de p tr µelul codicat cu valoarea L*C în urma mut rilor realizate. Pentru efectuarea unei mut ri,
el arunc mai întâi un zar. Dac acesta arat valoarea Z ³i jetonul se a în p tr µelul cu codul
P, jetonul va dus în p tr µelul cu codul P+Z. Dac P+Z>L*C, jocul se termin . în caz contrar,
exist situaµii în care jetonul nu va r mâne neap rat în noua poziµie, întrucât în unele poziµii ale
caroiajului sunt indicatoare care precizeaz unde trebuie dus jetonul care tocmai a ajuns în acea
poziµie.
4 3 2
Un p tr µel poate s conµin cel mult un indicator. Indicatoarele sunt de 9
5 X 1
tipuri: pentru primele 8 tipuri se precizeaz peste câte poziµii se va plasa jetonul
6 7 8
din poziµia curent , respectiv: pe aceea³i linie la dreapta(1), în diagonal pe
direcµia dreapta-sus(2), pe aceea³i coloan în sus(3), pe diagonal pe direcµia stânga-sus(4), pe
aceea³i linie la stânga(5), pe diagonal pe direcµia stânga-jos(6), pe aceea³i coloan în jos(7), în
diagonal pe direcµia dreapta-jos(8). Indicatorul de tipul 9 precizeaz codul unui p tr µel în care
va plasat jetonul.
La aplicarea unui indicator se respect regulile:
a) dac jetonul iese în afara tablei, acest indicator va neglijat, iar jetonul va r mâne pe loc
(jocul nu se poate termina astfel).
b) dac se ajunge într-un p tr µel care conµine un alt indicator, acesta nu va mai luat în
considerare.
Cerinµe
Cunoscând, în ordine, cele K valori obµinute în urma arunc rilor cu zarul, s se determine
dac jocul se poate încheia. în caz armativ se va a³a num rul de arunc ri cu zarul dup care
jocul se încheie. în caz contrar, se va a³a poziµia jetonului dup cele K mut ri.
Date de intrare
Fi³ierul zar.in conµine pe prima linie dou numere L ³i C reprezentând num rul de linii,
respectiv num rul de coloane ale tablei de joc.
Pe linia a 2-a se g se³te un num r natural I reprezentând num rul de p tr µele în care se
g sesc indicatoare.
Pe urm toarele I linii se g sesc câte 3 numere naturale separate prin câte un spaµiu repre-
zentând descrierea câte unui indicator. Primul num r este codul p tr µelului în care este pus
indicatorul, al doilea num r este tipul de indicator. Dac tipul de indicator este 9, al treilea nu-
m r semnic codul p tr µelului unde va trimis jetonul. Dac al doilea num r este din mulµimea
{1, 2, 3, 4, 5, 6, 7, 8}, al treilea num r reprezint num rul de poziµii de pe tabl peste care se va
muta jetonul în direcµia precizat .
Pe linia urm toare se a un num r natural K reprezentând num rul de arunc ri cu zarul.
Pe urm toarea linie sunt K numere naturale separate prin câte un spaµiu, reprezentând, în
ordine, valorile obµinute dup ecare aruncare.
Date de ie³ire
Fi³ierul zar.out va conµine pe prima linie dou numere naturale separate printr-un spaµiu.
Dac jocul se termin , prima valoare va 1, iar a doua va reprezenta num rul de mut ri dup
care s-a terminat. Dac jocul nu se termin , prima valoare va 2, iar a doua codul p tr µelului
unde a r mas jetonul.
CAPITOLUL 21. ONI 2011 263
Restricµii ³i preciz ri
a 1 & L, C & 50; 0 & I & L C;
a 1 & K & 1000;
a Valorile obµinute în urma arunc rilor cu zarul sunt numere din mulµimea {1, 2, 3, 4, 5, 6};
a Num rul de poziµii cu care se poate deplasa jetonul pentru un indicator de tip 1-8 este num r
întreg nenul & 50;
Exemple
zar.in zar.out Explicaµii
3 4 2 11 Iniµial jetonul este în p tr µelul 1. Dup prima mutare el ajunge în
4 p tr µelul 5 (zarul arat 2 ³i jetonul ar ajunge în p tr µelul 3 dar
3 2 1 indicatorul de acolo în trimite în p tr µelul 5). Dup mutarea a doua
8 1 1 jetonul ajunge în p tr µelul 6 (acolo îl trimite zarul ³i nu este întâlnit
7 1 2 un indicator). Dup mutarea a treia, jetonul ajunge în p tr µelul
9 9 11 7 (zarul îl trimite în 8, iar indicatorul de acolo în 7 â acum nu
4 se tine cont de indicatorul din 7). Dup mutarea 4 jetonul ajunge la
2 1 2 2 p tr µelul 11 (dup aruncarea cu zarul trebuia dus în 9 iar indicatorul
de acolo îl trimite în 11).
Se simuleaz mut rile conform regulilor din enunµ. Probabilitatea de a gre³i tratând multitu-
dinea de cazuri ce pot ap rea poate sc zut printr-o codicare ecient a datelor. Astfel, se pot
pastra structuri de date care s permit determinarea poziµiei pe tabla de joc pentru un cod dat
(un vector de structuri, V k .i ³i V k .j sunt poziµiile pe tabla de joc ale p tr µelului cu codul
k ), respectiv pentru determinatea codului p tr µelului aat pe poziµia i, j pe tabla de joc (o
matrice, M ij = codul p tr µelului de pe poziµia i, j ).
Aceste structuri se construiesc la citirea datelor. Se poate renunµa la utilizarea structurilor
scriind funcµii care s fac trecerea de la cod la coordonate ³i invers. Se pot utilize 2 vectori de
direcµii, di ³i dj , deplasarea cu x pa³i din poziµia i, j pe direcµia k putându-se face prin construcµii
de forma i x di k , j x dj k .
ONI 2010
22.1 char
Problema 1 - char 100 de puncte
Alex a primit de la Mo³ Cr ciun un joc foarte interesant. Jocul este format dintr-un text cu
n litere mici ale alfabetului englez. Fiecare liter are o anumit putere, dat printr-un num r
natural. Puterea k a unei litere c const în faptul c , dac aceasta este atins atunci toate literele
din secvenµa de k litere, din stânga ³i din dreapta se transform în c. Spre exemplu, dac litera x
are puterea 2, atunci dup atingere, textul abcbxpbrr se transform în abxxxxxrr. Cunoscând
puterea ec rei litere, jocul const în determinarea num rului maxim m de litere, care dup
atingere s transforme orice liter din text cel mult o dat .
Cerinµe
Scrieµi un program care s citeasc un text cu n litere, puterea ec rei litere ³i s a³eze
num rul de litere din text cu puterea maxim , notat cu q precum ³i num rul m.
Date de intrare
În ³ierul char.in se dau:
- pe prima linie: num rul natural n
- pe a doua linie: cele n litere ale textului f r spaµiu între ele
- pe a treia linie: num rul h de litere distincte din text
- pe a patra linie: h numere naturale separate între ele prin câte un spaµiu reprezentând puterea
literelor din text în ordine alfabetic .
Date de ie³ire
Fi³ierul char.out va conµine pe prima linie num rul q ³i pe a doua linie num rul m.
Restricµii ³i preciz ri
a 1 & n & 10000,
a 1 & putere liter & 100
a Dac în stânga sau dreapta unei litere sunt mai puµine litere decât puterea, atunci atingerea
ei conduce la transformarea tuturor literelor din stânga, respectiv dreapta.
a Se acord 30% din punctaj pentru determinarea num rului q ³i 70% din punctaj pentru
determinarea num rului m.
a Prima liter din text este pe poziµia 1, a doua liter pe poziµia 2, ³i a³a mai departe.
Exemple
char.in char.out Explicaµii
12 6 Litera a are puterea 2, litera b puterea 5, litera c puterea 3,
acbbxacbbbxb 3 respectiv litera x are puterea 2.
4 Litera cu puterea maxim este b ³i apare în secvenµ de 6 ori.
2 5 3 2 Num rul maxim de litere, care pot atinse astfel încât oricare
liter a textului s se transforme cel mult o dat este 3 (de
exemplu se pot atinge literele de pe poziµiile 1, 6, 11).
1. Se construie³te un vector v 1, v 2, ..., v h cu literele distincte din text, astfel ec rei
v
litere v i pi, i 1, ..., h.
îi corespunde o putere
2. Se determin în max puterea maxim ³i apoi poziµiile literelor cu puterea egal cu max în
text. Pentru ecare astfel de liter determinat anterior, se incrementeaz variabila q .
3. Pentru a doua cerinµ se observ faptul c ec rei litere îi corespunde o porµiune continu de
litere din text. O astfel de porµiune este caracterizat prin cap tul din stânga, respectiv dreapta.
Determin m în doi vectori st st1, ..., stn, dr dr1, ..., drn aceste capete de porµiuni.
4. Acum problema se reduce la determinarea unui num r maxim de porµiuni disjuncte. Acest
num r este num rul c utat m.
1 #include <fstream>
2
3 using namespace std;
4
5 char x[10003],y[100];
6 int s[10003],d[10003],i,h,p[100],n,k,nr,t,j,aux,m,maxx,i1,j1;
7
8 void afis()
9 {
10 ofstream fout("char.out");
11 fout<<nr<<’\n’<<m;
12 fout.close();
13 }
14
15 void cit()
16 {
17 int i,j,sw;
18 char aux;
19
20 ifstream fin("char.in");
21 fin>>n;
22 fin.get();
23
24 for (i=1;i<=n;i++)
25 x[i]=fin.get();
26 fin.get();
27
28 fin>>h;
29 for (i=1;i<=h;i++)
30 fin>>p[i];
31 fin.close();
32
33 //lit dist din x
34 k=0;
35 for (i=1;i<=n;i++)
36 {
37 sw=1;
38 for (j=1;j<=k;j++)
39 if (y[j]==x[i])
40 {
41 sw=0;
42 break;
43 }
44
45 if (sw)
CAPITOLUL 22. ONI 2010 266
46 {
47 k++;
48 y[k]=x[i];
49 }
50 }
51
52 for (i=1;i<k;i++)
53 for (j=i+1;j<=k;j++)
54 if (y[i]>y[j])
55 {
56 aux=y[i];
57 y[i]=y[j];
58 y[j]=aux;
59 }
60
61 // for(i=1;i<=h;i++) cout<<y[i]<<" "<<p[i]<<’\n’;
62 }
63
64 int putere(char c)
65 {
66 int i;
67 for (i=1;i<=h;i++)
68 if (y[i]==c)
69 return p[i];
70 return 0;
71 }
72
73 int main()
74 {
75 cit();
76
77 //prima parte
78 maxx=0;
79 for (i=1;i<=h;i++)
80 if (p[i]>maxx)
81 maxx=p[i];
82
83 nr=0;
84 for (i=1;i<=n;i++)
85 if (maxx==putere(x[i]))
86 nr++;
87
88 //a doua parte
89 //cout<<"\n";
90 for (i=1;i<=n;i++)
91 {
92 t=putere(x[i]);
93 i1=i-t;
94 j1=i+t;
95 if (i1<0) i1=0;
96 if (j1>n) j1=n;
97 s[i]=i1;
98 d[i]=j1;
99 // cout<<i1<<" "<<j1<<’\n’;
100 }
101
102 for (i=1;i<n;i++)
103 for (j=i+1;j<=n;j++)
104 if (d[i]>d[j])
105 {
106 aux=s[i];
107 s[i]=s[j];
108 s[j]=aux;
109 aux=d[i];
110 d[i]=d[j];
111 d[j]=aux;
112 }
113 i=1;
114 m=1;
115 //cout<<s[1]<<" "<<d[1]<<’\n’;
116 for (j=2;j<=n;j++)
117 if (s[j]>d[i])
118 {
119 m++;
120 i=j;
121 // cout<<s[i]<<" "<<d[i]<<’\n’;
CAPITOLUL 22. ONI 2010 267
122 }
123
124 afis();
125 return 0;
126 }
22.2 maraton
Problema 2 - maraton 100 de puncte
Pentru desf ³urarea probei de maraton a po³ta³ilor, organizatorii au plasat pe traseu n2
semafoare, la distanµe egale unul de cel lalt. Primul semafor e plasat pe linia de start, iar ultimul
semafor este plasat pe linia de sosire ³i ambele vor avea aprins culoarea verde din momentul în
care se d startul ³i pân la sfâr³itul cursei.
Pentru ecare semafor întâlnit pe traseu,
cele trei culori ale sale: ro³u, galben ³i verde
se aprind succesiv astfel: întotdeuna dup ro³u
se face galben, dup galben se face verde, iar
dup verde urmeaz ro³u, ³i a³a mai departe.
Culoarea ro³ie a ec rui semafor se schimb în
galben dup 5 secunde, galbenul se schimb în Figura 22.1: maraton
verde dup 3 secunde, iar verdele în ro³u dup
2 secunde.
În momentul în care se d startul ³i se porne³te cronometrul toate cele n semafoare de pe traseu
se aprind. La unele va culoarea ro³ie, la altele galben, iar la altele verde, neind sincronizate la
acest moment.
Fiecare po³ta³ înscris la maraton trebuie s parcurg traseul de la linia de start pân la linia de
sosire ³i s treac pe rând de cele n semafoare, doar pe culoarea verde a ec ruia dintre ele. Dac
un concurent ajunge în dreptul semaforului ³i acesta este verde va trece obligatoriu mai departe.
Dac ajunge în dreptul unui semafor chiar în secunda în care se schimb culoarea acestuia, atunci
concurentul poate trece mai departe doar dac aceast schimbare s-a facut de la galben la verde,
nu ³i de la verde la ro³u sau de la ro³u la galben.
Cerinµe
tiind c po³ta³ul Andrei parcurge distanµa dintre dou semafoare succesive în k secunde, s
se scrie un program care s determine num rul minim de secunde necesar pentru ca el s treac
linia de sosire.
Date de intrare
Din ³ierul maraton.in:
- De pe prima linie se citesc dou numere naturale n ³i k desp rµite printr-un spaµiu. Valoarea
n reprezint num rul de semafoare plasate între cele dou linii, cea de start ³i cea de sosire, iar
num rul k reprezint timpul necesar, exprimat în secunde, pentru parcurgerea distanµei dintre
oricare dou semafoare succesive de pe traseu.
- De pe urm toarea linie se citesc n valori întregi desp rµite prin câte un spaµiu, ce reprezint
culoarea pe care o are ecare semafor în momentul startului. Vom codica cu 2 culoarea ro³ie,
1 culoarea galben ³i cu 0 culoarea verde a semaforului.
Date de ie³ire
Fi³ierul maraton.out va conµine o singur linie pe care se va scrie num rul natural s, care
reprezint num rul minim de secunde necesar pentru ca Andrei s treac de linia de sosire.
Restricµii ³i preciz ri
a 1 & n & 5000 ³i 1&k & 600
a linia de sosire este plasat imediat dup ultimul semafor.
CAPITOLUL 22. ONI 2010 268
Exemple
maraton.in maraton.out Explicaµii
3 2 25 Se d startul ³i dup 2 secunde po³ta³ul ajunge în dreptul
0 0 -1 primului semafor. La acesta tocmai se schimb culoarea din
verde în ro³u ³i ca urmare po³ta³ul nu poate trece. A³teapt
8 secunde, se face verde iar dup alte 2 secunde ajunge în
dreptul celui de-al doilea semafor (au trecut 12 secunde de la
start). Aici mai a³teapt 8 secunde, se face verde ³i poate
trece. Parcurge în 2 secunde distanµa pân în dreptul celui
de-al treilea semafor. Când ajunge în dreptul acestui semafor
(dup 22 secunde de la start) mai a³teapt o secund (1), se
face verde ³i peste 2 secunde trece linia de sosire (22+1+2=25
secunde).
1 # include <fstream>
2
3 using namespace std;
4
5 ifstream f("maraton.in");
6 ofstream g("maraton.out");
7
8 int main()
9 {
10 long n,k,i,t,culoare,mai_sta;
11 long timp=0;
12
13 f>>n>>k;
14
15 for(i=1;i<=n;i++)
16 {
17 f>>culoare;
18
19 timp=timp+k;
20 t=(timp%10);
21
22 switch(culoare)
23 {
24 case -2:
25 if(t==8 || t==9)
CAPITOLUL 22. ONI 2010 269
26 mai_sta=0;
27 else
28 if(t==10)
29 mai_sta=8;
30 else
31 mai_sta=8-t;
32 break;
33 case -1:
34 if (t==4)
35 mai_sta=0;
36 else
37 if (t<=3)
38 mai_sta=3-t;
39 else
40 mai_sta=3+(10-t);
41 break;
42 case 0:
43 if(t==0 || t==1)
44 mai_sta=0;
45 else
46 if(t==2)
47 mai_sta=8;
48 else
49 mai_sta=10-t;
50 break;
51 }
52
53 timp=timp+mai_sta;
54 }
55
56
57 g<<(timp+k);
58 return 0;
59 }
1 #include<fstream>
2
3 using namespace std;
4
5 ifstream f("maraton.in");
6 ofstream g("maraton.out");
7
8 int a[6000],n,k;
9 long s=0;
10
11 void citire();
12
13 void actualizare(int i,int val)
14 {
15 for(int j=i;j<=n;j++)
16 a[j]=(a[j]+val)%10;
17 }
18
19 void blabla()
20 {
21 for (int i=1;i<=n;i++)
22 {
23 s=s+k;
24 actualizare(i,k);
25
26 if(a[i]<8)
27 {
28 int v=8-a[i];
29 actualizare(i,v);
30 s=s+v;
31 }
32 }
33 }
34
35 int main()
36 {
37 citire();
38 blabla();
CAPITOLUL 22. ONI 2010 270
39 s+=k;
40 g<<s;
41 g.close();
42 return 0;
43 }
44
45 void citire()
46 {
47 f>>n>>k;
48 int x;
49
50 for(int i=1;i<=n;i++)
51 {
52 f>>x ;
53 if(x==-2)
54 a[i]=0;
55 else
56 if(x==-1)
57 a[i]=5;
58 else
59 a[i]=8;
60 }
61 }
22.3 roboti
Problema 3 - roboti 100 de puncte
Într-o zon dreptunghiular cu p linii ³i q coloane se a n roboµi. Celula din stânga sus se
a pe linia 1 ³i coloana 1.
Pentru ecare robot se cunoa³te linia ³i coloana pe care se a , precum ³i orientarea lui.
Un robot poate orientat în una din cele patru direcµii: nord, sud, est sau vest, codicate cu
caracterele N, S, E, respectiv V. Fiecare robot execut m comenzi. O comand este codicat
printr-un caracter L, R sau F. La o comand de tip L, robotul se întoarce cu 90 de grade spre
stânga, în sensul invers acelor de ceasornic. La o comand de tip R, robotul se întoarce cu 90 de
grade spre dreapta, în sensul acelor de ceasornic. La o comand de tip F, robotul se deplaseaz
cu o poziµie în sensul în care este orientat robotul.
Roboµii execut simultan prima comand din ³irul lor de comenzi, apoi a doua comand , etc.
Dac la un moment dat, doi sau mai mulµi roboµi ajung în aceea³i poziµie, aceasta va conduce
la dispariµia lor, iar celula din care dispar se consider traversat de toµi cei care au disp rut.
Dac un robot se deplaseaz în afara suprafeµei la execuµia unei comenzi, robotul dispare.
Se consider trecere printr-o celul vizitarea rezultat în urma execut rii unei comenzi de tip
F. Dac un robot trece de mai multe ori printr-o celul , se contorizeaz ecare trecere a sa. Celula
din care pleac ecare robot se consider trecere pentru robotul respectiv.
Cerinµe
Scrieµi un program care s determine:
a) num rul de roboµi r ma³i dup execuµia celor m comenzi,
b) poziµia celulei din zon prin care s-a trecut cel mai des (dac exist mai multe celule, atunci
se va preciza cea cu indicele de linie cel mai mic, iar dac exist mai multe cu acest indice, cea cu
indicele de coloan cel mai mic) ³i num rul de treceri prin aceast celul .
Date de intrare
Fi³ierul roboti.in conµine:
- pe prima linie: p ³i q, valori separate printr-un spaµiu ³i reprezentând num rul de linii ³i de
coloane ale zonei;
- pe a doua linie: valoarea n, reprezentând num rul de roboµi;
- pe urm toarele n linii: câte trei valori separate prin câte un spaµiu, reprezentând linia, coloana
³i orientarea ec rui robot;
- pe urm toarea linie: valoarea m reprezentând num rul de comenzi de executat de c tre
ecare robot;
- pe urm toarele n linii se a câte m caractere reprezentând comenzile pentru ecare robot
(mai întâi cele m comenzi pentru primul robot, apoi cele m comenzi pentru al doilea robot,
³.a.m.d.). între caracterele unei comenzi nu exist niciun spaµiu.
CAPITOLUL 22. ONI 2010 271
Date de ie³ire
Fi³ierul roboti.out va conµine:
- pe prima linie num rul de roboµi r ma³i în nal
- pe linia a doua poziµia celulei (linie ³i coloan ) prin care s-a trecut cel mai des (dac exist
mai multe celule, atunci se va preciza cea cu indicele de linie cel mai mic, iar dac exist mai
multe cu acest indice, cea cu indicele de coloan cel mai mic) ³i num rul de treceri prin aceast
celul , trei valori separate prin câte un spaµiu
Restricµii ³i preciz ri
a 1 & p, q, m & 50
a 2 & n & 50
a Caracterele cu care se codic orient rile pot doar N, S, E, V, iar cele pentru comenzi L,
R sau F (litere mari).
a Iniµial, nu exist doi sau mai mulµi roboµi în aceea³i celul .
a Se acord 50% din punctaj pentru rezolvarea cerinµei a) ³i 50% pentru cerinµa b).
Exemple
roboti.in roboti.out Explicaµii
4 4 0 Dup prima comand , roboµii 1 ³i 2 ar trebui s ajung în aceea³i
3 1 2 2 celul , deci dispar. Al treilea robot conform primei deplas ri va
1 1 E p r si zona, deci dispare. în nal vor 0 roboµi. Doi roboµi au
1 3 V ajuns în celula de pe linia 1 ³i coloana 2, dup care au disp rut.
4 4 S Prin celelalte celule s-a trecut maxim o singur dat .
2
FL
FF
FF
Se execut mai întâi prima comand de c tre toµi roboµii, identicând mai întâi situaµiile în
care ace³tia p r sesc zona (se veric dac dup o deplasare de tip F indicele de linie pentru noua
poziµie nu se a în intervalul 1, p, sau indicele de coloan nu se a în intervalul 1, q .
Se identic apoi situaµiile în care ajung în aceea³i celul mai mulµi roboµi, µinând cont c cei
care fac comenzi de tip L sau R nu p r sesc zona, iar cei cu comenzi F se vor deplasa într-o nou
celul .
Se continu în acela³i mod cu toate comenzile. Se contorizeaz num rul de roboµi disp ruµi,
pentru a se preciza num rul celor r ma³i în nal, conform cerinµei a).
Trecerea printr-o celul se marcheaz într-o nou matrice care va avea în nal num rul de
treceri prin ecare celul . Se determin apoi cel mai mare element din matrice ³i poziµia primului
element din matrice egal cu acesta (dac exist mai multe elemente se va scrie poziµia celui cu
indicele de linie cel mai mic, iar la egalitate, cel cu indicele de coloan cel mai mic)
75 *c_nou = c + 1;
76 break ;
77 case ’V’ :
78 *c_nou = c - 1;
79 break ;
80 case ’S’ :
81 *l_nou = l + 1;
82 break ;
83 case ’N’ :
84 *l_nou = l - 1;
85 break ;
86 }
87 }
88
89 void deplasare()
90 {
91 int i, j, vechil, vechic;
92 short a[MAX][MAX], b[MAX][MAX], p, q;
93
94 for (i = 1; i <= m; i++)
95 {
96 for (p = 1; p <= l; p++)
97 for (q = 1; q <= c; q++)
98 a[p][q] = 0;
99
100 for (j = 1; j <= nr; j++)
101 if ( exista[j] )
102 if ( depl[j][i] == ’L’ || depl[j][i] == ’R’)
103 a[x[j]][y[j]] = 1, b[x[j]][y[j]] = j;
104
105 for (j = 1; j <= nr; j++)
106 if ( exista[j] )
107 {
108 switch ( depl[j][i] )
109 {
110 case ’L’ : miscare_l(ori[j], &ori[j]); break ;
111 case ’R’ : miscare_r(ori[j], &ori[j]); break ;
112 case ’F’ :
113 {
114 miscare_f(x[j], y[j], ori[j], &x[j], &y[j]);
115 if (x[j] == 0 || y[j] == 0 || x[j] > l || y[j] > c)
116 exista[j] = 0;
117 else
118 {
119 tr[x[j]][y[j]]++;
120 if (a[x[j]][y[j]] == 0)
121 a[x[j]][y[j]] = 1, b[x[j]][y[j]] = j;
122 else exista[j] = 0, exista[b[x[j]][y[j]]] = 0;
123 }
124 break;
125 }
126 }
127 }
128 }
129
130 n = 0;
131 for (i = 1; i <= nr; i++)
132 if ( exista[i] ) ++n;
133 }
134
135 void afisare()
136 {
137 int i, j, max, p, q;
138
139 printf("%d\n", n);
140
141 max = tr[1][1];
142 p = q = 1;
143 for (i = 1; i <= l; i++)
144 for (j = 1; j <= c; j++)
145 if (tr[i][j] > max)
146 max = tr[i][j], p = i, q = j;
147
148 printf("%d %d %d", p, q, max);
149 }
150
CAPITOLUL 22. ONI 2010 274
Un pic de matematic !
A.1 ...
...
A.1.2 Exemple
...
276
Anexa B
Un pic de programare!
B.1 ...
...
B.1.2 Exemple
...
277
Glosar
I don't know who the author is., v vector de sume parµiale, 165
vector suma, 16
lee, 9 vectori de direcµii, 263
278
Bibliograe
[1] Aho, A., Hopcroft, J., Ullman, J.D.; Data strutures and algorithms, Addison Wesley, 1983
[2] Andreica M.I.; Elemente de algoritmic - probleme ³i soluµii, Cibernetica MC, 2011
[3] Andonie R., Gârbacea I.; Algoritmi fundamentali, o perspectiv C++, Ed. Libris, 1995
[5] Bell D., Perr M.; Java for Students, Second Edition, Prentice Hall, 1999
[7] Cerchez, E., erban, M.; Informatic - manual pentru clasa a X-a., Ed. Polirom, 2000
[8] Cerchez, E.; Informatic - Culegere de probleme pentru liceu, Ed. Polirom, 2002
[9] Cerchez, E., erban, M.; Programarea în limbajul C/C++ pentru liceu, Ed. Polirom, 2005
[10] Cori, R.; Lévy, J.J.; Algorithmes et Programmation, Polycopié, version 1.6;
http://w3.edu.polytechnique.fr/informatique/
[11] Cormen, T.H., Leiserson C.E., Rivest, R.L.; Introducere în Algoritmi, Ed Agora, 2000
[12] Cormen, T.H., Leiserson C.E., Rivest, R.L.; Pseudo-Code Language, 1994
[13] Cristea, V.; Giumale, C.; Kalisz, E.; Paunoiu, Al.; Limbajul C standard, Ed. Teora, Bucure³ti,
1992
[16] Giumale C., Negreanu L., C linoiu S.; Proiectarea ³i analiza algoritmilor. Algoritmi de sortare,
Ed. All, 1997
[18] Knuth, D.E.; Arta program rii calculatoarelor, vol. 1: Algoritmi fundamentali, Ed. Teora,
1999.
[19] Knuth, D.E.; Arta programarii calculatoarelor, vol. 2: Algoritmi seminumerici, Ed. Teora,
2000.
[20] Knuth, D.E.; Arta programarii calculatoarelor, vol. 3: Sortare ³i c utare, Ed. Teora, 2001.
[21] Knuth, D.E.; The art of computer programming, vol. 4A: Combinatorial algorithms, Part 1,
Addison Wesley, 2011.
[22] Lambert,K. A., Osborne,M.; Java. A Framework for Programming and Problem Solving,
PWS Publishing, 1999
[24] Livovschi, L.; Georgescu H.; Analiza ³i sinteza algoritmilor. Ed. Enciclopedic , Bucure³ti,
1986.
279
BIBLIOGRAFIE 280
[26] Od gescu, I., Smeureanu, I., tef nescu, I.; Programarea avansat a calculatoarelor personale,
Ed. Militar , Bucure³ti 1993
[27] Od gescu, I.; Metode ³i tehnici de programare, Ed. Computer Lobris Agora, Cluj, 1998
[28] Popescu Anastasiu, D.; Puncte de articulaµie ³i punµi în grafuri, Gazeta de Informatic nr.
5/1993
[35] Tomescu, I.; Probleme de combinatoric ³i teoria grafurilor, Editura Didactic ³i Pedagogic ,
Bucure³ti, 1981
[36] Tomescu, I.; Leu, A.; Matematic aplicat în tehnica de calcul, Editura Didactic ³i Pedago-
gic , Bucure³ti, 1982
[37] Tudor, S.; Informatic - prolul real intensiv, varianta C++; Editura L&S, Bucure³ti, 2004
[38] Tudor, S.; Hutanu, V,; Informatic intensiv; Editura L&S, Bucure³ti, 2006
[40] Vi³inescu, R.; Vi³inescu, V.; Programare dinamic - teorie ³i aplicaµii; GInfo nr. 15/4 2005
[41] Vlada, M.; Conceptul de algoritm - abordare modern , GInfo, 13/2,3 2003
[43] Vlada, M.; Gândirea Algoritmic - O Filosoe Modern a Matematicii ³i Informaticii, CNIV-
2003, Editura Universit µii din Bucure³ti, 2003
[44] Weis, M.A.; Data structures and Algorithm Analysis, Ed. The Benjamin/Cummings Pu-
blishing Company. Inc., Redwoods City, California, 1995.
[46] Wirth N.; Algorithms + Data Structures = Programs, Prentice Hall, Inc 1976
[48] *** -
https://github.com/DinuCr/CS/blob/master/Info/stuff%20stuff/Re
zolvari_C09.pdf
[49] *** - https://dokumen.tips/documents/rezolvaric09.html
Emanuela Cerchez, 30, 74, 108, 117, 157, Octavian Dumitra³cu, 203, 216
211
Eugen Nodea, 111 Pintea Adrian Doru, 168
282