Sunteți pe pagina 1din 300

PROBLEME DE INFORMATIC€

date la olimpiade

în

2020
2019 2018 2017 2016 2015
2014 2013 2012 2011 2010

la clasa a 7-a

... draft (ciorn ) ...


*** Nobody is perfect ***

Ph.D. Adrian R bâea

9 decembrie 2020
Dedicaµie

I would like to dedicate this book ...

1
to myself ...
in a time when ...
I will not be able ...
2
to be.

That is because ...

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 !

Limbajul de programare se alege în funcµie de problema pe care o avem de rezolvat. Cu ni³te


ani în urm  alegerea era mai simpl : dac  era o problem  de calcul se alegea Fortran iar dac  era
o problem  de prelucrarea masiv  a datelor atunci se alegea Cobol. Acum alegerea este ceva mai
5 6
dicil ! :-) Vezi, de exemplu, IOI2020 ³i IOI2019 , IOI2015 .

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.

ALGORITMI utili la olimpiadele de informatic  , separat pentru gimnaziu ³i liceu, sper s 


e de folos, a³a cum cred c  sunt [1] - [28], [34] - [47], [57] - [82], ... ³i multe alte c rµi ³i site-uri!.

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 ... !!!

"I'm only responsible for what I say,


14
not for what you understand."

Adrese interesante (rezultatele elevilor români):

https://stats.ioinformatics.org/halloffame/
https://stats.ioinformatics.org/tasks/
http://stats.ioinformatics.org/results/ROU

Adresele acestor cursuri:

http://adrianrabaea.scienceontheweb.net/
https://www.scribd.com/user/243528817/Adrian-Rabaea
https://drive.google.com/drive/folders/1hC5PZuslCdS95sl37SW46H-qy59GRDGZ

Adrese utile (programe ³colare):

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

Bistriµa, Ph.D. Adrian R bâea


9 decembrie 2020

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."

Bistriµa, 9 decembrie 2020

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

Lector universitar - Universitatea Tehnic  din Cluj Napoca - Centrul


Universitar Nord din Baia Mare, Facultatea de “tiinµe, Str. Victoriei,
nr. 76, Baia Mare, România, (pensionat: 01.10.2018)
http://www.stiinte.utcluj.ro/
Discipline predate (1992-2018):
Algoritmi ³i structuri de date, Algoritmi în teoria opµiunilor nanciare, Bazele matematice
ale calculatoarelor, Bazele tehnologiei informaµiei, Birotic , Capitole speciale de inteligenµ 
articial , Capitole speciale de teoria algoritmilor, Calcul paralel, Informatic  economic ,
Instruire asistat  de calculator, Limbaje de programare; Programare orientat  pe obiecte,
Programare procedural , Structuri de date,

Studii doctorale în informatic  economic  - Diplom  de doctor (1997-2002):


Institutµia: Academia de Studii Economice, Bucure³ti;
17
Titlul tezei: Algoritmi paraleli ³i aplicaµii pe ma³ini virtual paralele
18
Conduc tor ³tiinµic: Prof. dr. ing. Gheorghe Dodescu
Teme studiate: utilizarea algoritmilor paraleli în teoria opµiunilor nanciare

Studii de specializare în informatic  - Certicat anul V - 'master' (1978-1979):


Instituµia: Facultatea de matematic  ³i informatic , Bucure³ti;
Titlul tezei: Probleme la limit  pentru procese cu cre³teri independente ³i aplicaµii în teoria
a³tept rii
19
Conduc tor ³tiinµic: Prof. dr. Constantin Tudor

Studii universitare de licenµ  în informatic  - Diplom  de licenµ  (1974-1978):


Instituµia: Facultatea de matematic  ³i informatic , Bucure³ti;
Titlul tezei: Metode de comparaµie multipl  în analiza dispersional 
20
Conduc tor ³tiinµic: Prof. dr. Ion V duva

Locuri de munc : (1979-2018):


- (2018-2009) Universitatea Tehnic  din Cluj-Napoca, Centrul Universitar Nord din Baia-
Mare, Facultatea de “tiinµe, Departamentul de Matematic -Informatic 
- (2009-1992) Universitatea "Ovidius" din Constanµa, Facultatea de Matematic  ³i Informa-
tic , Departamentul de Informatic 
- (1992-1979) Centrul de Informatic  ³i organizare CINOR, Bucure³ti

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

I OJI - Olimpiada judeµean  de informatic  1


1 OJI 2020 2
1.1 foto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.2 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1.3 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.2 wind . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.2.2 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.2.3 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

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

8 OJI 2013 107


8.1 compar - OJI 2013 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
8.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
8.1.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
8.1.3 Codul surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
8.2 unic - OJI 2013 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
8.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
8.2.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
8.2.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

9 OJI 2012 116


9.1 arme - OJI 2012 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
9.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
9.1.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
9.1.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
9.2 triunghi - OJI 2012 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
9.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
9.2.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
9.2.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

10 OJI 2011 128


10.1 grupe - OJI 2011 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
10.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
10.1.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
10.1.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
10.2 litere - OJI 2011 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
10.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
10.2.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
10.2.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132

11 OJI 2010 134


11.1 Cuvinte - OJI 2010 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
11.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
11.1.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
11.1.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
11.2 Zar - OJI 2010 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
11.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
11.2.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
11.2.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

II ONI - Olimpiada naµional  de informatic  140


12 ONI 2020 141
12.1 *** . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
12.1.1 *Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
12.1.2 *Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
12.1.3 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
12.2 *** . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
12.2.1 *Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
12.2.2 *Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
12.2.3 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
12.3 *** . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
12.3.1 *Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
12.3.2 *Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
12.3.3 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

13 ONI 2019 144


13.1 domino . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
13.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
13.1.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
13.1.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
13.2 tuburi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
13.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
13.2.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
13.2.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
13.3 venus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
13.3.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
13.3.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
13.3.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

14 ONI 2018 161


14.1 evip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
14.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
14.1.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
14.1.3 *Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
14.2 nxy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
14.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
14.2.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
14.2.3 *Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
14.3 viitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
14.3.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
14.3.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
14.3.3 *Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
15 ONI 2017 167
15.1 carte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
15.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
15.1.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
15.1.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
15.2 ghinde . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
15.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
15.2.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
15.2.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
15.3 submat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
15.3.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
15.3.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
15.3.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174

16 ONI 2016 176


16.1 birouri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
16.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
16.1.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
16.1.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
16.2 cristale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
16.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
16.2.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
16.2.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
16.3 parchet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
16.3.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
16.3.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
16.3.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192

17 ONI 2015 202


17.1 cript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
17.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
17.1.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
17.1.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
17.2 scadere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
17.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
17.2.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
17.2.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
17.3 tv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
17.3.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
17.3.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
17.3.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217

18 ONI 2014 218


18.1 codat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
18.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
18.1.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
18.1.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
18.2 nod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
18.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
18.2.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
18.2.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
18.3 placa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
18.3.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
18.3.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
18.3.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
19 ONI 2013 244
19.1 secvp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
19.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
19.1.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
19.1.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
19.2 patrate2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
19.2.1 *Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
19.2.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
19.2.3 *Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
19.3 cursa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
19.3.1 *Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
19.3.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
19.3.3 *Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249

20 ONI 2012 250


20.1 bile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
20.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
20.1.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
20.1.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
20.2 proiecte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
20.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
20.2.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
20.2.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
20.3 zigzag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
20.3.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
20.3.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
20.3.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257

21 ONI 2011 259


21.1 joc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
21.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
21.1.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
21.1.3 *Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
21.2 mesaj . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
21.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
21.2.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
21.2.3 *Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
21.3 zar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
21.3.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
21.3.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
21.3.3 *Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263

22 ONI 2010 264


22.1 char . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
22.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
22.1.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
22.1.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
22.2 maraton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
22.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
22.2.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
22.2.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
22.3 roboti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270
22.3.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
22.3.2 *Rezolvare detaliat  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
22.3.3 Cod surs  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271

Anexa A Un pic de matematic ! 276


A.1 ... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
A.1.1 Prezentare general  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
A.1.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
Anexa B Un pic de programare! 277
B.1 ... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
B.1.1 Prezentare general  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
B.1.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277

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

9.1 armeIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117


9.2 triunghi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120

11.1 triunghi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

13.1 domino . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144


13.2 domino . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
13.3 joc1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
13.4 tuburi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

16.1 birouri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176

19.1 cursa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248

20.1 zigzag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256

21.1 joc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259


21.2 mesaj . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261

22.1 maraton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267

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

OJI - Olimpiada judeµean  de


informatic 

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 ;

b) un fulger poate avea un singur p trat alb pe un rând.

Î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.

Pentru a putea  analizat  de c tre programatori,


fotograa este codicat  cu ajutorul unui tablou bidi-
mensional cu N linii si M coloane, ale c rui elemente
sunt 0 ³i 1. Valoarea 0 este codicarea p tratului negru,
iar valoarea 1 este codicarea p tratului alb.

Având codicarea, programatorii trebuie s  g seasc 


num rul maxim P de p trate negre dispuse al turat pe
acela³i rând, num rul de fulgere F precum ³i în lµimea
maxim  H a unui fulger din fotograe. De exemplu, fotograa al turat  este codicat  de tabloul
T al turat fotograei .

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:

1) a³eaz  num rul maxim P de p trate negre dispuse al turat pe un rând în fotograe;

2) a³eaz  num rul F de fulgere ³i în lµimea maxim  H a unui fulger din fotograe.

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

Fi³ierul de ie³ire foto.out va conµine, pe o singur  linie:


a dac  C 1, num rul P, reprezentând r spunsul la cerinµa 1;

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:

foto.in foto.out Explicaµii


1 3 Se rezolv  cerinµa 1.
6 7 N 6, M 7
0 1 0 0 1 0 0 Sunt maximum P 3 p trate negre al turate
1 0 0 0 1 0 0 pe rândurile 2, 3 ³i 4 (vezi fotograa din enunµ)
0 0 1 0 0 0 1
0 1 0 0 0 1 0
0 1 0 0 1 0 0
0 0 1 0 1 0 1
5 4 Se rezolv  cerinµa 2.
N 6, M 7
Sunt F 5 fulgere iar în lµimea maxim  a
unui fulger este H 4 (vezi fotograa din
enunµ)

Timp maxim de executare/test: 0.2 secunde


Memorie: total 16 MB din care pentru stiv  16 MB
Dimensiune maxim  a sursei: 5 KB

1.1.1 Indicaµii de rezolvare


prof. Carmen Minc , Colegiul Naµional de Informatic  Tudor Vianu Bucure³ti

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

b) Cât timp T[I][J]=1 proced m astfel:

b1) Modic m în matrice T[I][J]=0. Contorizam p tratul alb (h=h+1).

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)

Altfel, (adic  dac  T[I+1][J-1]=0, T[I+1][J]=0 ³i T[I+1][J+1]=0) atunci au fost


g site toate p tratele albe care formeaz  fulgerul. Actualiz m H=max(H,h) apoi
se va c uta urm toarea valoare de 1 în matrice, revenind la pasul a) pentru noile
valori lin si col cu proprietatea c  T[lin][col]=1. Mergi la pas a)

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

La încheierea parcurgerii matricei T, aceasta va avea toate valorile egale cu 0.


Se vor a³a valorile nale ale variabilelor F ³i H.
II. Solutie complexitate O N ˜ M
Se parcurge matricea.
Pentru ecare element T[I][J]=1 proced m astfel:

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;

a se actualizeaz  variabila ce memoreaz  lungimea maxima a fulgerelor H=max(H, T[I][J]);

La încheierea parcurgerii matricei T, se vor a³a valorile nale ale variabilelor F ³i H.

1.1.2 Cod surs 

Listing 1.1.1: foto_1_c.c

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 }

Listing 1.1.2: foto_2_c.c

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 }

Listing 1.1.3: foto_1_cpp.cpp

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 }

Listing 1.1.4: foto_2_cpp.cpp

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 }

Listing 1.1.5: foto_AB.cpp

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 }

Listing 1.1.6: foto_AF.cpp


CAPITOLUL 1. OJI 2020 9

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 }

Listing 1.1.7: foto_cm_rec.cpp

1 #include <fstream>
2 #include <iostream>
3
CAPITOLUL 1. OJI 2020 10

4 using namespace std;


5
6 ifstream f("foto.in");
7 ofstream g("foto.out");
8
9 int a[102][102],h, N, M;
10
11 void caut(int i, int j)
12 {
13 a[i][j]=0;
14 h++;
15 if(a[i+1][j-1])caut(i+1,j-1);
16 else if(a[i+1][j])caut(i+1,j);
17 else if(a[i+1][j+1])caut(i+1,j+1);
18 }
19
20 int main()
21 {
22 int C;//,N,M;
23 f>>C>>N>>M;
24
25 if(C==1)
26 {
27 int x,P=0,i,j,p=0;
28 for(i=1; i<=N; i++)
29 {
30 p=0;
31 for(j=1; j<=M; j++)
32 {
33 f>>x;
34 if(x==0)p++;
35 else
36 {
37 P=max(p,P);
38 p=0;
39 }
40 }
41 P=max(P,p);
42 }
43 g<<P<<endl;
44 }
45 else
46 {
47 int H=0,F=0,i,j,r,c;
48 for(i=1; i<=N; i++)
49 for(j=1; j<=M; j++)
50 f>>a[i][j];
51
52 for(r=1; r<=N; r++)
53 for(c=1; c<=M; c++)
54 if(a[r][c]==1)
55 {
56 F++;
57 h=0;
58 caut(r,c);
59 H=max(h,H);
60 }
61
62 g<<F<< " "<<H;
63 }
64 return 0;
65 }

Listing 1.1.8: fotoCS.cpp

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 }

Listing 1.1.9: fotoFB.cpp

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 }

Listing 1.1.10: fotoKB.cpp

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 }

Listing 1.1.11: fotoMM.cpp

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.1.3 *Rezolvare detaliat 

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 ;

a ecare dintre cele N centrale eoliene trebuie s  e atribuit  unui ora³;

a factorul de dezechilibru, notat cu P k , este valoarea maxim  a diferenµei dintre energiile


repartizate oric ror dou  ora³e diferite, dintre cele k.

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;

a Se vor construi minimum 2 ora³e;

a Pentru rezolvarea cerinµei 1 se acord  20 de puncte, pentru rezolvarea cerinµei 2 se acord 


70 de puncte (35 de puncte pentru X ³i 35 de puncte pentru E ).

Exemple:

wind.in wind.out Explicaµii


1 5 Cerinµa este 1.
12 Centralele eoliene se pot grupa câte 1, câte 2, câte 3,
2 4 -5 12 3 5 -6 4 5 7 -8 2 câte 4 sau câte 6.
2 3 1 Cerinµa este 2.
12 Posibilit µile de grupare:
2 4 -5 12 3 5 -6 4 5 7 -8 2 câte 1 central /ora³ (sumele sunt 2, 4,-5, ..,2;
P(12)=20=12-(-8));
câte 2 centrale/ora³ (sumele sunt: 6, 7, 8, -2, 12, -6;
P(6)=18=12-(-6));
câte 3 centrale/ora³ (sumele sunt:1, 20, 3, 1;
P(4)=19=20-1);
câte 4 centrale/ora³ (sumele sunt: 13, 6, 6;
P(3)=7=13-6);
câte 6 centrale/ora³ (sumele sunt: 21 si 4;
P(2)=17=21-4).
Astfel, factorul de dezechilibru minim este P(3)=7,
deci X 3.
Pentru aceast  grupare a centralelor, ora³ul cu can-
titatea maxim  de energie (13) corespunde primului
grup, care începe cu centrala etichetat  cu E 1.

Timp maxim de executare/test: 0.3 secunde


Memorie: total 16 MB din care pentru stiv  16 MB
Dimensiune maxim  a sursei: 10 KB

1.2.1 Indicaµii de rezolvare

prof. Flavius Boian, Colegiul Naµional Spiru Haret - Târgu-Jiu

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.2.2 Cod surs 


CAPITOLUL 1. OJI 2020 17

Listing 1.2.1: wind.c

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

75 else if(dif==minimm && x<divx)


76 {
77 divx=x;
78 pozmax=poz;
79 }
80 }
81
82 n=n/divx;
83 fprintf(g,"%lli %lli\n",n,pozmax);
84 }
85
86 return 0;
87 }

Listing 1.2.2: wind.cpp

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 }

Listing 1.2.3: windCM.cpp

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 }

Listing 1.2.4: windCS.cpp

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 }

1.2.3 *Rezolvare detaliat 


Capitolul 2

OJI 2019

2.1 poarta - OJI 2019


Problema 1 - poarta 90 de puncte
Sindbad a descoperit un recipient care conµine o poµiune magic  ³i o inscripµie care descrie
cum se poate deschide poarta unui templu. Urmând instrucµiunile din inscripµie, Sindbad a ajuns
la un tunel acoperit cu dale p trate, aliniate astfel încât formeaz  linii ³i coloane. Tunelul are mai
multe linii, iar pe ecare linie sunt câte N dale. Dalele din tunel sunt numerotate începând cu 1,
astfel încât, parcurgându-le linie cu linie ³i ecare linie de la stânga la dreapta, se obµine un ³ir
strict cresc tor de numere naturale consecutive.
Sindbad se a  la intrare, înaintea primei linii. Pentru a deschide poarta templului, el trebuie
s  ajung  pe dala numerotat  cu P, c lcând pe un num r minim de dale. Dac  exist  mai multe
astfel de soluµii, o va alege pe cea pentru care consumul total de pic turi de poµiune magic  este
minim.
Pe parcursul deplas rii el trebuie s  respecte urm toarele reguli:
a de la intrare, poate s ri pe orice dal  aat  pe prima line, f r  a consuma poµiune magic ;
a de pe o dal  numerotat  cu X , Sindbad poate s ri e pe dala numerotat  cu X 1, consumând
o pic tur  de poµiune magic , e pe dala numerotat  cu 2 ˜ X , consumând dou  pic turi de poµiune
magic .

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

Timp maxim de executare/test: 0.1 secunde


Memorie: total 8 MB din care pentru stiv  4 MB
Dimensiune maxim  a sursei: 10 KB
Sursa: poarta.cpp, poarta.c sau poarta.pas va  salvat  în folderul care are drept nume ID-ul
t u.

2.1.1 Indicaµii de rezolvare

prof. Filonela Balasa - Colegiul National ’’Grigore Moisil’’, Bucuresti

Pentru rezolvarea problemei se foloseste metoda drumului inapoi. Se pleaca de pe da


numerotata cu P. Pentru a obtine numarul minim de pasi solicitat de enunt, in cazul
care numarul P este par valoarea lui se imparte la 2, altfel valoarea lui P scade

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

Pentru rezolvarea cerintei 2, numarul minim de picaturi se determina astfel: pent


fiecare impartire la 2 valoarea lui T creste cu 2 (doua picaturi de potiune magica)
iar pentru fiecare scadere cu 1, valoarea lui T creste cu 1 (o picatura de potiune

2.1.2 *Rezolvare detaliat 

2.1.3 Cod surs 

Listing 2.1.1: poarta1_100.cpp

1 //Rodica Balasa - 100


2 #include <fstream>
3 using namespace std;
4 int main()
5 {
6 int i,k=1,ck,nv,j,v[10001],nk=0,gata=0,cer,pas=0,n;
7 long long T=0;
8 char c;
9 ifstream f("poarta.in");
10 ofstream g("poarta.out");
CAPITOLUL 2. OJI 2019 24

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 }

Listing 2.1.2: poarta2_100.cpp

1 //Ungureanu Florentina 100


2 #include <fstream>
3 #include <cstring>
4 #include <cstdlib>
5
6 using namespace std;
7
8 ifstream in("poarta.in");
9 ofstream out("poarta.out");
10
11 const int MAXN = 1005;
12 char p[MAXN],N[20];
13 int n,c,l;
14
15 void Divide(char p[], int &n)
16 { int i;
17 unsigned R=0;
18 for (i=n;i>=0;--i)
19 { p[i]=’0’+(R=(10*R+p[i]-’0’))/2;
CAPITOLUL 2. OJI 2019 25

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 }

Listing 2.1.3: poarta3_100.cpp

1 //Em. Cerchez 100


2 #include <fstream>
3 #define LGMAX 10002
4
5 using namespace std;
6
7 ifstream fin("poarta.in");
8 ofstream fout("poarta.out");
9
10 int N, cerinta;
11 int P[LGMAX];
12 int lgp;
13 int T, nrmin=1, X;
14
15 void imparte2(int P[LGMAX], int& lgp);
16 int compara(int P[LGMAX], int lgp, int nr);
17 int convert(int P[LGMAX], int lgp);
18
19 int main()
20 {char c;
21 int st, dr, aux;
22 fin>>cerinta>>N;
23 while (fin>>c)
24 P[lgp++]=c-’0’;
25 for (st=0, dr=lgp-1; st<dr; st++, dr--)
26 {aux=P[st]; P[st]=P[dr]; P[dr]=aux;}
27 while (1)
28 {
29 if (compara(P, lgp, N)<=0) {X=convert(P, lgp); break;}
30 if (compara(P, lgp, N+1)==0) {X=N; T++; nrmin++; break;}
31
32 if (P[0]%2)
33 {
34 P[0]--; nrmin++; T++;
35 }
36 else
37 {
38 imparte2(P, lgp);
39 nrmin++; T+=2;
40 }
41 }
42 if (cerinta==1)
43 fout<<nrmin<<’\n’;
44 else
45 fout<<T<<’\n’;
46 return 0;
47 }
48
49 void imparte2(int P[LGMAX], int& lgp)
50 {int i, v=0;
51 for (i=lgp-1; i>=0; i--)
52 {
53 v=v*10+P[i];
54 P[i]=v/2;
55 v=v%2;
56 }
57 if (P[lgp-1]==0) lgp--;
58 }
59
60 int compara(int P[LGMAX], int lgp, int nr)
61 //returneaza 1 daca P>nr
62 //returneaza -1 daca p<nr
63 //returneaza 0 daca P==nr
64 {int Q[20], lgq=0, i;
65 do {Q[lgq++]=nr%10; nr/=10;} while (nr);
66 if (lgp>lgq) return 1;
67 if (lgp<lgq) return -1;
68 for (i=lgp-1; i>=0 && P[i]==Q[i]; i--);
69 if (i<0) return 0;
CAPITOLUL 2. OJI 2019 27

70 if (P[i]<Q[i]) return -1;


71 return 1;
72 }
73
74 int convert(int P[LGMAX], int lgp)
75 {int rez=0, i;
76 for (i=lgp-1; i>=0; i--) rez=rez*10+P[i];
77 return rez;
78 }

Listing 2.1.4: poarta4_100.cpp

1 //Maria Nita - 100


2 #include <fstream>
3 #define MaxC 10005
4
5 using namespace std;
6
7 ifstream cin("poarta.in");
8 ofstream cout("poarta.out");
9
10 int nr[MaxC], k, n, nc, start;
11 int pr;
12 int pasi = 1, potiune;
13
14 void read()
15 {
16 char cif;
17 cin >> pr >> n;
18 while(cin >> cif)
19 nr[++k] = cif -’0’;
20 int aux = n;
21 while(aux >0)
22 {
23 nc ++;
24 aux /= 10;
25 }
26 }
27
28 void drum()
29 {
30 int c[MaxC] = {0}, kc, rest = 0, i, val;
31
32 while(k > nc)
33 {
34 kc = 0;
35 pasi ++;
36
37 if(nr[k]%2==0)
38 {
39 potiune += 2;
40 if(nr[1] < 2)
41 {
42 kc = 1;
43 c[kc] = (nr[1]*10 + nr[2])/2;
44 rest = (nr[1]*10 + nr[2])%2;
45 i = 3;
46 }
47 else
48 {
49 i = 1;
50 rest = 0;
51 }
52
53 for(; i<=k; i++)
54 {
55 rest = rest *10 + nr[i];
56 c[++kc] = rest/2;
57 rest = rest %2;
58 }
59
60 for(i=1; i<=kc; i++)
61 nr[i] = c[i];
62 k = kc;
63 }
CAPITOLUL 2. OJI 2019 28

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 }

2.2 valutar - OJI 2019


Problema 2 - valutar 90 de
puncte
Valutar este un joc care poate  jucat de oricâµi juc tori. La începutul jocului, ecare juc tor
prime³te L lei ³i E euro, precum ³i un jeton numerotat cu num rul juc torului. Mai exact, dac 
exist  M juc tori, vor  M jetoane, numerotate de la 1 la M.
Tabla de joc este harta unui ora³ pe care este ilustrat un traseu circular ce conµine N case de
schimb valutar, numerotate în ordinea de pe traseu de la 1 la N. N
Fiind circular, dup  casa
urmeaz  casa 1. Pentru ecare cas  de schimb valutar se cunosc dou  valori C
V (C reprezint ³i
câµi lei pl te³te un juc tor dac  vrea s  cumpere 1 euro de la casa respectiv , iar V reprezint  câµi
lei prime³te juc torul dac  vrea s  vând  1 euro). Fiecare cas  are o anumit  culoare în funcµie
de care juc torul ajuns în punctul respectiv trebuie s  efectueze o anumit  acµiune astfel:

Exemple
CAPITOLUL 2. OJI 2019 29

valutar.in valutar.out Explicaµii


Alb A Juc torul nu face nimic la aceast  mutare.
Ro³u R Juc torul prime³te un cartona³ denumit pas. Un juc tor care
are un cartona³ pas va folosi ulterior cartona³ul (o singur 
dat , dup  care cartona³ul va  scos din joc) ³i astfel evit  s 
execute o acµiune pe care nu poate s  o execute, pentru a nu 
eliminat din joc.
Galben G Juc torul trebuie s  cumpere i euro (unde i este num rul casei
de schimb valutar la care se a ). Dac  nu are sucienµi lei
pentru a face acest lucru ³i nu deµine un cartona³ pas, juc torul
este eliminat din joc. Dac  are un cartona³ pas, juc torul îl
va folosi ³i nu va executa acµiunea, f r  a  eliminat din joc.
Verde V Juc torul trebuie s  vând  i euro (unde i este num rul casei
de schimb valutar la care se a ). Dac  nu are sucienµi euro
pentru a face acest lucru ³i nu deµine un cartona³ pas, juc torul
este eliminat din joc. Dac  are un cartona³ pas, juc torul îl
va folosi ³i nu va executa acµiunea, f r  a  eliminat.

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:

Mu- Ju- Nu- De Unde Ac- Lei Euro Obs.


ta- ca- mar unde ajunge ti-
re tor pleaca une
1 1 4 1 5 R 2 3 A primit un cartona³ pas.
2 2 5 1 1 A 2 3 Nu face nimic.
3 3 3 1 4 V 2 3 Trebuie s  vând  4 euro, dar nu are
decât 3, nu are cartona³ pas, deci
este scos din joc.
4 1 2 5 2 G 2 3 Trebuie s  cumpere 2 euro, care
cost  2˜5 10 lei, el nu are des-
tui bani, dar are un cartona³ pas
pe care îl folose³te, deci r mâne în
joc.
5 2 4 1 5 R 2 3 A primit un cartona³ pas.
6 1 5 2 2 G 2 3 Trebuie s  cumpere 2 euro, care
cost  2˜5 10 lei, el nu are destui
bani, nu mai are niciuun cartona³,
deci este eliminat din joc.
7 2 3 5 3 G 2 3 Trebuie s  cumpere 3 euro care ar
costa 6˜3 18 lei, nu are bani dar
are un cartona³ pas pe care îl folo-
se³te ³i nu este eliminat din joc.
8 2 2 3 5 R 2 3 Prime³te un cartona³ pas.

Timp maxim de executare/test: 0.1 secunde


Memorie: total 8 MB din care pentru stiv  4 MB
Dimensiune maxim  a sursei: 10 KB
Sursa: valutar.cpp, valutar.c sau valutar.pas va  salvat  în folderul care are drept nume ID-ul
t u.

2.2.1 Indicaµii de rezolvare

prof. Emanuela Cerchez - Colegiul National ’’Emil Racovita’’ Iasi

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

-unde - casa de schimb valutar la care se afla jucatorul


-out - va avea valoarea 1 daca jucatorul a fost eliminat din joc si 0 altfel.
Jucatorii vor fi retinuti intr-un vector J cu elemente de tip jucator.
Initial toti jucatorii au campul sl=L, se=E, pas=0, unde=1 si out=0.
Rezolvarea problemei presupune simularea jocului.
Se efectueaza cele X mutari, una cate una, si la fiecare mutare:
-se genereaza urmatorul numar afisat de zar (utilizand formula din enunt);
-se determina jucatorul aflat la mutare (avand grija sa sarim peste jucatorii
care au fost eliminati din joc);
-se determina noua pozitie a jucatorului aflat la mutare;
-in functie de culoarea casei din noua pozitie se efectueaza actiunea asociata.
La final se contorizeaza numarul jucatorilor pentru care out este 0 (pentru cerinta
sau se determina suma maxima in euro si jucatorul care are aceasta suma (pentru cer

2.2.2 *Rezolvare detaliat 

2.2.3 Cod surs 

Listing 2.2.1: valutar_cpp_100.cpp

1 //Em. Cerchez 100


2 #include <fstream>
3 #define MMAX 102
4 #define NMAX 10002
5
6 using namespace std;
7
8 ifstream fin("valutar.in");
9 ofstream fout("valutar.out");
10
11 struct casa {char cod; int c, v;};
12
13 struct jucator {int sl, se, pas, unde; bool out;};
14
15 jucator J[MMAX];
16 casa C[NMAX];
17
18 int n, m, a, b, nr, X, cerinta, nrout;
19
20 int main()
21 {int i, L, E, cine=0, sum=-1, jmax;
22 char culoare;
23 fin>>cerinta>>a>>b>>nr>>n>>m>>L>>E>>X;
24
25 for (i=1; i<=n; i++)
26 fin>>C[i].cod>>C[i].c>>C[i].v;
27
28 for (i=1; i<=m; i++)
29 {J[i].unde=1; J[i].sl=L; J[i].se=E;}
30
31 for (i=1; i<=X; i++)
32 {
33 if (nrout==m) break;
34
35 do {cine++; if (cine>m) cine=1;} while (J[cine].out);
36
37 nr=(a*nr+b)%n+1;
38 J[cine].unde+=nr; if (J[cine].unde>n) J[cine].unde-=n;
39 culoare=C[J[cine].unde].cod;
40
41 if (culoare==’A’) { continue;}
42 else
43 if (culoare==’R’) J[cine].pas++;
44 else
45 if (culoare==’G’) //cumpar euro
46 {
CAPITOLUL 2. OJI 2019 32

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 }

Listing 2.2.2: valutar1_100.cpp

1 //Ungureanu Florentina 100


2 #include <fstream>
3
4 using namespace std;
5
6 ifstream in("valutar.in");
7 ofstream out("valutar.out");
8
9 const int MAXN = 10005;
10 const int MAXM = 105;
11
12 int a,b,p,nr0,n,m,x;
13 long long l,e;
14
15 struct casa
16 {
17 char cod;
18 unsigned long long c,v;
19 } c[MAXN];
20
21 struct jucator
22 {
23 bool stare;
24 int cc,pas;
25 unsigned long long l,e;
26 } J[MAXN];
27
28 void citire()
29 {
30 in>>p;
31 in>>a>>b>>nr0;
32 in>>n>>m>>l>>e>>x;
33 for (int i=1; i<=n; ++i)
34 in>>c[i].cod>>c[i].c>>c[i].v;
35 for (int i=1; i<=m; ++i)
36 {
37 J[i].cc=1;
38 J[i].l=l;
CAPITOLUL 2. OJI 2019 33

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 }

Listing 2.2.3: valutar2_100.cpp

1 //Nita Maria - 100


2 #include <fstream>
CAPITOLUL 2. OJI 2019 34

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

3.1 puzzle - OJI 2018


Problema 1 - puzzle 100 de puncte
Mihai a primit de ziua lui un joc de puzzle. Jocul are N piese confecµionate prin lipirea unor
buc µi de dimensiune 1x1 (ilustrate în gurile de mai jos prin X ); aceste buc µi le vom numi în
continuare, pe scurt, X -uri. Pentru confecµionarea unei piese se respect  urm toarele reguli:
1. X-urile sunt a³ezate unul peste altul, formând coloane ce pot avea în lµimi diferite, apoi
coloanele se aliniaz  în partea de jos ³i se lipesc între ele, una dup  cealalt , de la stânga spre
dreapta;
2. pe o coloan  sunt cel mult 9 X -uri;
3. toate piesele au acela³i num r de coloane.
Exemple:

Figura 3.1: Puzzle

Î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.

Timp maxim de executare/test: 0.5 secunde


Memorie: total /bf 32 MB din care pentru stiv  32 MB
Dimensiune maxim  a sursei: 10 KB

3.1.1 Indicaµii de rezolvare

Autor, prof. Marius Nicoli - Colegiul National ’’Fratii Buzesti’’ - Craiova

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).

Structurile de date utilizate: vectori

Tipul problemei: prelucrarea cifrelor unui numar, vector de frecvente

Gradul de dificultate: 3
CAPITOLUL 3. OJI 2018 38

3.1.2 *Rezolvare detaliat 

3.1.3 Cod surs 

Listing 3.1.1: p2.cpp

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 }

Listing 3.1.2: p4.cpp

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

3.2 tbile - OJI 2018


Problema 2 - tbile 100 de puncte
Roboµelul Nino a primit cadou un dispozitiv care inscripµio-
neaz  bile. Dispozitivul poate  înc rcat cu n bile, ce vor  in-
scripµionate în ordine, cu numerele 1, 2, ..., n.
Nino trebuie s  împart  bilele inscripµionate în dou  ³iruri, X
³i Y, astfel:
- La primul pas Nino va pune în primul ³ir bila cu num rul 1
(X1 1), iar în al doilea ³ir bila cu num rul 2 (Y1 2).
Figura 3.2: tbile
- La al doilea pas Nino va pune în primul ³ir bila cu num rul
3 X2 3), iar în al doilea ³ir bila cu num rul 4 (Y24).
- La ecare pas i ' 3 Nino va pune în ³irul X Xi Xi1  Yi1 , iar în ³irul Y ,
bila în ordine
cresc toare, bilele numerotate cu Xi1  1, Xi1  2, ..., Xi  1, cu excepµia bilei 4 care a fost pus 
deja.
Dac  la un pas k , Xk % n, bilele r mase vor  inscripµionate cu valorile Xk1  1, Xk1  2, ..., n
³i vor  puse în ³irul Y.
Pentru c  bilele se rostogolesc, Nino împacheteaz  în tuburi verticale de culoare galben , bilele
din primul ³ir, iar în tuburi verticale de culoare ro³ie, bilele din al doilea ³ir. În ecare tub încap
cel mult m bile, dispuse pe o singur  coloan . Tuburile sunt a³ezate vertical, întâi cele galbene,
în ordinea umplerii, apoi cele ro³ii în ordinea umplerii lor. Bilele de la baza ec rui tub formeaz 
nivelul 1, cele situate imediat deasupra lor formeaz  nivelul 2 etc., nivelul maxim putând  m.

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

Timp maxim de executare/test: 0.2 secunde


Memorie: total 8 MB din care pentru stiv  8 MB
Dimensiune maxim  a sursei: 10 KB

3.2.1 Indicaµii de rezolvare

Structurile de date utilizate: vectori.

Problema de generare, calcul matematic.

Gradul de dificultate: 4

Se genereaza intr-un vector termenii sirului X <= n. Fie k numarul acestora.


Se determina numarul br de bile din tuburile de culoare rosie ca fiind n - k.

Pentru cerinta 1 se afiseaza [br/m] (partea intreaga superioara!) si br.

Pentru rezolvarea cerintei doi o abordare posibila ar fi:


Se aduna la suma termenii:

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.

3.2.2 *Rezolvare detaliat 

3.2.3 Cod surs 

Listing 3.2.1: t1.cpp

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 }

Listing 3.2.2: t2.cpp

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

4.1 Cursuri - OJI 2017


Problema 1 - Cursuri 90 de
puncte
Într-o tab r  de var  se programeaz  susµinerea unor cursuri în K s li de clas . Sunt N
profesori care ³i-au exprimat dorinµa de a participa, ecare dintre ei specicând intervalul de timp
ai , bi  în care î³i poate susµine cursul. Programarea pe s li a profesorilor trebuie s  µin  cont de
faptul c  într-o clas , la un moment dat, nu poate preda decât un singur profesor.

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;

Timp maxim de executare/test: 0.2 secunde


Memorie: total 64 MB din care pentru stiv  32 MB
Dimensiune maxim  a sursei: 15 KB

4.1.1 Indicaµii de rezolvare

prof. Daniela Lica, Centrul Judetean de Excelenta Prahova

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*

A doua cerinta se poate rezolva astfel:


Metoda 1) Sortam crescator dupa momentul de intrare, ocupam cele K sali cu primele
(cele care debuteaza cel mai devreme) apoi traversam cursurile ramase, din K in K,
maxima comuna fiind obtinuta ca diferenta minima intre momentele de inceput a cursu
A[i] si A[i-K], oricare K < i <= N.
Metoda 2) Cautam binar durata maxima a cursurilor, astfel incat toate cele N cursur
se poata desfasura. Complexitatea algoritmului fiind O(N*N *log Durata_max).
------------------------------------ ??? ’’log’’ la clasa a 7-a ??? ---------------

4.1.2 *Rezolvare detaliat 

4.1.3 Cod surs 

Listing 4.1.1: cursuri_Dan_100p.cpp

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 }

Listing 4.1.2: cursuri_NlogN.cpp

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

30 for(int j=1; j<=K; j++)


31 if (A[i].first>=Sala[j] && Min> A[i].first - Sala[j])
32 {
33 Min = A[i].first - Sala[j];
34 poz = j;
35 }
36
37 if(Min!= inf){ nr++; Sala[poz]=A[i].second;}
38 }
39
40 return nr;
41 }
42
43 int solve_2(curs A[Nmax])
44 {
45 curs B[Nmax]; int i, tmax=0, ans;
46
47 sort (A + 1, A + N + 1, cmpf);
48
49 for(i=1; i<=N; ++i)
50 tmax = max(tmax, A[i].second - A[i].first);
51
52 ans = tmax;
53 for(i=K+1; i<=N; ++i)
54 ans = min(ans, A[i].first - A[i-K].first);
55
56 return ans;
57 }
58
59 int main()
60 {
61 freopen("cursuri.in", "r", stdin);
62 freopen("cursuri.out", "w", stdout);
63
64 scanf("%d\n%d %d\n", &T, &N, &K);
65
66 for(int i=1; i<=N; i++)
67 scanf("%d %d\n", &A[i].first, &A[i].second);
68
69 if (T==1)
70 printf("%d\n", solve_1(A));
71 else
72 printf("%d\n", solve_2(A));
73
74 return 0;
75 }

Listing 4.1.3: cursuri_NxN.cpp

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 }

Listing 4.1.4: cursuri_raluca_100p.cpp

1 //Raluca Costineanu
2 #include <fstream>
3
CAPITOLUL 4. OJI 2017 50

4 using namespace std;


5
6 ifstream f("cursuri.in");
7 ofstream g("cursuri.out");
8
9 int cerinta, n, k, dmax;
10
11 struct curs
12 {
13 int oi,of;
14 bool p;
15 }a[1010];
16
17 void sort()
18 {
19 int i, ok, poz, nn=n;
20 curs x;
21 do
22 {
23 ok=1;
24 for(i=1;i<nn; i++)
25 if(a[i].of>a[i+1].of)
26 x=a[i], a[i]=a[i+1], a[i+1]=x, poz=i, ok=0;
27 nn=poz;
28 } while(!ok);
29 }
30
31 int cerinta1()
32 {
33 int cate=0, i, j;
34 curs sal[1010];
35
36 for(i=0;i<=k;i++)
37 sal[i].oi=sal[i].of=0;
38
39 for(i=1;i<=n;i++)
40 {
41 int p=0;
42 for(j=1;j<=k;j++)
43 if(a[i].oi>=sal[j].of && a[i].oi-sal[j].of<=a[i].oi-sal[p].of)
44 p=j;
45
46 if(p)
47 sal[p]=a[i], cate++;
48 }
49
50 return cate;
51 }
52 bool verif(int x)
53 {
54 int i;
55
56 for(i=1;i<=n;i++)
57 a[i].of=a[i].oi+x, a[i].p=false;
58
59 sort();
60
61 if(cerinta1()==n)
62 return true;
63
64 return false;
65 }
66
67 int cerinta2()
68 {
69 int i, gasit=1;
70
71 for(i=1;i<=n;i++)
72 if(a[i].of-a[i].oi>dmax)
73 dmax=a[i].of-a[i].oi;
74
75 int s=1, d=dmax, m;
76
77 while(s<=d)
78 {
79 m=(s+d)/2;
CAPITOLUL 4. OJI 2017 51

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 }

Listing 4.1.5: cursuri_rm.cpp

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

123 v[i].b = v[i].a + mij;


124 if(nr_suprapuneri(v, n, 100000 + 10) <= k)
125 rez=mij, st=mij+1;
126 else
127 dr=mij-1;
128 }
129
130 g<<rez<<endl;
131 }
132
133 return 0;
134 }

4.2 joc - OJI 2017


Problema 2 - joc 90 de puncte
Inspiraµi de clasicul joc Tic-Tac-Toe (X ³i 0), Teodora ³i ³tefan î³i propun
s  joace ceva asem n tor, ad ugând jocului clasic câteva reguli noi:
- tabla de joc este un p trat de latur  N, care este împ rµit în N ˜ N
celule, a³ezate pe N linii ³i N coloane; celulele p tratului sunt numerotate
2
de la 1 la N parcurgând liniile de sus în jos, ³i coloanele de la stânga la
dreapta;
- Teodora va marca celulele cu X (litera X ), iar “tefan cu 0 (cifra 0);
Figura 4.1: joc1
- în cadrul unei runde, copiii marcheaz  alternativ câte o celul  din p trat,
nemarcat  anterior;
2
- o rund  a jocului este descris  printr-un ³ir format din exact N numere
naturale reprezentând celulele p tratului, în ordinea în care au fost marcate
succesiv de cei doi copii;
- jocul are K runde; prima este început  de Teodora, a doua de “tefan,
a treia Teodora, a patra “tefan ³i a³a mai departe;
- o rund  este câ³tigat  de juc torul care reu³e³te primul s  marcheze
complet o linie, o coloan , diagonala principal  sau una din cele dou  se-
Figura 4.2: joc2
midiagonale paralele ³i al turate cu aceasta (gura 1), diagonala secundar 
sau una din cele dou  semidiagonale paralele ³i al turate acesteia (gura 2);
2
- o rund  se încheie f r  un câ³tig tor dac  dup  marcarea celor N celule nu exist  pe tabla
de joc nicio linie, coloan , diagonal  sau semidiagonal  marcate cu acela³i simbol.

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

Figura 4.3: Puzzle

joc.in joc.out Explicaµii


2 14 Doar 3 dintre cele 4 runde jucate au fost
4 4 câ³tigate. Pân  în momentul câ³tig rii în
16 13 15 9 10 1 5 2 6 14 3 7 11 4 8 12 prima rund  s-au f cut 7 marc ri, în a doua
1 2 3 4 5 6 7 8 12 11 10 9 13 14 15 16 14, iar în a treia 8. Deci num rul maxim
1 5 9 6 2 7 3 8 4 10 11 12 13 14 15 16 de marc ri f cute pân  la câ³tigarea unei
1 2 3 4 8 7 6 5 12 11 10 9 16 15 14 13 runde este 14.

Timp maxim de executare/test: 0.3 secunde


Memorie: total 64 MB din care pentru stiv  32 MB
Dimensiune maxim  a sursei: 15 KB

4.2.1 Indicaµii de rezolvare

prof. Costineanu Raluca, Colegiul National ’’Stefan cel Mare’’ Suceava

O solutie posibila ar fi contorizarea pe parcursul desfasurarii rundelor de joc a n


de celule marcate de fiecare jucator pe fiecare linie/coloana/diagonala/semidiagona

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.

Jucatorului Teodora ii va corespunde jucator[0], iar lui stefan jucator[1]


Pentru fiecare din cele K runde de joc:
- stabilim jucatorul care incepe runda
CAPITOLUL 4. OJI 2017 55

- initializam cu 0 campurile corespunzatoare celor 2 jucatori


- citim cele n*n numere corespunzatoare rundei si pentru fiecare numar citit,
pana se ajunge la castigarea rundei:
-- determinam linia si coloana pe tabla de joc corespunzatoare numarului cit
-- actualizam corespunzator linia/coloana/digonala/semidiagonala marcata
-- verificam daca marcarea curenta a condus la finalizarea rundei, caz in ca
--- actualizam numarul corespunzator castigatorului
--- verificam daca numarul de marcari facute pana la castigarea runde
curente este mai mare decat maximul si in caz afirmativ actualiza
valoarea maximului
--- continuam doar cu citirea numerelor pana la sfarsitul runde

O solutie in care se simuleaza jocul prin costruirea matricei corespunzatoare table


si in care se verifica la fiecare marcare daca runda a fost castigata poate obtine
partial de maximum 40 de puncte.

4.2.2 *Rezolvare detaliat 

4.2.3 Codul surs 

Listing 4.2.1: joc.cpp

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 }

Listing 4.2.2: joc_dl.cpp

1 //Dana Lica
2 #include <cstdio>
3 #include <algorithm>
4 #include <cstring>
5
6 #define Nmax 155
7
CAPITOLUL 4. OJI 2017 57

8 using namespace std;


9
10 int diag1T[5], diag1S[5], diag2T[5], diag2S[5],
11 LT[Nmax], LS[Nmax], CT[Nmax], CS[Nmax];
12 int N, K, test, T, winS, winT, i, x, moves;
13 bool win;
14
15 bool addT(int x)
16 {
17 if(win) return false;
18
19 int linie, coloana, dif;
20
21 if(x%N==0)
22 linie = x/N, coloana = N;
23 else
24 linie = x/N+1, coloana = x%N;
25
26 ++LT[linie];
27 if(LT[linie]==N)
28 return true;
29
30 ++CT[coloana];
31 if(CT[coloana]==N)
32 return true;
33
34 dif = linie-coloana+2;
35
36 if(dif>=1 && dif<=3)
37 {
38 ++diag1T[dif];
39 if((dif==2 && diag1T[dif]==N) ||
40 (dif!=2 && diag1T[dif]==N-1))
41 return true;
42 }
43
44 dif = linie+coloana-(N-1);
45 if(dif>=1 && dif<=3)
46 {
47 ++diag2T[dif];
48 if((dif==2 && diag2T[dif]==N) ||
49 (dif!=2 && diag2T[dif]==N-1))
50 return true;
51 }
52
53 return false;
54 }
55
56 bool addS(int x)
57 {
58 if(win) return false;
59
60 int linie, coloana, dif;
61
62 if(x%N==0)
63 linie = x/N, coloana = N;
64 else
65 linie = x/N+1, coloana = x%N;
66
67 ++LS[linie];
68 if(LS[linie]==N) return true;
69
70 ++CS[coloana];
71 if(CS[coloana]==N) return true;
72
73 dif = linie-coloana+2;
74 if(dif>=1 && dif<=3)
75 {
76 ++diag1S[dif];
77 if((dif==2 && diag1S[dif]==N) ||
78 (dif!=2 && diag1S[dif]==N-1))
79 return true;
80 }
81
82 dif = linie+coloana-(N-1);
83 if(dif>=1 && dif<=3)
CAPITOLUL 4. OJI 2017 58

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 }

Listing 4.2.3: joc_pracsiu.cpp

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 }

Listing 4.2.4: joc_rm.cpp


CAPITOLUL 4. OJI 2017 61

1 ///prof. Rotar Mircea


2 #include <fstream>
3
4 using namespace std;
5
6 ifstream f("joc.in");
7 ofstream g("joc.out");
8
9 int v,n,k;
10
11 void zero(auto &a,int n)
12 {
13 for(int i=1;i<=n;++i)
14 {
15 for(int j=1;j<=n;++j)
16 {
17 a[i][j]=0;
18 }
19 }
20 }
21
22 int test(auto a, int x, int y, int p)
23 {
24 int lin=1,col=1,d1=1,d2=1,dif,i1,j1;
25
26 for(int j=1;j<=n;j++) ///linia
27 {
28 if(a[x][j]!=p){
29 lin=0;
30 break;
31 }
32 }
33
34 if(lin==1) return 1;
35 for(int i=1;i<=n;i++) ///coloana
36 {
37 if(a[i][y]!=p){
38 col=0;
39 break;
40 }
41 }
42
43 if(col==1) return 1;
44
45 dif = y-x; ///diag principala
46 if(dif>=-1 && dif<=1)
47 {
48 if(dif>=0)
49 {
50 i1=1; j1=1+dif;
51 }
52 else
53 {
54 dif=(-1)*dif;
55 i1 = 1 + dif; j1=1;
56 }
57
58 for(int i=0;i<=n-dif-1;i++)
59 {
60 if(a[i1+i][j1+i]!=p)
61 {
62 d1=0; break;
63 }
64 }
65 }
66 else
67 {
68 d1=0;
69 }
70
71 if(d1==1) return 1;
72
73 dif=x-(n-y+1); ///diag secundara
74 if(dif>=-1 && dif<=1)
75 {
76 if(dif<=0)
CAPITOLUL 4. OJI 2017 62

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

5.1 axyz - OJI 2016


Problema 1 - axyz 1000 de puncte
Se consider  numerele naturale A (format din dou  sau trei cifre, toate distincte ³i nenule) ³i
X (format din N cifre, toate nenule).
Din num rul X, folosind toate cele N cifre ale sale, se poate construi un cel mai mare num r
natural Y strict mai mic decât X. De exemplu, pentru X 121621 se construie³te Y 121612.
Tot din num rul X, se poate obµine num rul A prin ³tergerea unor cifre din scrierea lui X
³i alipirea celor r mase, f r  a le schimba ordinea. De exemplu, dac  X 121621 ³i A 12,
exist  Z 3 posibilit µi distincte prin care s  obµinem num rul A din X ³i anume: 1) 121621; 2)
121621; 3) 121621.
Cerinµe
Cunoscându-se numerele A, N ³i cele N cifre ale lui X, s  se determine:
1. cel mai mare num r natural Y, strict mai mic decât X, care se poate obµine rearanjând
cifrele lui X;
2. num rul maxim Z de posibilit µi distincte prin care se poate obµine num rul A din num rul
X prin ³tergerea unor cifre ³i alipirea celor r mase, f r  a le schimba ordinea.

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

Timp maxim de executare/test: 0.1 secunde


Memorie: total 2 MB din care pentru stiv  2 MB
Dimensiune maxim  a sursei: 5 KB

5.1.1 Indicaµii de rezolvare

Autor prof. Carmen Minca


Colegiul National de Informatica ’’Tudor Vianu’’, Bucuresti

Descrierea solutiei

Cerinta 1 (30 puncte)

O solutie se poate obtine astfel:

- Parcurgem sirul cifrelor de la pozitia N catre prima, intrerupand parcurgerea la


cifra X[k] cu proprietatea ca:
X[k]>X[k+1] <= X[k+2] <=...<= X[N]

- 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]

- Interschimbam cifrele X[k] si X[poz].

- Sortam descrescator in vectorul X cifrele de pe pozitiile k+1,k+2,...,N restul nu


nemodificandu-se. Complexitatea este data de algoritmul de sortare folosit,
maximum O(N2) - solutia obtine un punctaj partial

- Pentru a obtine o complexitate liniara (O(N)), ne vom folosi de faptul ca in vect


cifrele de pe pozitiile k+1,k+2,...,N sunt sortate crescator. Nu are sens sa le sor
descrescator, deoarece le putem scrie in fisierul de iesire in ordine inversa, solu
cautata fiind X[1], X[2],..., X[K], X[N], X[N-1],..., X[K+1]

Cerinta 2 (70 puncte)

O solutie cu punctaj maxim se poate obtine astfel:

2.1.Pentru A format din 2 cifre

-Separam cifrele lui A: ab, a=[A/10], b=A%10

-Parcurgem sirul cifrelor lui X de la pozitia N catre prima numarand aparitiile


cifrelor b in variabila NB (initial cu valoarea 0). Variabila Z va memora
numarul perechilor cerute (initial este 0).

-in timpul acestei parcurgeri, se studiaza fiecare cifra astfel:


- Daca cifra curenta este egala cu b atunci o numaram ( NB=NB+1).
CAPITOLUL 5. OJI 2016 66

- 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)

2.2.Pentru A format din 3 cifre

-Separam cifrele lui A: abc, a=[A/100], b=[A/10%10], c=A%10;

-Parcurgem sirul cifrelor lui X de la pozitia N catre prima numarand aparitiile


cifrelor c in variabila NC (initial cu valoarea 0). La intilnirea unei cifre b
se pot genera NC numere de forma bc, astfel vom incrementa variabila NBC
(initial cu valoarea 0) cu valoarea NC. La intilnirea unei cifre a se pot genera
NBC numere de forma abc, astfel vom incrementa variabila Z (initial cu valoarea 0)
cu valoarea NBC. Variabila Z va memora numarul perechilor cerute.

-in timpul acestei parcurgeri, se studiaza fiecare cifra astfel:


- Daca cifra curenta este egala cu c atunci o numaram ( NC=NC+1).
- Daca cifra curenta este egala cu b atunci se pot forma inca NC numere de
si adaugam acest numar la variabila NBC ( NBC=NBC+NC).
- Altfel, daca cifra curenta este a atunci se pot forma cu NBC numere A di
curenta si cele NBC numere bc situate la dreapta lui a in X. Adaugam numarul ace
la celelalte gasite pana in acest moment (Z=Z+NBC)

-Complexitate O(N)

5.1.2 *Rezolvare detaliat 

5.1.3 Cod surs 

Listing 5.1.1: axyz.cpp

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 }

5.2 galerie - OJI 2016


Problema 2 - galerie 100 de puncte
La întâlnirea anual  a cârtiµelor, la concursul pentru selecµia noilor
membri ai consiliului director, a fost propus  urm toarea problem :
De jur-împrejurul unui teren dreptunghiular împ rµit în n  m celule
de form  p trat , cu aceea³i arie, cârtiµele au s pat galerii exterioare.
Celulele aate pe marginea terenului sunt numerorate consecutiv, de
la 1 la 2 ˜ n  m, începând din colµul din stânga-sus, ca în imaginea
al turat . În galeriile exterioare, pe marginea terenului, se a  t cârtiµe
care sunt preg tite s  sape galerii interioare. Cârtiµele aate pe latura
de Nord a terenului se vor deplasa c tre Sud, cele care se a  pe latura
de la Est se vor deplasa c tre Vest, cele care se a  pe latura de la Sud
se vor deplasa c tre Nord, iar cele care se a  pe latura de la Vest se
Figura 5.1: galerie
vor deplasa c tre Est.
Cârtiµele încep s  sape în acela³i timp. în ecare or , o cârtiµ  sap  într-o singur  celul  a
terenului.
O cârtiµ  se opre³te dac :
a ajunge într-o alt  galerie interioar ; ea nu sap  în aceasta, iar galeria ei se une³te cu cea în
care ajunge;
a în celula în care sap , mai sap  ³i alte cârtiµe, în aceea³i or ; galeriile lor se unesc într-o
singur  galerie ³i toate aceste cârtiµe se opresc;
a ajunge pe marginea terenului, în partea opus  celei din care a plecat, galeria s pat  de ea
pân  în acest moment comunicând acum cu galeria exterioar , în care ea nu sap .
De exemplu, dac  pe marginea unui teren format din 7  5 celule, se a  5 cârtiµe, în celulele
3, 8, 10, 19 ³i 23, atunci, dup  o or , terenul are conguraµia din g.1, dup  dou  ore, conguraµia
din g.2, dup  trei ore, conguraµia din g.3 (ultima cârtiµ  ajunge în galeria primei cârtiµe ³i
primele dou  cârtiµe sap  în aceea³i celul  ³i apoi se opresc), dup  4 ore, conguraµia din g.4,
dup  5 ore, conguraµia din g.5, când cele dou  cârtiµe r mase sap  pe marginea terenului ³i apoi
se opresc pentru c  au ajuns în galeria exterioar  (g.6). Galeriile acestora nu se unesc pentru c 
niciuna dintre ele nu a intrat în galeria celeilalte ³i nici nu s-au întâlnit într-o celul .
1 `
CAPITOLUL 5. OJI 2016 68

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

Timp maxim de executare/test: 0.5 secunde


Memorie: total 5 MB din care pentru stiv  5 MB
Dimensiune maxim  a sursei: 5 KB

5.2.1 Indicaµii de rezolvare

Autor prof. Cristina Sichim Colegiul National ’’Ferdinand I’’, Bacau

Cerinta 1 ( 30 puncte)

Problema se restrange la fiecare pas la multimea cartitelor active (cele care sapa)

Pentru fiecare moment de timp

* se determina, pentru fiecare dintre cartitele active, celula in care ajunge;

* 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);

* se contorizeaza momentele de timp in care cel putin o cartita este activa.

Cerinta 2 ( 70 de puncte)

Pentru fiecare cartita ci, se memoreaza lungimea li a galeriei interioare in care s

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.

Cand toate cartitele se opresc, se determina max{li | 1 <= i <= t}.

5.2.2 *Rezolvare detaliat 

5.2.3 Cod surs 

Listing 5.2.1: galerie0.cpp

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 }

Listing 5.2.2: galerie1.cpp

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

6.1 ech - OJI 2015


Problema 1 - ech 100 de puncte
Numim num r echilibrat un num r natural pentru care suma cifrelor de pe poziµii pare este
egal  cu suma cifrelor de pe poziµii impare.
De exemplu num rul 13552 este echilibrat, pentru c  152 8 3  5.

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.

Timp maxim de executare/test: 1.0 secunde


Memorie: total 2 MB din care pentru stiv  1 MB
Dimensiune maxim  a sursei: 10 KB

6.1.1 Indicaµii de rezolvare

Autor prof. Emanuela Cerchez Colegiul National ’’Emil Racovita’’ Iasi

Solutie 80 de puncte

Vom incrementa numarul N pana cand obtinem un numar echilibrat.


Pentru 40% dintre teste se poate lucra cu tipurile de date standard (problema
se reduce doar la a verifica proprietatea de numar echilibrat)

74
CAPITOLUL 6. OJI 2015 75

Pentru a lucra cu numere de cel mult 23 de cifre va trebui sa extragem


cifrele lui N, sa le plasam intr-un vector si sa simulam incrementarea.

Solutie 100 puncte

Se observa ca numerele echilibrate sunt divizibile cu 11.


Bazandu-ne pe aceasta observatie, putem aduna initial la N valoarea 11-r
(unde r=N%11) pentru a obtine primul numar divizibil cu 11 strict mai mare
decat N. La fiecare pas verificam daca numarul obtinut este echilibrat.
In caz contrar, adunam 11.

Solutie optima 100 puncte, prof. Pit-Rada Ionel-Vasile

Precalculam sumele partiale

si[i]=suma cifrelor din pozitiile impare incepand cu cea mai semnificativa


cifra si terminand cu pozitia i;

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.

Parcurgem numarul de la pozitia 0 (cifra cea mai putin semnificativa,


cifra unitatilor) si analizam doar pozitiile i unde cifra este < 9 si
poate fi imbunatatita. La fiecare astfel de pozitie verificam, in functie
de paritate, daca avem posibilitatea sa echilibram sumele.

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).

6.1.2 *Rezolvare detaliat 

6.1.3 Cod surs 

Listing 6.1.1: ech_add11.cpp

1 //Em. Cerchez 100 puncte


2 #include <fstream>
3 #include <cassert>
4
5 using namespace std;
6
7 ifstream fin("ech.in");
8 ofstream fout("ech.out");
9
10 int a[50];
11 int lg=0;
12 int nx[50];
13
14 void add(int x);
CAPITOLUL 6. OJI 2015 76

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 }

Listing 6.1.2: ech_lucia_miron.cpp

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 }

Listing 6.1.3: ech_Ovidiu_Dumitrescu.cpp

1 //100 de puncte, optim


2 #include<cstdio>
3 #include<algorithm>
CAPITOLUL 6. OJI 2015 78

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 }

Listing 6.1.4: ech_raluca_costinescu.cpp

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 }

Listing 6.1.5: ech_vasile_pit_rada.cpp

1 //100 de puncte, optim


2 #include<fstream>
3
4 using namespace std;
5
6 struct numar
7 {
8 int v[50],n;
CAPITOLUL 6. OJI 2015 81

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 }

6.2 lasere - OJI 2015


Problema 2 - lasere 100 de
puncte
Se consider  un teren reprezentat printr-o matrice cu n linii ³i n coloane având elemente numere
naturale. În ecare element al matricei este memorat  în lµimea zonei de teren corespunz toare
ca poziµie elementului respectiv. Pe acest teren sunt amplasate m lasere, în poziµii cunoscute. Un
laser este îndreptat spre unul dintre cele 4 puncte cardinale, codicate prin numere astfel: Nord
prin valoarea 1, Est prin valoarea 2, Sud prin valoarea 3 ³i respectiv Vest prin valoarea 4. Fiecare
laser va executa o singur  tragere ³i ca urmare va sc dea cu 1 valorile tuturor elementelor din
matrice din direcµia sa de tragere, exceptând poziµia laserului respectiv.
Dup  efectuarea tuturor tragerilor, se caut  poziµiile tuturor gropilor ³i ale tran³eelor.
Numim groap  un element din matrice pentru care toate cele 8 elemente învecinate pe linie,
coloan  sau diagonale au valori mai mari sau egale decât el.
Numim tran³ee o secvenµ  maximal  format  din dou  sau mai multe gropi situate pe aceea³i
linie, pe coloane consecutive. Secvenµa se nume³te maximal  dac  nu mai poate  prelungit  la
niciunul dintre capete.

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

Timp maxim de executare/test: 0.2 secunde


Memorie: total 8 MB din care pentru stiv  4 MB
Dimensiune maxim  a sursei: 10 KB

6.2.1 Indicaµii de rezolvare

Autor: prof. Nicu Vad Laurentiu, Liceul Teoretic Mihail Kogalniceanu Vaslui

Varianta 1 -100p

Se citesc datele si se modifica tabloul conform pozitilor laserelor in ordinea in c


Pentru a afla numarul de gropi se calculeaza poziile valorilor minime in cele opt d
si contorizarea acestora.
Pentru transee se foloseste un vector auxiliar cu valori de 0 si 1, 1 pentru poziti
se cauta secventa maxima de valori consecutive de 1 si se contorizeaza.
CAPITOLUL 6. OJI 2015 84

6.2.2 *Rezolvare detaliat 

6.2.3 Cod surs 

Listing 6.2.1: lasere_adrian_pintea.cpp

1 //Pintea Adrian Doru -Inspectoratul Scolar Judetean Cluj


2 #include<fstream>
3 #include<iostream>
4
5 using namespace std;
6
7 ifstream fin("lasere.in");
8 ofstream fout("lasere.out");
9
10 int a[202][202];
11 int cerinta,i,j,m,n,x,y,z,d;
12
13 int N(int x,int y)
14 {
15 int k;
16 for(k=1;k<x;k++)
17 if(a[k][y]>0) a[k][y]--;
18 return 0;
19 }
20
21 int S(int x,int y)
22 {
23 int k;
24 for(k=x+1;k<=n;k++)
25 if(a[k][y]>0) a[k][y]--;
26 return 0;
27 }
28
29 int V(int x,int y)
30 {
31 int k;
32 for(k=1;k<y;k++)
33 if(a[x][k]>0) a[x][k]--;
34 return 0;
35 }
36
37 int E(int x,int y)
38 {
39 int k;
40 for(k=y+1;k<=n;k++)
41 if(a[x][k]>0) a[x][k]--;
42 return 0;
43 }
44
45 int groapa(int x,int y)
46 {
47 if(a[x][y]<=a[x][y+1]&&a[x][y]<=a[x][y-1]&&a[x][y]<=a[x+1][y]&&
48 a[x][y]<=a[x-1][y]&&a[x][y]<=a[x+1][y+1]&&a[x][y]<=a[x-1][y+1]&&
49 a[x][y]<=a[x-1][y-1]&&a[x][y]<=a[x+1][y-1])
50 return 1;else return 0;
51 }
52
53 int transee(int l)
54 {
55 int k=0,p=1,q;
56 while(p<n)
57 {
58 q=1;
59 while((a[l][p]==a[l][p+q])&&groapa(l,p)&&groapa(l,p+q)) q++;
60 if(q>1) k++;
61 p=p+q;
62 }
63 return k;
64 }
65
CAPITOLUL 6. OJI 2015 85

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 }

Listing 6.2.2: lasere_emanuela_cerchez.cpp

1 //Emanuela Cerchez Colegiul National Emil Racovita 100 puncte


2 #include <fstream>
3
4 #define NMAX 208
5 #define INF 1000004
6
7 using namespace std;
8
9 ifstream fin("lasere.in");
10 ofstream fout("lasere.out");
11
12 int T[NMAX][NMAX];
13 bool G[NMAX][NMAX]; //G[i][j]=true daca in pozitia i j exista o groapa
14
15 int n, m;
16 int gropi, transee;
17 int c;
18 int dl[]={0, -1, 0, 1, 0, -1,-1, 1, 1};
19 int dc[]={0, 0, 1, 0, -1, -1, 1, -1, 1};
20
21 bool este_groapa(int lin, int col);
22 int cauta_gropi();
23 void bordare();
24 void trage(int lin, int col, int d);
25 int cauta_transee();
26
27 int main()
28 {int i, j, lin, col, d;
29 fin>>c>>n>>m;
30 for (i=1; i<=n; i++)
31 for (j=1; j<=n; j++) fin>>T[i][j];
32
33 bordare();
34 for (i=1; i<=m; i++)
CAPITOLUL 6. OJI 2015 86

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 }

Listing 6.2.3: lasere_lucia_miron.cpp

1 //Miron Lucia Colegiul "C. Negruzzi", Iasi


2 #include <fstream>
3
4 using namespace std;
5
CAPITOLUL 6. OJI 2015 87

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 }

Listing 6.2.4: lasere_nicu_vlad.cpp

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

63 /* for(i=1; i<=n; i++)


64 {
65 for(j=1; j<=n; j++) cout<<A[i][j]<<" ";
66 cout<<"\n";
67 }*/
68 }

Listing 6.2.5: lasere_raluca_costinescu.cpp

1 //Costineanu Veronica Raluca Colegiul National Stefan cel Mare Suceava


2 #include <fstream>
3
4 #define vmax 999999999
5
6 using namespace std;
7
8 ifstream f("lasere.in");
9 ofstream g("lasere.out");
10
11 int a[210][210],n, m, c, gr[210][210];
12
13 void trage(int x, int y, int d)
14 {
15 int i, j;
16 if(d==1)
17 for(i=x-1;i>=1;i--)
18 a[i][y]--;
19 else
20 if(d==2)
21 for(j=y+1;j<=n;j++)
22 a[x][j]--;
23 else
24 if(d==3)
25 for(i=x+1;i<=n;i++)
26 a[i][y]--;
27 else
28 for(j=y-1;j>=1;j--)
29 a[x][j]--;
30 }
31
32 int groapa(int x, int y)
33 {
34 if(a[x][y]<=a[x-1][y-1] and a[x][y]<=a[x-1][y] and
35 a[x][y]<=a[x-1][y+1] and a[x][y]<=a[x][y-1] and
36 a[x][y]<=a[x][y+1] and a[x][y]<=a[x+1][y-1] and
37 a[x][y]<=a[x+1][y] and a[x][y]<=a[x+1][y+1])
38 return 1;
39 return 0;
40 }
41
42 int main()
43 {
44 f>>c;
45 f>>n>>m;
46 int i, j, x, y, d, nr=0,p;
47 for(i=1;i<=n;i++)
48 for(j=1;j<=n;j++)
49 f>>a[i][j];
50 for(i=0;i<=n+1;i++)
51 a[0][i]=a[n+1][i]=a[i][0]=a[i][n+1]=vmax;
52 for(p=1;p<=m;p++)
53 {
54 f>>x>>y>>d;
55 trage(x,y,d);
56 }
57 for(i=1;i<=n;i++)
58 for(j=1;j<=n;j++)
59 if(groapa(i,j))
60 gr[i][j]=1, nr++;
61 int tr=0;
62 for(i=1;i<=n;i++)
63 {
64 j=1;
65 while(j<=n)
66 {
CAPITOLUL 6. OJI 2015 90

67 while(j<=n and gr[i][j]==0)j++;


68 x=0;
69 while(j<=n and gr[i][j]==1)j++, x++;
70 if(x>1)tr++;
71 }
72 }
73
74 if(c==1)
75 g<<nr<<’\n’;
76 else
77 g<<tr<<’\n’;
78 return 0;
79 }

Listing 6.2.6: lasere_vasile_pit_rada.cpp

1 //PIT-RADA IONEL-VASILE COLEGIUL NATIONAL TRAIAN


2 #include<fstream>
3
4 using namespace std;
5
6 ifstream fin("lasere.in");
7 ofstream fout("lasere.out");
8
9 int n,m,nrg,nrt,i,j,k,c,caz,li,co,dir;
10
11 short int a[203][203], b[203][203];
12 short int dl[8]={-1,-1, 0,+1, 0,-1,+1,+1};
13 short int dc[8]={-1, 0,+1, 0,-1,+1,+1,-1};
14
15 int main()
16 {
17 fin>>caz>>n>>m;
18
19 for(i=0;i<=n+1;i++)
20 {
21 a[i][0]=10000;
22 a[0][i]=10000;
23 a[n+1][i]=10000;
24 a[i][n+1]=10000;
25 }
26
27 for(i=1;i<=n;i++)
28 {
29 for(j=1;j<=n;j++)
30 {
31 fin>>a[i][j];
32 }
33 }
34
35 for(i=1;i<=m;i++)
36 {
37 fin>>li>>co>>dir;
38 switch(dir)
39 {
40 case 1 :
41 {
42 for(j=li-1;j>=1;j--)
43 {
44 a[j][co]--;
45 }
46 break;
47 }
48 case 3 :
49 {
50 for(j=li+1;j<=n;j++)
51 {
52 a[j][co]--;
53 }
54 break;
55 }
56 case 4 :
57 {
58 for(j=co-1;j>=1;j--)
59 {
CAPITOLUL 6. OJI 2015 91

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

7.1 p trat - OJI 2014


Problema 1 - patrat 100 de
puncte
Cel mai mare observator astronomic din România ³i din Europa de
Est, aat la Galaµi, a captat o imagine a boltei cere³ti, ce surprinde
toate stelele vizibile în acel moment. Imaginea este în format digital,
codicat  sub forma unui tablou bidimensional, cu N linii ³i M coloane.
Fiecare element al tabloului conµine un num r natural care reprezint 
intensitatea luminoas  a unei stele.
Numim stea str lucitoare o stea care are intensitatea luminoas  mai
Figura 7.1: patrat
mare decât a tuturor stelelor învecinate direct cu ea, pe orizontal ,
vertical  sau diagonal . Numim constelaµie p trat  patru stele str lucitoare care se a  plasate în
colµurile unui p trat cu laturile paralele cu marginile tabloului. Lungimea laturii unei constelaµii
p trate este egal  cu num rul de stele din care este format  latura. O stea str lucitoare poate
face parte din mai multe constelaµii p trate.

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.

Timp maxim de executare/test: 0.6 secunde


Memorie: total 2 MB
Dimensiune maxim  a sursei: 5 KB

7.1.1 Indicaµii de rezolvare


Autor prof. Sanda Junea Liceul Teoretic Gr Moisil Timisoara

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.

1. Determinarea numarului stelelor stralucitoare:

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

2. Determinarea numarului constelatiilor patrate si laturii celei mai mari


constelatii patrate:

Parcurg matricea pe linii iar in momentul in care intalnesc o stea


stralucitoare A, voi cauta de-a lungul liniei urmatoarea stea stralucitoare B.

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.

In cazul in care am gasit cele 4 stele stralucitoare in colturile unui patrat


voi contoriza o constelatie patrata.

Retin latura patratului determinat daca aceasta este cea mai mare pana in
acest moment.

Complexitatea algoritmului este O(L3) unde L=maximum(N si M).

7.1.2 *Rezolvare detaliat 

7.1.3 Cod surs 


CAPITOLUL 7. OJI 2014 94

Listing 7.1.1: patratdl.cpp

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 }

Listing 7.1.2: patratdt.cpp

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 }

Listing 7.1.3: patratMN.cpp

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 }

Listing 7.1.4: patratsj.cpp

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 }

Listing 7.1.5: patratvg.cpp

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 }

7.2 schi - OJI 2014


Problema 2 - schi 100 de puncte
La proba de s rituri cu schiurile din cadrul jocurilor olimpice de iarn  particip  N concurenµi,
numerotaµi cu numere de la 1 la N.
Regulile de desf ³urare a probei sunt urm toarele:
- concurenµii evolueaz  pe rând, în ordine de la 1 la N;
- ecare concurent va efectua o singur  s ritur ;
- dup  efectuarea s riturii ecare concurent prime³te un anumit punctaj;
- pe tot parcursul concursului, comisia de arbitri are obligaµia s  alc tuiasc  o list  cu punc-
tajele obµinute de concurenµi, în ordinea evoluµiei lor;
- evoluµia unui concurent dureaz  exact un minut;
- nu se face pauz  între evoluµiile a doi concurenµi care au numere de ordine consecutive;
- a³area punctajului nu necesit  timp suplimentar dup  efectuarea s riturii;
- proba se încheie la un minut dup  evoluµia ultimului concurent.
Pe tot parcursul concursului se µine în mod neocial ³i un clasament parµial, pe baza rezultatelor
obµinute de concurenµii care au evoluat pân  în acel moment. Asta pentru c  ³eful comisiei de
arbitri are o curiozitate aparte ³i pune K întreb ri sub forma urm toare: Câte minute s-a ocupat
primul loc din clasament cu un punctaj egal cu X puncte ? Dac  nici un concurent nu s-a clasat
pe primul loc cu X puncte atunci prime³te ca r spuns valoarea 0.
Cerinµe
Scrieµi un program care determin  r spunsul pentru ecare dintre cele K întreb ri puse de
³eful comisiei de arbitri.

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

schi.in schi.out Explicaµii


10 0 1 4 4 0 1 Cu punctajul 5 nu s-a ocupat niciodat  locul 1, cu punctajul 1
1 6 5 3 6 8 8 6 1 9 s-a ocupat primul loc un singur minut, cu punctajele 6 ³i 8 s-a
6 ocupat locul 1 câte 4 minute. Cu punctajul 2 nu s-a ocupat locul
5 1 6 8 2 9 1. El nici nu a fost obµinut de vreun concurent. Cu punctajul 9
s-a ocupat locul 1 un minut.

Timp maxim de executare/test: 0.5 secunde


Memorie: total 8 MB
Dimensiune maxim  a sursei: 5 KB

7.2.1 Indicaµii de rezolvare


Autor: prof. Marius Nicoli, C. N. ’’Fratii Buzesti’’, Craiova

Observam ca sirul P al punctajelor cu care se ocupa primul loc odata cu trecerea


minutelor este unul crescator.

La o intrebare X ne intereseaza lungimea secventei in care valoarea X apare in


sirul crescator P.

-Pentru punctaj maxim, trebuie sa determinam atat prima cat si ultima pozitie
din P unde se gaseste valoarea X folosind algoritmul de cautarea binara.

-Alt mod de a obtine punctaj maxim este urmatorul: Se sorteaza intrebarile


(cu un algoritm rapid de ordonare) si se parcurg deodata sirul de intrebari
si cel al punctajelor, care este si el sortat.

Exista mai multe abordari prin care se pot obtine punctaje partiale:

-La fiecare intrebare X parcurgem sirul pana cind intalnim toate


aparitiile lui X;
-La fiecare intrebare X determinam prin cautare binara o pozitie
pe care se gaseste X in sirul P apoi ne deplasam la dreapta si
la stanga cat timp intalnim X (cazul defavorabil este cand X apare
de multe ori in P, situatie in care cautarea devine liniara).

-Pastram o structura de date cu rezultatele la toate intrebarile


puse deja. Astfel, nu va fi necesar sa procesam o intrebare de 2 ori.
In functie de structura aleasa vor aparea depasiri ale timpului
de executare impus sau a memoriei disponibile.

7.2.2 *Rezolvare detaliat 

7.2.3 Cod surs 

Listing 7.2.1: schi.cpp

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 }

Listing 7.2.2: schidL.cpp

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 }

Listing 7.2.3: schidt.cpp

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 }

Listing 7.2.4: schiNQ.cpp


CAPITOLUL 7. OJI 2014 104

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 }

Listing 7.2.5: schiNQcb.cpp

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 }

Listing 7.2.6: schiSortQ.cpp

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

8.1 compar - OJI 2013


Problema 1 - compar 100 de puncte
Ana ³i Bogdan au inventat jocul Compar. Ana scrie pe tabl  o secvenµ  format  din N
numere naturale distincte cuprinse între 1 ³i N, apoi compar  ecare dou  numere învecinate din
secvenµ  scriind între ele semnul < sau semnul >, dup  caz.
De exemplu, dac  secvenµa de pe tabl  este 6 4 2 1 3 5, dup  compararea elementelor învecinate
³i inserarea semnelor în secvenµ , Ana obµine:

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.

Timp maxim de executare/test: 0.2 secunde


Memorie: total 2 MB din care pentru stiv  1 MB
Dimensiune maxim  a sursei: 5 KB
107
CAPITOLUL 8. OJI 2013 108

8.1.1 Indicaµii de rezolvare


prof. Emanuela Cerchez C. N. ’’E. Racovita’’ Iasi

Citim secventa de semne intr-un vector de caractere si calculam numarul de


caractere citite.

Incepem sa reconstituim secventa initiala incepand de la valoarea crt=1.

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.

Nu sunt necesare operatii cu siruri de caractere.

Complexitatea solutiei este liniara.

Solutia 2 - prof. Dana Marcu

Se considera un minim, initial 1 si un maxim, initial egal cu n.

Se parcurge sirul.

Daca pe pozitia curenta, i, din sir se afla caracterul ’<’, se afiseaza


valoarea minimului si se reactualizeaza prin incrementare cu 1.

Daca caracterul curent din sir este ’>’, se afiseaza maximul si


se micsoreaza cu 1 valoarea acestuia.

8.1.2 *Rezolvare detaliat 

8.1.3 Codul surs 

Listing 8.1.1: compar_dm.cpp

1 //Dana Marcu 100 puncte


2 #include<cstring>
3 #include<fstream>
4
5 using namespace std;
6
7 char s[100000];
8
9 int main()
10 {
11 ifstream fin("compar.in");
12 ofstream fout("compar.out");
13
14 fin>>s;
15 int N;
16 N=strlen(s)+1;
17 fout<<N<<"\n";
18
19 int maxx=N, minn=1;
CAPITOLUL 8. OJI 2013 109

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 }

Listing 8.1.2: compara_en.cpp

1 //Eugen Nodea 100 puncte


2 # include <fstream>
3 # include <cstring>
4
5 # define lmax 100001
6
7 using namespace std;
8
9 ifstream f("compar.in");
10 ofstream g("compar.out");
11
12 int i,N,Max,Min,j,k;
13 char s[lmax];
14
15 int main()
16 {
17 f.getline(s,lmax);
18 N=strlen(s);
19 g<<N+1<<"\n";
20
21 Max=N+1;
22 Min=1;
23 i=0;
24 while(i<N)
25 {
26 if (s[i]==’<’)
27 {
28 g<<Min<<" ";
29 ++Min; ++i;
30 }
31 else
32 {
33 j=i;
34 while (s[j]==’>’ && j<N) ++j;
35 for (k=i;k<j;++k)
36 {
37 g<<Max<<" ";
38 --Max;
39 }
40 i=j;
41 }
42 }
43
44 if (s[N-1]==’<’)
45 g<<Min<<"\n";
46 else
47 g<<Max<<"\n";
48
49 return 0;
50 }

8.2 unic - OJI 2013


Problema 2 - unic 100 de
puncte
Se consider  un ³ir A A1 , A2 , ..., AN , format din N numere naturale nenule. Dou  numere
se consider  vecine dac  se a  pe poziµii al turate (Ai are ca vecini pe Ai1 ³i Ai1 , pentru orice
1 $ i $ N , A1 are ca vecin doar pe A2 , iar AN are ca vecin doar pe AN 1 ).
CAPITOLUL 8. OJI 2013 110

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

Timp maxim de executare/test: 1.0 secunde


Memorie: total 2 MB din care pentru stiv  1 MB
Dimensiune maxim  a sursei: 5 KB

8.2.1 Indicaµii de rezolvare


prof. Eugen Nodea Colegiul National ’’Tudor Vladimirescu’’, Tg-Jiu

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);

//verificam posibile unificari


Cat timp (comun(a[i],a[i-1]) && i>1) Executa
a[i-1] = unific(a[i-1],a[i])
i--;
Sf. cat timp
Altfel
a[++i] = xa
Sf. daca
Sf. cat timp

Un caz aparte il reprezinta numerele care contin cifra 0.

O solutie brute-force care elimina prin deplasare elementele


(A[i])i=1,N obtine cel mult 50p.

8.2.2 *Rezolvare detaliat 

8.2.3 Cod surs 

Listing 8.2.1: unic_em.cpp

1 //Emanuela Cerchez 100 puncte


2 #include <fstream>
3 #include <cassert>
4
5 #define NMAX 100001
6
7 using namespace std;
8
9 ifstream fin("unific.in");
CAPITOLUL 8. OJI 2013 112

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;} }

Listing 8.2.2: unic_eugen_1.cpp

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

9.1 arme - OJI 2012


Problema 1 - arme 100 de puncte
N arme,
Vasile joac  (din nou!) jocul s u preferat cu împu³c turi. Personajul s u are la brâu
a³ezate în N huse speciale, numerotate de la 1 la N . i are puterea pbi (1 & i & N ).
Arma din husa
În camera armelor a g sit M arme, a³ezate pe perete, în M locaµii, numerotate de la 1 la M .
Pentru ecare arm  j (1 & j & M ) este cunoscut  puterea sa pcj .
Vasile poate înlocui arme pe care le are la brâu cu arme aate pe perete în camera armelor.
La o înlocuire el ia arma de pe perete din locaµia j (1 & j & M) ³i o pune la brâu în husa i
(1 & i & N ), iar arma din husa i o pune pe perete în locaµia j .
Cerinµe
Scrieµi un program care s  determine suma maxim  a puterilor armelor pe care le va avea la
brâu Vasile dup  efectuarea înlocuirilor.

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

Timp maxim de executare/test: 0.2 secunde


Memorie: total 2 MB din care pentru stiv  1 MB
Dimensiune maxim  a sursei: 5 KB

116
CAPITOLUL 9. OJI 2012 117

9.1.1 Indicaµii de rezolvare


prof. Emanuela Cerchez C. N. ’’Emil Racovita’’ Iasi

Solutie 1 - Emanuela Cerchez


----------------------------
Vom utiliza metoda Greedy.

Sortam armele de la brau crescator dupa punctaj.


Sortam si armele din camera armelor crescator dupa punctaj.
Parcurgem in ordine crescatoare armele de la brau si le inlocuim pe cele
mai mici arme de la brau cu cele mai mari din camera armelor
(doar daca punctajul se mareste).

Solutie 2 - Marinel serban


--------------------------
Utilizand interclasarea a doi vectori sortati (puterile armelor), insumam
primele n valori din cei doi vectori sortati descrescator. Nu retinem
vectorul realizat dupa interclasare.

Solutie 3 - Marcu Ovidiu/Mot Nistor


-------------------------------------
Se ordoneaza crescator sirul puterilor armelor de la brau si descrecator
sirul puterilor armelor de pe perete. Se inlocuieste arma cu cea mai mica
putere cu arma cu putere maxima dintre cele aflate pe perete
(daca este posibil) si asa mai departe pana cand nu mai putem alege nimic
de pe perete (pbi>=pci) sau nu mai avem arme la dispozitie (m<n).

Suma initiala a puterilor pbi va creste la fiecare inlocuire cu diferenta


pci-pbi.

O scurta justificare a faptului ca acest mod de alegere conduce la suma maxima


este urmatoarea demonstratie:
Notam :
-sirul puterilor armelor de la brau cu a[1..n] si
-sirul puterilor de pe perete cu b[1..m].

Figura 9.1: armeIR

9.1.2 *Rezolvare detaliat 


CAPITOLUL 9. OJI 2012 118

9.1.3 Cod surs 

Listing 9.1.1: arme_Adrian.cpp

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 }

Listing 9.1.2: arme_ema.cpp

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 }

Listing 9.1.3: arme_Ovidiu.cpp

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 }

9.2 triunghi - OJI 2012


Problema 2 - triunghi 90 de
puncte
Se consider  un triunghi alc tuit din numere naturale scrise pe n linii
ca în gura al turat .
Liniile triunghiului sunt numerotate de la 1 la n, începând cu linia de
la baza triunghiului (linia de jos), iar poziµiile pe linie sunt numerotate
începând cu 1 de la stânga la dreapta.
Fiecare num r din triunghi, exceptând pe cele de pe linia 1, este egal
cu suma numerelor aate imediat sub el, în stânga ³i respectiv în dreapta
lui.

Cerinµe Figura 9.2: triunghi


CAPITOLUL 9. OJI 2012 121

Cunoscând câte un num r de pe ecare linie a triunghiului, determinaµi toate numerele de pe


linia 1.

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

Timp maxim de executare/test: 0.2 secunde


Memorie: total 20M B din care pentru stiv  10M B
Dimensiune maxim  a sursei: 5KB

9.2.1 Indicaµii de rezolvare


prof. Nistor Mot C. N. ’’N. Balcescu’’ Braila

Solutia1 - reconstruirea matricii (Pintea Adrian, Nodea Eugen, Marcu Ovidiu)


----------------------------------------------------------------------------
Evident, cunoscand singurul numar de pe linia n si unul dintre cele doua
numere de pe linia n-1 il putem afla imediat pe celalalt, printr-o scadere.

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.

Solutia 2 - utilizarea doar a 2 vectori


CAPITOLUL 9. OJI 2012 122

(Mot Nistor, serban Marinel, Nodea Eugen, Marcu Ovidiu)


-------------------------------------------------------
Nu am folosit matrice ci, ca si in triunghiul lui Pascal, numai doua
linii: linia anterioara L1 care este completata si linia curenta, L2,
care se calculeaza in acest moment.

Dupa calculare linia curenta L2 devine linie precedenta L1 si procesul


continua. Initial linia L1 este formata doar din elementul din varful
triunghiului L1[1].

9.2.2 *Rezolvare detaliat 

9.2.3 Cod surs 

Listing 9.2.1: tri_adrian_.cpp

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 }

Listing 9.2.2: tri_marinel_.cpp

1 //Serban Marinel //februarie 2012


2 #include <fstream>
3
4 #define DIM 1001
5
6 using namespace std;
7
8 ifstream fin("triunghi.in");
9 ofstream fout("triunghi.out");
10
11 int N, p[DIM];
12 unsigned long long L1[DIM], L2[DIM], v[DIM];
13
14 void citire()
15 {
16 int i;
17 fin >> N;
18 for (i = N; i >0; i--) //le citesc invers ca sa lucrez
19 fin >> p[i] >> v[i]; //"mai usor" la reconstruire
20 fin.close();
21 }
22
23 void refa()
24 {
25 int i, j;
26 for (i = 2; i <= N; i++) //refa linia i (de sus in jos)
27 {
28 L2[p[i]] = v[i]; //pun in L2 valoarea cunoscuta
29 if (p[i] > p[i - 1]) //detectez sensul recalcularii
30 {
31 for (j = p[i] - 1; j > 0 ; j--) //intai spre stanga
32 L2[j] = L1[j] - L2[j + 1];
33 for (j = p[i] + 1; j <= i; j++) //apoi spre freapta
34 L2[j] = L1[j - 1] - L2[j - 1];
35 }
36 else
37 {
38 for (j = p[i] + 1; j <= i; j++) //intai spre dreapta
39 L2[j] = L1[j - 1] - L2[j - 1];
40 for (j = p[i] - 1; j > 0; j--) //apoi spre stanga
41 L2[j] = L1[j] - L2[j + 1];
42 }
43 for (j = 1; j <= i; j++) //copiez L2 in L1
44 L1[j] = L2[j]; //adica L2 devine L1
45 for (j = 1; j <= i; j++) //"curat" L2
46 L2[j] = 0; //nu era neaparat necesar
47 }
48 }
49
50 void afisare()
51 {
52 int i;
53 for (i = 1; i < N; i++) //afisez primele N-1 valori
54 fout << L1[i] << ’ ’; //urmate de un spatiu
55 fout << L1[N] << ’\n’; //apoi ultima valoare urmata de ENTER
56 }
57
58 int main()
59 {
60 citire();
61 L1[1] = v[p[1]];
62 refa();
CAPITOLUL 9. OJI 2012 124

63 afisare();
64 fout.close();
65 return 0;
66 }

Listing 9.2.3: triunghi_Eugen00.cpp

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 }

Listing 9.2.4: triunghi_Eugen11.cpp

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 }

Listing 9.2.5: triunghi_Eugen22.cpp

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 }

Listing 9.2.6: triunghi_O_Marcu_matrice.cpp

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 }

Listing 9.2.7: triunghi_O_Marcuo.cpp

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

10.1 grupe - OJI 2011


Problema 1 - grupe 100 de puncte
Se consider  un tablou bidimensional cu m linii, n coloane ³i elemente numere naturale. Pentru
ecare element se determin  num rul de divizori pozitivi. Se formeaz  apoi grupe cu elementele
tabloului care au acela³i num r de divizori, grupe notate G1 , G2 , ..., Gk . Se ordoneaz  descresc tor
grupele dup  num rul de elemente ce le conµin. Se ³tie c  o grup  G1 se a  în faµa unei alte grupe
G2 dac  G1 are mai multe elemente decât G2 sau, în cazul în care cele dou  grupe conµin acela³i
num r de elemente, num rul de divizori ai elementelor din grupa G1 este mai mare decât num rul
de divizori ai elementelor din grupa G2 . Dup  ordonarea descresc toare a grupelor, not m prima
grup  cu A ³i a doua grup  cu B. În cazul în care toate elementele vor avea acela³i num r de
divizori, va exista o singur  grup , grupa A.

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.

Timp maxim de executare/test: 1.0 secunde

10.1.1 Indicaµii de rezolvare


Timplaru Roxana - Liceul de Informatica ’’Stefan Odobleja’’, ISJ Dolj

Pentru fiecare element se determina numarul de divizori pozitivi. Se poate opta


pentru modificarea elementului cu valoarea numarului sau de divizori, dar nu se
mai poate determina astfel cel mai mare element dintr-o grupa. De aceea, se va
folosi un vector v in care v[i] reprezinta numarul de elemente care au exact i
divizori pozitivi si vectorul w in care w[i] reprezinta cel mai mare element
care are exact i divizori pozitivi.

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.

10.1.2 *Rezolvare detaliat 

10.1.3 Cod surs 

Listing 10.1.1: RCGRUPE.CPP

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 }

10.2 litere - OJI 2011


Problema 2 - litere 100 de puncte
Algorel a primit un joc care conµine n jetoane pe care sunt scrise litere mari ale alfabetului.
Fiecare liter  are asociat un cod format dintr-o singur  cifr  nenul . Jetoanele se a³eaz  în ordinea
dat  iniµial, iar prin citirea literelor de pe acestea, de la primul la ultimul jeton, se formeaz  un
cuvânt. Dac  se citesc numerele de pe ecare jeton, începând de la primul la ultimul, se obµine
un num r k1 . Jocul continu  la fel, dar se a³eaz  jetoanele începând de la al doilea la ultimul,
obµinându-se un nou num r k2 . Apoi, se a³eaz  jetoanele începând de la al treilea la ultimul,
obµinându-se un nou num r k3 , ³.a.m.d. pân  se ajunge la a³ezarea doar a ultimului jeton, caz în
CAPITOLUL 10. OJI 2011 131

care se obµine num rul kn .

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

Timp maxim de executare/test: 1.0 secunde

10.2.1 Indicaµii de rezolvare


solutie posibila pentru 100 puncte

//citirea datelor folosind siruri de caractere(char)


// se numara succesiunile de forma vocala-consoana sau consoana-vocala
// text[i]=vocala si text[i+1]=consoana sau
// text[i+1]=vocala si text[i]=consoana
//calcularea sumelor
CAPITOLUL 10. OJI 2011 132

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

10.2.2 *Rezolvare detaliat 

10.2.3 Cod surs 

Listing 10.2.1: litere.cpp

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

11.1 Cuvinte - OJI 2010


Problema 1 - Cuvinte 100 de puncte
Se consider  un ³ir de cuvinte separate dou  câte dou  printr-un spaµiu. Fiecare cuvânt este
caracterizat prin num rul de ordine care reprezint  poziµia lui în ³irul de cuvinte (primul cuvânt
are num rul de ordine 1). Unui cuvânt i se pot aplica în mod repetat urm toarele transform ri:
primul caracter al cuvântului (cel mai din stânga) se ³terge de acolo ³i se adaug  dup  ultimul
caracter din cuvânt. Astfel, dintr-un cuvânt s cu k caractere se pot obµine alte k  1 cuvinte
pe care le numim cuvinte obµinute din transformarea cuvântului s. De exemplu, dintr-un cuvânt
format din 4 caractere c1 c2 c3 c4 , cuvintele obµinute prin transformarea lui sunt: c2 c3 c4 c1 , c3 c4 c1 c2 ,
c4 c1 c2 c3 .
Se caut  în ³irul de cuvinte prima pereche de cuvinte vecine a, b, în care al doilea cuvânt
din pereche (cuvântul b) este identic cu un cuvânt obµinut din transformarea lui a. Dac  exist  o
astfel de pereche, se ³terge cuvântul b din ³ir. Prin ³tergerea cuvântului b din ³ir, acesta va avea
mai puµin cu un cuvânt! Se repet  operaµia de c utare de mai sus pân  când în ³irul r mas nu
mai exist  o pereche a, b de cuvinte vecine, astfel încât b s  e obµinut prin transformarea lui a.
Se ³tie c  pe parcursul modic rilor, cuvintele nu-³i schimb  numerele de ordine pe care le-au
avut iniµial.

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

11.1.1 Indicaµii de rezolvare


Timplaru Roxana Liceul de Informatica ’’Stefan Odobleja’’ Craiova

Pentru primul cuvant se determina toate cuvintele obtinute prin transformarea lui.

Se verifica apoi cuvantul al doilea in lista de cuvinte obtinuta anterior.

Daca acesta se regaseste in lista, se sterge si se verifica al treilea cuvant daca


este in lista, daca si acesta este se sterge si se continua in acelasi mod pana nu
mai exista cuvinte in lista.

In momentul in care se gaseste un cuvant care nu mai e xista in lista,


se construieste lista de cuvinte pentru acesta cu cuvintele obtinute prin
transformarea sa. Se continua in acelasi mod pana se epuizeaza toate cuvintele.

11.1.2 *Rezolvare detaliat 

11.1.3 Cod surs 

Listing 11.1.1: 7_pr1_s.cpp

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

20 int verifica(unsigned int j, unsigned int n)


21 {
22 unsigned int i;
23 for(i=0;i<n;i++)
24 {
25 if (strcmp(x[j],y[i])==0)
26 return 1;
27 }
28
29 return 0;
30 }
31
32 int main()
33 {
34 char s[255],*p;
35 unsigned int n,i=0,t,j,prima=0;
36
37 ifstream f("cuvant.in");
38 ofstream g("cuvant.out");
39
40 f.get(s,255);
41 p=strtok(s," !");
42
43 while(p)
44 {
45 strcpy(x[i++],p);
46 poz[i-1]=i;
47 p=strtok(NULL," !");
48 }
49
50 n=i;
51 i=0;
52 j=1;
53 while(i<n-1)
54 {
55 transforma(x[i]);
56 if (verifica(j,strlen(x[i])-1))
57 {
58 for(t=j;t<n-1;t++)
59 {
60 strcpy(x[t],x[t+1]);
61 poz[t]=poz[t+1];
62 }
63
64 if (prima==0)
65 prima=j+1;
66
67 n--;
68 }
69 else
70 {
71 i++;
72 j=i+1;
73 }
74 }
75
76 if (poz)
77 g<<prima<<"\n";
78 else
79 g<<"0"<<"\n";
80
81 for(j=0;j<n;j++)
82 g<<poz[j]<<" ";
83
84 f.close();
85 g.close();
86
87 return 0;
88 }

11.2 Zar - OJI 2010


Problema 2 - Zar 100 de puncte
CAPITOLUL 11. OJI 2010 137

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.

Timp maxim de executare/test: 1.0 secunde


CAPITOLUL 11. OJI 2010 138

11.2.1 Indicaµii de rezolvare


Iordaiche Cristina Liceul ’’Grigore Moisil’’ Timisoara

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.

11.2.2 *Rezolvare detaliat 

11.2.3 Cod surs 

Listing 11.2.1: 7_pr2_s.cpp

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

ONI - Olimpiada naµional  de


informatic 

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:

***.in ***.out Explicaµii

Timp maxim de executare/test: 0.5 secunde pe Windows, 0.5 secunde pe Linux


Memorie: total 2 MB din care pentru stiv  2 MB
Dimensiune maxim  a sursei: 15 KB

12.1.1 *Indicaµii de rezolvare

12.1.2 *Cod surs 

12.1.3 *Rezolvare detaliat 

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

***.in ***.out Explicaµii

Timp maxim de executare/test: 0.5 secunde pe Windows, 0.5 secunde pe Linux


Memorie: total 2 MB din care pentru stiv  2 MB
Dimensiune maxim  a sursei: 15 KB

12.2.1 *Indicaµii de rezolvare

12.2.2 *Cod surs 

12.2.3 *Rezolvare detaliat 

12.3 ***
Problema 3 - ... 100 de puncte

Cerinµe
Date de intrare
Date de ie³ire
Restricµii ³i preciz ri

Exemple:

***.in ***.out Explicaµii

Timp maxim de executare/test: 0.5 secunde pe Windows, 0.5 secunde pe Linux


Memorie: total 2 MB din care pentru stiv  2 MB
Dimensiune maxim  a sursei: 15 KB

12.3.1 *Indicaµii de rezolvare

12.3.2 *Cod surs 

12.3.3 *Rezolvare detaliat 


Capitolul 13

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:

Figura 13.1: domino

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

Fi³ierul de ie³ire domino.out va conµine o singur  linie.


Dac  C 1, pe prima linie se vor a³a
N numere naturale separate prin câte un spaµiu; al i-lea num r a³at reprezint  suma numerelor
din jocul de domino având dimensiunea di (1 & i & N ). Dac  C 2, pe prima linie se vor a³a în
ordine, separate prin câte un spaµiu, valorile din ³irul B determinat conform regulilor din enunµ.

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

Figura 13.2: domino

Timp maxim de executare/test: 0.2 secunde


Memorie: total 8 MB din care pentru stiv  4 MB
Dimensiune maxim  a sursei: 10 KB
Sursa: domino.cpp, domino.c sau domino.pas va  salvat  în folderul care are drept nume
ID-ul t u.
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.

13.1.1 Indicaµii de rezolvare


Descrierea unei solutii posibile

Prof. Maria NITA - Colegiul National ’’Emanuil Gojdu’’, Oradea

Cerinta 1:

Pentru un set de dominouri de dimensiune d, determinarea valorii cerute se poate


realiza generand toate sumele de forma (i,j), cu 0 <= i <= d si 0 <= j <= i.

Generarea sumelor nu se incadreaza in timp pentru datele mari.

Daca termenii sumei se grupeaza se poate obtine:


0 0
1 0 1 1
2 0 2 1 2 2
3 0 3 1 3 2 3 3
...
i 0 i 1 i 2 ... ... i i
...
d 0 d 1 d 2 ... ... d i ... d d
CAPITOLUL 13. ONI 2019 146

Pe coloana 0: apare 0 de (d+1) ori si suma 0+1+2+...+d = d*(d+1)/2


Pe coloana 1: apare 1 de d ori si suma 1+2+...+d = d*(d+1)/2
Pe coloana 2: apare 2 de d-1 ori si suma 2+3+..+d = (1+2+3+...+d) -1 = d*(d+1)/2 -1
Pe coloana 3: apare 3 de d-2 ori si suma 3+4+...+d = (1+2+3+...+d)-1-2 = d*(d+1)/2
...
Pe coloana i: apare i de d-i+1 ori si suma i+(i+1)+...+d = 1+2+..+(i-1) + i + (i+1)
-(1+2+...+i-1) = d*(d+1)/2 -(1+2+..+i-1)
Pe coloana d: d apare de 1 ori si d = 1+2+..+(d-1)+d - (1+2+...+d-1) = d*(d+1)/2 -(

Adunam aceste sume si obtinem:

(d+1)*(d*(d+1)/2) + 1*d + 2*(d-1) + 3*(d-2) + ... + d*1 -1-(1+2)-(1+2+3)-...-(1+2+.


(d+1)* (d*(d+1)/2) +1*d +2*(d-1) + 3*(d-2) + ... + d*1-1*(d-1)-2*(d-2)-3*(d-3)-..-(
(d+1) * (d*(d+1)/2) + 1+2+3+..+d = (d+1) * (d*(d+1)/2) + d*(d+1)/2 =(d+1+1)* d*(d+1
d*(d+1)*(d+2)/2

Deci suma este pentru fiecare d in parte devine: d*(d+1)*(d+2)/2

Cerinta 2:

O modalitate de rezolvare poate fi:


- se ataseaza fiecarei valori v[i] valoarea p[i] = 10 numarul_de_cifre_v[i] - 1
- se parcurge vectorul v[], luand alternative valorile v[i] ( i=1, i<=j) si v[j] (j
- pentru v[i] cifrele se genereaza astfel:
cif = v[i]/p[i]; v[i] %= p[i]; p[i] /=10;
- pentru v[j] cifrele se genereaza astfel:
cif = v[j]%10; v[j]/=10;
- din cauza dimensiunii numerelor ce se pot obtine se vor folosi siruri de caracter
sir_anterior, sir_urmator
- in sir_urmator se introduc cifre pana la prima valoarea strict mai mare decat sir
- erau necesare prelucrari pentru situatia: prima cifra din sir_urmator este 0

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

13.1.2 *Rezolvare detaliat 

13.1.3 Cod surs 

Listing 13.1.1: Domino_1.cpp

1 //Maria Nita 100


2 #include <fstream>
3 #include <cstring>
4
5 #define M 10005
6
7 using namespace std;
8
9 ifstream cin("domino.in");
10 ofstream cout("domino.out");
11
12 int n, v[M], p[M];
13
14 int main()
15 {
16 int pr;
17 cin >> pr;
18
CAPITOLUL 13. ONI 2019 147

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 }

Listing 13.1.2: domino_2_assert.cpp

1 //Em. Cerchez 100


2 #include <fstream>
3 #include <cstring>
4 #include <cassert>
5
6 #define NMAX 100008
7
8 using namespace std;
9
10 ifstream fin("domino.in");
11 ofstream fout("domino.out");
12
13 int x, n, cerinta, lglast, lgcrt;
14 char s[NMAX];
15 char crt[NMAX];
16 char last[NMAX];
17 int v[12];
18
CAPITOLUL 13. ONI 2019 149

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 }

Listing 13.1.3: domino_3.cpp

1 //Florentina Ungureanu 100


2
3 #include <fstream>
4 #include <cstring>
5
6 const int MAXN = 10005;
7 const int MAXS = 1010;
8 const int MAXB = 100050;
9
10 using namespace std;
11
12 ifstream in("domino.in");
13 ofstream out("domino.out");
14
15 typedef unsigned long long nat;
16
17 int n,C,v[MAXN];
18 nat S[MAXS];
19 char s[MAXB],c[12],a[MAXB],b[MAXB];
20
21 void citire()
22 {
23 in>>C>>n;
24 if(C==1)
25 { for (int i=1; i<=n; ++i)
26 in>>v[i];
27 for (int i=1; i<=1000; ++i) S[i]=S[i-1]+nat(i)*(i+1)/2*3;
28 }
29 else
30 for (int i=1; i<=n; ++i)
31 {in>>c;
32 strcat(s,c);
33 }
34 }
35
36 void P1()
37 {
38 for (int i=1; i<=n; ++i)
39 out<<S[v[i]]<<’ ’;
40 }
41 void P2()
42 {
43 int i=1,j=strlen(s)-1,p=2,nc=1;
44 a[0]=s[0];a[1]=’\0’;
45 out<<a<<’ ’;
46
47 while(i<=j){
48 if(p%2){
49 while(s[i]==’0’)i++;
50 if(i+nc<=j+1)
51 { strncpy(b,s+i,nc);b[nc]=’\0’;
52 if(strcmp(a,b)>=0)
53 { nc++;strncpy(b,s+i,nc);b[nc]=’\0’;}
54 }else return;
55 i+=nc;
56 }else {
57 //out<<i<<’*’<<j<<’\n’;
58 while(j>=i&&s[j]==’0’)j--;
59 if(i+nc<=j+1)
60 { for(int k=0;k<nc;++k)
61 b[k]=s[j--];
62 b[nc]=’\0’;//out<<’*’<<b<<’\n’;
63 if(strcmp(a,b)>=0)
64 { if(i>j) return;
65 b[nc++]=s[j--];b[nc]=’\0’;
66 }
67 }
68 }
CAPITOLUL 13. ONI 2019 151

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

Figura 13.4: tuburi

Timp maxim de executare/test: 0.2 secunde


Memorie: total 8 MB din care pentru stiv  4 MB
Dimensiune maxim  a sursei: 10 KB
Sursa: tuburi.cpp, tuburi.c sau tuburi.pas va  salvat  în folderul care are drept nume ID-ul
t u.
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.

13.2.1 Indicaµii de rezolvare


Descrierea unei solutii posibile

Prof. Florentina Ungureanu - Colegiul National de Informatica, Piatra Neamt

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.

Pentru k diferit de 1 se identifica pentru fiecare coloana j din multimea de indici


{1, 2, ..., m}, de pe randul k tipul piesei care poate fi conectata cu fiecare dint
piesele aflate pe in una dintre pozitiile sus, stanga sau dreapta si se determina
lungimea traseului corespunzator conexiunii facute, recalculand lungimea traseului
bilei pe baza matricei construite pe parcursul rezolvarii cerintei 1.

13.2.2 *Rezolvare detaliat 

13.2.3 Cod surs 


CAPITOLUL 13. ONI 2019 153

Listing 13.2.1: tuburi_100.cpp

1 //Florentina Ungureanu 100


2 #include <bits/stdc++.h>
3
4 #define Nmax 505
5
6 using namespace std;
7
8 ifstream in("tuburi.in");
9 ofstream out("tuburi.out");
10
11 int n,m,lm,p,r,k=0;
12 int a[Nmax][Nmax],C[Nmax][Nmax];
13
14 void citire()
15 {
16 in>>p>>n>>m;
17 for (int i=1; i<=n; ++i)
18 for (int j=1; j<=m; ++j)
19 if(in>>a[i][j])++k;
20 for (int j=1; j<=m; ++j)
21 if (a[1][j]%2==0)
22 C[1][j]=j;
23 }
24
25 int lungime (int i,int j,int k)
26 {
27 int l=1,jj=0,g,col;
28 if(j==0||j>m)return 0;
29 do
30 {
31 g=0;
32 col=C[i][j];
33 if (a[i][j]&&a[i][j]<4)
34 {
35 if (a[i+1][j] && a[i+1][j]%2==0)
36 {i++;l++;g=1;}
37 }
38 else switch(a[i][j])
39 {
40 case 4:
41 if (a[i][j+1]==5 || a[i][j+1]==3)
42 {jj=j;j++;l++;g=1;}break;
43 case 5:
44 if (jj==j-1)
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;
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 if(p==1) out<<lm<<’\n’;
CAPITOLUL 13. ONI 2019 154

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 }

Listing 13.2.2: tuburiOcial.cpp

1 //Florentina Ungureanu 100


2 #include <bits/stdc++.h>
3
4 #define Nmax 505
5
6 using namespace std;
7
8 ifstream in("tuburi.in");
9 ofstream out("tuburi.out");
10
11 int n,m,lm,p,r,k=0;
12 int a[Nmax][Nmax],C[Nmax][Nmax];
13
14 void citire()
15 {
16 in>>p>>n>>m;
17 for (int i=1; i<=n; ++i)
18 for (int j=1; j<=m; ++j)
19 if(in>>a[i][j])++k;
20 for (int j=1; j<=m; ++j)
21 if (a[1][j]%2==0)
22 C[1][j]=j;
23 }
24
25 int lungime (int i,int j,int k)
26 {
27 int l=1,jj=0,g,col;
28 if(j==0||j>m)return 0;
29 do
30 {
31 g=0;
32 col=C[i][j];
33 if (a[i][j]&&a[i][j]<4)
34 {
35 if (a[i+1][j] && a[i+1][j]%2==0)
36 {i++;l++;g=1;}
37 }
38 else switch(a[i][j])
39 {
40 case 4:
41 if (a[i][j+1]==5 || a[i][j+1]==3)
42 {jj=j;j++;l++;g=1;}break;
43 case 5:
44 if (jj==j-1)
CAPITOLUL 13. ONI 2019 155

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.

Timp maxim de executare/test: 0.1 secunde


Memorie: total 8 MB din care pentru stiv  4 MB
Dimensiune maxim  a sursei: 10 KB
Sursa: venus.cpp, venus.c sau venus.pas va  salvat  în folderul care are drept nume ID-ul t u.
CAPITOLUL 13. ONI 2019 157

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.

13.3.1 Indicaµii de rezolvare


Descrierea unor solutii posibile

prof. Emanuela Cerchez, Colegiul National "Emil Racovita" Iasi

Solutia 1, prof. Emanuela Cerchez, Colegiul National "Emil Racovita" Iasi

In primul rand observam ca daca o comanda nu poate fi onorata la timp, putem sa o l


la final, pentru oricum nu vom primi valoarea ei. Deci comenzile neonorate la timp
toate plasate la sfarsitul planificarii optimale, nu conteaza in ce ordine.
Pierderea va fi suma valorilor acestor comenzi.
Ca urmare ne intereseaza in mod special lista comenzilor care pot fi onorate la tim
(sa o numim pe scurt Lista)
Observam de asemenea ca este convenabil sa onoram mai intai comenzile cele mai valo
deci vom ordona comenzile descrescator dupa valoare.
Vom parcurge comenzile in ordinea descrescatoare a valorii lor si pentru fiecare co
analizam daca o putem sau nu onora la timp. Pentru aceasta vom cauta o pozitie in L
in care comanda respectiva ar putea fi inserata (fara a afecta alte comenzi, adica
comenzilor existente deja in Lista trebuie sa ramana la timp, deoarece aceste comen
mai valoroase).
Daca o astfel de pozitie nu este gasita vom considera ca aceasta comanda este neono
Pentru a putea verifica daca inserarea este posibila, vom retine comenzile in Lista
ordinea crescatoare a timpului lor de predare. Parcurgem comenzile secvential in or
inversa si cautam pozitia in care putem insera comanda curenta, astfel incat Lista
ramana ordonata dupa timpul de predare, iar comenzile parcurse pot fi amanate cu ti
de predare al comenzii curente.
Deoarece este complicat sa lucram cu date si cu ore, chiar de la citire vom calcula
de predare in ore.

Solutie alternativa,

prof. Florentina Ungureanu, Colegiul National de Informatica, Piatra Neamt

Se declara un vector p cu maximum 366*24 elemente, pozitiile 1, 2, ... , 366*24/t


corespunzand perioadelor t, 2*t, 3*t s.a.m.d.

Se transforma timpii de finalizare ai comenzilor in ore si se retine pentru fiecare


intr-un camp nt numarul intreg de perioade t dupa care aceasta trebuie finalizata.

Se sorteaza descrescator dupa valoare comenzile.

Se parcurge sirul obtinut si pentru fiecare comanda v[i]:

- se verifica daca p[v[i].nt] este 0, caz in care aceasta se planifica executarea c


in perioada v[i].nt, iar p[v[i].nt] = v[i].nr (nr. initial al comenzii);

- daca p[v[i].nt] este diferit de 0, se cauta pozitia k (k din multimea {v[i].nt-1,


p[k]=0, caz in care se planifica executarea comenzii in perioada k, se bifeaza intr
boolean comenzile executate. in cazul nu se gaseste o pozitie k conform specificati
de mai sus, comanda ramane restanta;

- valoarea totala a comenzilor restante se determina scazand din valoarea totala a


valoarea fiecarei comenzi planificate;

- se afiseaza comenzile planificate parcurgand sirul p construit, iar cele restante


crescatoare a numarului initial (ordinea executarii acestora nefiind importanta).
CAPITOLUL 13. ONI 2019 158

13.3.2 *Rezolvare detaliat 

13.3.3 Cod surs 

Listing 13.3.1: venus_1.cpp

1 //Em. Cerchez 100


2 #include <fstream>
3 #include <cstring>
4
5 #define NMAX 1002
6
7 using namespace std;
8
9 ifstream fin("venus.in");
10 ofstream fout("venus.out");
11
12 char Luni[12][50]={"ianuarie","februarie", "martie", "aprilie" ,"mai","iunie",
13 "iulie","august","septembrie","octombrie","noiembrie","decembrie"};
14
15 int zl[12]={31,29,31,30,31,30,31,31,30,31,30,31};
16 int sz[12];
17
18 struct Comanda
19 {short int v, p, nr, tc; };
20 ///v = valoare
21 ///p=timpul pana la care trebuie predata comanda
22 ///nr de ordine al comenzii
23 ///tc=-1 daca comanda nu poate fi onorata la timp sau timpul curent de predare altfel
24 int n, lg, t;
25 Comanda C[NMAX];
26 int pmin;
27 int L[NMAX];
28
29 int main()
30 {int i, zi, ora, k, j, sch;
31 char luna[50];
32 Comanda aux;
33 fin>>n>>t;
34
35 for (i=1; i<12; i++) sz[i]=sz[i-1]+zl[i-1];
36 for (i=1; i<=n; i++)
37 {
38 fin>>C[i].v>>zi>>luna>>ora;
39 for (j=0; j<12; j++)
40 if (!strcmp(Luni[j],luna)) break;
41 C[i].p=(sz[j]+zi-1)*24+ora;
42 C[i].nr=i;
43 }
44
45 ///sortez descrescator comenzile dupa v
46 do
47 {sch=0;
48 for (i=1; i<n; i++)
49 if (C[i].v<C[i+1].v)
50 {
51 aux=C[i]; C[i]=C[i+1]; C[i+1]=aux;
52 sch=1;
53 }
54 }
55 while (sch);
56
57 for (i=1; i<=n && t>C[i].p; i++) C[i].tc=-1;
58
59 if (i<=n)
60 {L[1]=i; lg=1; C[i].tc=t;
61 for (i++; i<=n; i++)
62 {///verific daca pot onora la timp comanda C[i]
63 ///parcurg comenzile existente si verific care pot fi amanate
64 for (j=lg;
65 j>=1 && C[L[j]].tc+t<=C[L[j]].p && C[L[j]].p>=C[i].p;
CAPITOLUL 13. ONI 2019 159

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 }

Listing 13.3.2: venus_2.cpp

1 //Florentina Ungureanu 100


2 #include <fstream>
3 #include <cstring>
4 #include <algorithm>
5
6 using namespace std;
7
8 ifstream cin("venus.in");
9 ofstream cout("venus.out");
10
11 struct comanda
12 {
13 int nr, v, h,nt;
14 } v[1001];
15
16 char luni[][15]= {"","ianuarie","februarie","martie","aprilie","mai","iunie",
17 "iulie","august","septembrie","octombrie", "noiembrie", "decembrie"};
18
19 int n,m,p[8800],k,tlm,L[]= {0,31,29,31,30,31,30,31,31,30,31,30,31},mg,tot,t;
20 bool b[1001];
21
22 int lunaZ(char* luna)
23 {
24 int i=1;
25 while(strcmp(luni[i],luna)) i++;
26 return L[i-1];
27 }
28
29 bool comp(comanda x, comanda y)
30 {
31 return x.v>y.v;
32 }
33
34 int main()
35 {
36 int zi,l,j,i,dmax=0;
37 char luna[15];
38 cin>>n>>t;
39
40 for (int i=1; i<12; ++i)
41 L[i]+=L[i-1];
42
43 for (int i=1; i<=n; ++i)
44 {
CAPITOLUL 13. ONI 2019 160

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 SECVEN•E VIP din ³ir.
2. Lungimea minim  a unui ³ir de cifre care conµine acela³i num r de SECVEN•E 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 SECVEN•E 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 SECVEN•E 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 SECVEN•E 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 SECVEN•E VIP. Cel mai mic num r de cifre
413643623 dintr-un ³ir care conµine 6 SECVEN•E 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

Timp maxim de executare/test: 0.1 secunde


Memorie: total 8 MB din care pentru stiv  8 MB
Dimensiune maxim  a sursei: 10 KB

14.1.1 Indicaµii de rezolvare

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

Suma tuturor numerelor = < k 1


i 0 s ˜ 10 s ˜ 111...1
ÍÒÒ Ò Ò Ò Ò Ò Ò ÑÒÒ Ò Ò Ò Ò Ò Ò Ï
dekori
Cea mai mare sum  se obµine atunci când cel mai mare num r VIP conµine toate cele 9 cifre

s 
distincte (201599999798400)

Exemplu. Pentru mulµimea r1, 3, 4x, k < k


3, i 1 1  3  4 8 2˜1˜8 16
Suma tuturor numerelor = 16 ˜ 1  16 ˜ 10  16 ˜ 100 16 ˜ 111 1776

14.1.2 *Rezolvare detaliat 


CAPITOLUL 14. ONI 2018 163

14.1.3 *Cod surs 

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.

Timp maxim de executare/test: 0.2 secunde


Memorie: total 8 MB din care pentru stiv  8 MB
Dimensiune maxim  a sursei: 10 KB
CAPITOLUL 14. ONI 2018 164

14.2.1 Indicaµii de rezolvare

Metoda de programare utilizat  este Greedy.


Vom extrage cifrele num rului N ³i le vom plasa într-un vector.
Pentru a maximiza suma, în num rul x vom plasa câte cifre de 9 este posibil, cifrele din y ind
determinate astfel încât xy s  e N.
O atenµie special  trebuie s  acord m la determinarea primei cifre a lui x (care probabil nu va
mai  9) ³i la faptul c  y ar putea avea o cifr  mai puµin decât x.
Pentru xmin ymin proced m similar, doar c  plas m cifrele egale cu 9 în y ³i calcul m cifrele
din x.
Avem grij  îns  când ajungem la cifra dominant  s  o calcul m astfel încât cifra dominant 
din xmin s  e cât mai apropiat  de cifra dominant  din ymin (cu atenµie special  ca xmin s 
nu e mai mic decât ymin).
În problem  N este de tip long long int, dar algoritmul poate  cu u³urinµ  adaptat ³i pentru
numere mari.

14.2.2 *Rezolvare detaliat 

14.2.3 *Cod surs 

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

a 1 & N & 2 000 000 000


a 1 & M & 100 000
a 1 & K & 100 000
a Pentru teste valorând 30 de puncte, 1 & N, M, K & 1 000.
a 1&x&y & N, 1 & a & b & N
a Se garanteaz  c  ecare dintre cele N magazine are cel puµin un acµionar.
a Fiind foarte departe în viitor, observ m c  oamenii tr iesc mai mult, se deplaseaz  mai
repede, dar au ³i concedii mai lungi.

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

Timp maxim de executare/test: 1.3 secunde


Memorie: total 10 MB din care pentru stiv  10 MB
Dimensiune maxim  a sursei: 10 KB

14.3.1 Indicaµii de rezolvare

prof. Marius Nicoli, Colegiul Naµional Fraµii Buze³ti, Craiova

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.

14.3.2 *Rezolvare detaliat 


CAPITOLUL 14. ONI 2018 166

14.3.3 *Cod surs 


Capitolul 15

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

carte.in carte.out Explicaµii


1 3 2 Sunt maxim 3 c rµi de acela³i gen literar.
8 Sunt 2 genuri cu num r maxim de c rµi:
1289f5 { 128905, 129805, 219805 } ³i { 1e2, 12e, e21 }
128905
129805
219805
12
1e2
12e
e21
2 5 Sunt 5 coduri pereche cu 2189e5:
10 1289f5, 128905, 129805, 219805, 218905.
1289f5
128905
5
12
129805
219805
218905
132
312
2189e5

Timp maxim de executare/test: 2.0 secunde


Memorie: total 8 MB
Dimensiune maxim  a sursei: 15 KB

15.1.1 Indicaµii de rezolvare

prof. Pintea Adrian Doru, Colegiul Naµional Andrei Mure³anu DEJ

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).

15.1.2 *Rezolvare detaliat 

15.1.3 Cod surs 

Listing 15.1.1: carte.cpp

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

ghinde.in ghinde.out Explicaµii


1 29 Scart culege 10 ghinde de pe prima ramura, apoi 10 de pe a doua
3 10 3 ramura ³i alte 9 de pe a doua ramura, adic  10+10+9 = 29
13
19
4
2 23 20 Scratte: 10 de pe ramura a doua;
4 10 3 Scrat: 10 de pe ramura unu;
13 Scratte: 9 de pe ramura doi;
19 Scrat: 7 de pe ramura patru;
4 Scratte: 4 de pe ramura trei;
7 Scrat: 3 de pe ramura unu;
Scratte: 10+9+4=23
Scrat: 10+7+3=20

Timp maxim de executare/test: 0.7 secunde


Memorie: total 4 MB
Dimensiune maxim  a sursei: 15 KB

15.2.1 Indicaµii de rezolvare

prof. Mircea Rotar - Lic. Voc. Ped. N. Bolca³, Beiu³

Consider m M num rul maxim de ghinde culese la o tur .


A m câte ture se realizeaz  cu M ghinde culese la ecare tur . Pentru acest lucru la toate cele
N ramuri reµinem câtul dintre num rul de ghinde de pe ramur  ³i M, pe urm  însum m toate
aceste valori. Pentru ghindele r mase vom construi un vector de frecvenµe care reµine resturile
împ rµirii anterioare (restul împ rµirii dintre num rul de ghinde de pe ramur  ³i M) ³i le vom
distribui în ordine descresc toare a valorilor pentru resturi.

15.2.2 *Rezolvare detaliat 

15.2.3 Cod surs 

Listing 15.2.1: ghinde.cpp

1 ///prof. Rotar Mircea


2 #include <bits/stdc++.h>
3
4 using namespace std;
5
6 constexpr int Nmax=500005;
7 constexpr int Mmax=500005;
8
9 ifstream f("ghinde.in");
10 ofstream g("ghinde.out");
11
12 long long rez, nr, rez1, rez2;
13 int M, N, K, i, C, a[Mmax], j, x;
14
15 int main()
16 {
17 f>>C>>N>>M>>K;
18
19 for(i=1; i<=N; ++i)
20 {
21 f>>x;
22 nr += x/M;
23 a[x%M]++;
24 }
25
CAPITOLUL 15. ONI 2017 172

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).

Timp maxim de executare/test: 0.1 secunde


Memorie: total 256 MB din care pentru stiv  32 MB
Dimensiune maxim  a sursei: 15 KB

15.3.1 Indicaµii de rezolvare

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.

Pentru a determina submatricea cu num r maxim de elemente egale cu 1, x m o linie - e


ea linia i, apoi pentru toate liniile j, unde j ia valori de la i la n, calcul m num rul de elemente
egale cu 1 din submatricea aat  între liniile i si j ³i coloanele determinate de prima valoare cu
un elemente egal cu 1 de pe linia i ³i ultima coloan  cu un element egal cu 1 de pe coloana j care
este coloana anterioara primei coloane care conµine un 2. Aceste dou  coloane se deduc din datele
de intrare referitoare la linia i, respectiv la linia j.
2
Pentru încadrarea în timp pentru aceast  etap  a algoritmului, care are complexitatea O n ,
sunt necesare anumite optimiz ri care µin cont de dimensiunea submatricei de arie maxim  deter-
minat  pân  în acel moment ³i de particularit µile matricei.

15.3.2 *Rezolvare detaliat 


CAPITOLUL 15. ONI 2017 174

15.3.3 Cod surs 

Listing 15.3.1: submat_cpp.cpp

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

Timp maxim de executare/test: 0.2 secunde


Memorie: total 2 MB din care pentru stiv  2 MB
Dimensiune maxim  a sursei: 5 KB

16.1.1 Indicaµii de rezolvare

prof. Florentina Ungureanu, Colegiul Naµional de Informatic  Piatra-Neamµ

O soluµie se poate obµine astfel:


Se observ  c  nivelurile de ordin impar cu zidurile de lungime n ³i m (pe nivelul 1 m n) sunt
formate din n˜m birouri.
Pentru ecare nivel niv de ordin par:
- determin m k min n, m (n, m lungimile zidurilor de pe nivelul precedent), iar num rul
de birouri de pe acest nivel va  k ˜ k ©2  k ; dac  num rul de birouri obµinut este 0, nivelul nu
se va construi;
- dac  valoarea k este divizibil  cu patru, urm torul nivel va  de form  p tratic , cu lungimile
zidurilor n m k ©2, iar în caz contrar, lungimile zidurilor devin n n©2  1; m n©2  1.
Algoritmul se nalizeaz  când nu mai poate  construit un nivel nou.

16.1.2 *Rezolvare detaliat 

16.1.3 Cod surs 

Listing 16.1.1: ABbirouri.cpp

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

9 long long NrBirouri;


10 long long NrNiv;
11 long long n, lat, lun, drept, tmp;
12
13 int main()
14 {
15 short c;
16 int i, ok;
17 ifstream f(in);
18 f>>c>>n;
19 f.close();
20
21 NrNiv = NrBirouri = 0;
22 lat = n;
23 lun = n;
24 ok = 1;
25 drept = 1;
26 do
27 {
28 NrNiv++;
29 if(drept)
30 {
31 if(lun == lat)
32 {
33 if(lat % 2 == 1)
34 ok = 0;
35 NrBirouri += lat*lat;
36 lat /= 2; lun = lat;
37 }
38 else
39 {
40 NrBirouri += lat*lun;
41 if(lun < lat) tmp = lun, lun = lat, lat = tmp;
42 if(lat % 2 == 1 || lun % 2 == 1)
43 ok = 0;
44 lat /=2; lun = lat;
45 }
46 }
47 else
48 {
49 NrBirouri += 2*(lat-1)*lat;
50 if(lat % 2 == 1)
51 lat = lat - 1, lun = lun + 1;
52 }
53
54 drept = !drept;
55 if(lat == 1 || lun == 1)
56 ok = 0;
57 } while(ok);
58
59 ofstream g(ou);
60
61 if(c == 1)
62 g<<NrNiv<<endl;
63 else
64 g<<NrBirouri<<endl;
65
66 g.close();
67 return 0;
68 }

Listing 16.1.2: CSbirouri.cpp

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 }

Listing 16.1.3: FUbirouri.cpp

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).

Fiecare formaµiune este înconjurat  de jur-împrejur, ca în g.2, de un înveli³


special format ³i el din molecule identice, de alt tip decât cele din formaµiunea
cristalizabil  pe care o înconjoar  ³i o izoleaz  de restul formaµiunilor moleculare. În
acest fel, ecare molecul  din formaµiunea cristalizabil  se învecineaz  la N ord, Sud,
Est ³i V est cu o molecul  din aceea³i formaµiune cristalizabil  sau cu o molecul 
din înveli³ul special.

Fiecare formaµiune cristalizabil  se bombardeaz  cu raze X ³i în acest fel are loc


cristalizarea, proces prin care înveli³ul special se extinde peste formaµiunea crista-
lizabil  pe care o înconjoar , formând o singur  structur  din care se va dezvolta
cristalul.

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

cristale.in cristale.out Explicaµii


2 Se va rezolva cerinµa 1 a problemei.
E³antionul are 6 rânduri cu câte 8 molecule pe ecare
rând. Pe acest e³antion observ m o formaµiune crista-
lizabil  cu celule de tip 9, izolat  de înveli³ul special
format din celule identice, toate de tip 6 ³i o formaµiune
cristalizabil  cu celule de tip 7, izolat  de înveli³ul spe-
cial format din celule identice, toate de tip 4.
Formaµiunea de 3 molecule de tip 8 nu este o formaµiune
cristalizabil  întrucât se a  pe marginea e³antionului.
Se va rezolva cerinµa 2 a problemei.
Dup  cristalizare, peste ecare din cele dou  formaµiuni
cristalizabile identicate se extinde înveli³ul din jurul
lor.

Timp maxim de executare/test: 1.0 secunde


Memorie: total 1 MB din care pentru stiv  1 MB
Dimensiune maxim  a sursei: 10 KB

16.2.1 Indicaµii de rezolvare

prof. Cristina Iordaiche, Liceul Teoretic Grigore Moisil, Timi³oara

Identicarea unei formaµiuni cristalizabile presupune analizarea elementelor de pe patru rânduri


consecutive ale e³antionului. Astfel, datele pot  memorate într-un tablou bidimensional cu patru
linii ³i N coloane.

Acest tablou memoreaz  câte patru rânduri succesive din e³antion.

Se identic  apoi, ecare formaµiune cristalizabil , conform deniµiei din enunµ.

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 .

Pentru cerinµa 1 se num r  formaµiunile cristalizabile identicate iar pentru cerinµa 2, se


actualizeaz  valorile din tablou, conform fenomenului de cristalizare denit.

A³area tabloului se realizeaz  succesiv, linie cu linie, pe m sur  ce sunt actualizate valorile
acestuia.

16.2.2 *Rezolvare detaliat 

16.2.3 Cod surs 

Listing 16.2.1: ABcristale.cpp

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

88 if(c <= 2) A[i][j+1] = A[i+1][j+1] = A[i+1][j] = tmp;


89 }
90 }
91 }
92
93 if(c == 2)
94 {
95 for(j=1; j<=n; ++j)
96 g<<A[1][j]<<’ ’;
97 g<<’\n’;
98 }
99
100 for(i=2; i<=4; ++i)
101 for(j=1; j<=n; ++j)
102 A[i-1][j] = A[i][j];
103
104 for(j=1; j<=n; ++j)
105 f>>A[4][j];
106 cate--;
107 };
108
109 if(c == 1)
110 g<<NrC<<’\n’;
111 else
112 {
113 for(i=1; i<=3; i++)
114 {
115 for(j=1; j<=n; ++j)
116 g<<A[i][j]<<’ ’;
117 g<<’\n’;
118 }
119 }
120
121 f.close();
122 g.close();
123 return 0;
124 }

Listing 16.2.2: CIcristale.cpp

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

36 int f2(int li, int co)


37 {
38 int cp,cf;
39 cp=p[li][co];
40 cf=p[li][co-1];
41 if((cp==p[li][co+1])&&
42 (cp==p[li+1][co])&&
43 (cp!=cf)&&
44 (cf==p[li-1][co])&&
45 (cf==p[li-1][co+1])&&
46 (cf==p[li][co+2])&&
47 (cf==p[li+1][co+1])&&
48 (cf==p[li+2][co])&&
49 (cf==p[li+1][co-1]))
50 {
51 p[li][co]=p[li][co+1]=p[li+1][co]=cf;
52 return 1;
53 }
54
55 return 0;
56 }
57
58 int f3(int li, int co)
59 {
60 int cp,cf;
61 cp=p[li][co];
62 cf=p[li][co-1];
63 if((cp==p[li+1][co+1])&&
64 (cp==p[li+1][co])&&
65 (cp!=cf)&&
66 (cf==p[li-1][co])&&
67 (cf==p[li][co+1])&&
68 (cf==p[li+1][co+2])&&
69 (cf==p[li+2][co+1])&&
70 (cf==p[li+2][co])&&
71 (cf==p[li+1][co-1]))
72 {
73 p[li][co]=p[li+1][co+1]=p[li+1][co]=cf;
74 return 1;
75 }
76
77 return 0;
78 }
79
80 int f4(int li, int co)
81 {
82 int cp,cf;
83 cp=p[li][co];
84 cf=p[li][co-1];
85 if((cp==p[li+1][co])&&
86 (cp==p[li+1][co-1])&&
87 (cp!=cf)&&
88 (cf==p[li-1][co])&&
89 (cf==p[li][co+1])&&
90 (cf==p[li+1][co+1])&&
91 (cf==p[li+2][co])&&
92 (cf==p[li+2][co-1])&&
93 (cf==p[li+1][co-2]))
94 {
95 p[li][co]=p[li+1][co]=p[li+1][co-1]=cf;
96 return 1;
97 }
98
99 return 0;
100 }
101
102 void afis4_linii()
103 {
104 int i,j;
105 for(i=2;i<=2;i++)
106 {
107 g<<’\n’;//fprintf(g,"\n");
108 for(j=1;j<=n-1;j++)
109 g<<p[i][j]<<’ ’;//fprintf(g,"%d ",p[i][j]);
110
111 g<<p[i][n];//fprintf(g,"%d",p[i][n]);
CAPITOLUL 16. ONI 2016 185

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 }

Listing 16.2.3: CMcristale.cpp

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 }

Listing 16.2.4: CScristale.cpp

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

maxim de camere folosind întreaga cantitate de parchet.

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

Timp maxim de executare/test: 0.5 secunde


Memorie: total 2 MB din care pentru stiv  2 MB
Dimensiune maxim  a sursei: 5 KB
CAPITOLUL 16. ONI 2016 192

16.3.1 Indicaµii de rezolvare

Soluµie 1 (prof. Marinel “erban)


1. Se determin  suprafaµa ec rei camere.
2. Se ordoneaz  descresc tor vectorul care conµine suprafeµele camerelor.
3. Pentru prima cerinµ  se utilizeaz  un algoritm de tip umplerea rucsacului .
4. Pentru cerinµa a doua se utilizeaz  un algoritm pentru a determina o submulµime de sum 
dat  - se num r , evident, submulµimile de cardinal maxim. Algoritmul poate  de tip succesor,
care se poate implementa elementar, pe vector, sau utilizând operatorii pe biµi sau folosind tehnica
backtracking.

Soluµie 2 (prof. Alin Burµa)

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.

Pas 1. Se identic  prima poziµie liber  - neparchetat  - din tablou, e aceasta i, j 


Pas 2. Se parcheteaz  i, j , precum ³i poziµiile din dreapta, pân  la întâlnirea peretelui
(marc m acest fapt prin memorarea pe poziµiile parchetate a num rului camerei curente). Pe
parcurs, identic m prima pozµie liber  de pe linia urm toare, e acesta i  1, jj .
Pas 3. Dac  exist  o poziµie neparchetat  pe linia i  1, vom parcheta poziµia i  1, jj  precum
³i toate poziµiile libere din stânga ³i din dreapta acesteia, pân  la întâlnirea unui perete, aând
pe parcurs poziµia de unde va începe parchetarea poziµiilor de pe urm toarea linie. în acest mod
vom parcheta toate poziµiile libere începând cu linia i ³i pân  la peretele sudic al camerei curente.
Repet m pa³ii 1-3 pân  la parchetarea complet  a camerelor.

Î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.

16.3.2 *Rezolvare detaliat 

16.3.3 Cod surs 

Listing 16.3.1: ABparchet.cpp

1 //prof. Alin Burta


2 #include <fstream>
3 #include <cstring>
4 #include <iostream>
5
6 #define Nmax 252
7 #define in "parchet.in"
8 #define ou "parchet.out"
9
10 using namespace std;
11
12 unsigned int A[Nmax][Nmax], n, m, c, p, v;
13 unsigned int C[1001], ST[1001];
14 unsigned int S[1000]; // suprefetele camerelor
15 int x[21]; // pt. generare de submultimi
CAPITOLUL 16. ONI 2016 193

16 unsigned int cam; // cate camere am acoperit


17 unsigned int maxim, nrmaxim, NrCam;
18
19 void uneste(unsigned int a, unsigned int b)
20 {
21 unsigned int q, cop, t;
22 if (a > b)
23 cop = a, a = b, b = cop;
24 cop = b;
25 t = S[b] + S[a];
26
27 for(q = 1; q <= NrCam; ++q)
28 if(C[q] == cop)
29 C[q] = a;
30
31 for(q = 1; q <= NrCam; ++q)
32 if(C[q] == a)
33 S[q] = t;
34 }
35
36 int main()
37 {
38 char linie[Nmax];
39 unsigned int i,j, k, ok, ii, jj,t, nr;
40 unsigned int sup, pus, putere;
41
42 ifstream f(in);
43 f>>v>>n>>m>>p;
44 f.get();
45
46 sup = 0;
47 for(i=1; i<=n; ++i)
48 {
49 f.get(linie,m+1);
50 f.get();
51 //cout<<linie<<endl;
52 for(j=0; j<m; ++j)
53 if(linie[j] == ’P’)
54 A[i][j+1] = -1;
55 else
56 A[i][j+1] = 0;
57 }
58 f.close();
59
60 NrCam = 0;
61
62 //caut primul colt de camera neacoperit
63 for(i=1; i<=n-1; ++i)
64 for(j=1; j<=m-1; ++j)
65 if( A[i][j]==0 ) //am gasit un colt
66 {
67 //umplu linia cu nrcamerei
68 ok = 1;
69 NrCam++;
70 ii = i;
71 jj = j;
72 sup = 0;
73
74 while(ok)
75 {
76 ok = 0; //cout<<ii<<’ ’<<jj<<endl;
77 if( A[ii+1][jj] == 0) ok = jj ;
78
79 for(k=jj-1; A[ii][k]==0; k--)
80 {
81 if(A[ii][k] == 0)
82 A[ii][k] = NrCam, sup++;
83 if(A[ii+1][k] == 0)
84 ok = k;
85 }
86
87 for(k=jj+1; A[ii][k]==0; k++)
88 {
89 if(A[ii][k] == 0)
90 A[ii][k] = NrCam, sup++;
91 if(A[ii+1][k] == 0)
CAPITOLUL 16. ONI 2016 194

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 }

Listing 16.3.2: CSparchet.cpp

1 //prof. Cristina Sichim


2 #include <fstream>
3 #include <algorithm>
4
5 using namespace std;
6
7 ifstream f("parchet.in");
8 ofstream g("parchet.out");
9
10 int n,m,p,P,i,j,k,cate,numar;
11 char a[255][255];
12 int c[21],sum[21],nr[21],nrp,di[]={-1,0,1,0},dj[]={0,1,0,-1},cer;
13
14 void sterge(int i, int j)
15 {
16 int inou,jnou;
17 cate++;
18 a[i][j]=’P’;
19 for(int t=0;t<4;t++)
20 {
21 inou=i+di[t];
22 jnou=j+dj[t];
23 if(a[inou][jnou]==’S’)
24 sterge(inou, jnou);
25 }
CAPITOLUL 16. ONI 2016 196

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

102 while(k>0 && c[k]>P)


103 k--;
104 numara(1);
105 g<<cate<<’\n’;
106 }
107 }
108
109 f.close();
110 g.close();
111 return 0;
112 }

Listing 16.3.3: MSparchetBiti.cpp

1 //prof. Marinel Serban


2 #include <bits/stdc++.h>
3
4 using namespace std;
5
6 ifstream fin("parchet.in");
7 ofstream fout("parchet.out");
8
9 int Casa[255][255], Camere[210], N, M, S, nr_camere, Cerinta;
10
11 void Citire()
12 {
13 int i, j;
14 char X[255];
15
16 fin >> Cerinta;
17 fin >> N >> M; // dimensiuni casa
18 fin >> S; // suprafata parchet
19 fin.get(); // ENTER
20
21 for (i = 1; i <= N; ++i)
22 {
23 fin.getline(X, 255); //citesc o linie
24 for (j = 0; j < M; ++j)
25 Casa[i][j+1] = (X[j] == ’P’ ? -1 : 0);//-1 perete; 0 spatiu
26 }
27 }
28
29 int Suprafata(int l, int c, int nr)
30 {
31 struct element
32 {
33 short int lin, col;
34 } C[100000], X;
35
36 int dl[] = {-1, 0, 1, 0};
37 int dc[] = {0, 1, 0, -1};
38 int ic = 0, sc = -1, k, l9, c9, S = 1;
39
40 Casa[l][c] = nr;
41 sc++;
42 C[sc].lin = l;
43 C[sc].col = c;
44
45 while (ic <= sc)
46 {
47 X = C[ic++];
48 for (k = 0; k < 4; k++)
49 {
50 l9 = X.lin + dl[k];
51 c9 = X.col + dc[k];
52 if (Casa[l9][c9] == 0)
53 {
54 S++;
55 Casa[l9][c9] = nr;
56 sc++;
57 C[sc].lin = l9;
58 C[sc].col = c9;
59 }
60 }
61 }
CAPITOLUL 16. ONI 2016 198

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 }

Listing 16.3.4: MSparchetVector.cpp

1 //prof. Marinel Serban


2 #include <bits/stdc++.h>
3
4 using namespace std;
5
6 ifstream fin("parchet.in");
7 ofstream fout("parchet.out");
8
9 int Casa[255][255], Camere[210], N, M, S, nr_camere, Cerinta;
10
11 void Citire()
12 {
13 int i, j;
14 char X[255];
15
16 fin >> Cerinta;
17 fin >> N >> M; // dimensiuni casa
18 fin >> S; // suprafata parchet
19 fin.get(); // ENTER
20
21 for (i = 1; i <= N; ++i)
22 {
23 fin.getline(X, 255); // citesc o linie
24 for (j = 0; j < M; ++j)
25 Casa[i][j+1] = (X[j] == ’P’ ? -1 : 0);// -1 perete; 0 spatiu
26 }
27 }
28
29 int Suprafata(int l, int c, int nr)
30 {
31 struct element
32 {
33 short int lin, col;
34 } C[100000], X;
35
36 int dl[] = {-1, 0, 1, 0};
37 int dc[] = {0, 1, 0, -1};
38 int ic = 0, sc = -1, k, l9, c9, S = 1;
39
40 Casa[l][c] = nr;
41 sc++;
42 C[sc].lin = l;
43 C[sc].col = c;
44
45 while (ic <= sc)
46 {
47 X = C[ic++];
48 for (k = 0; k < 4; k++)
49 {
50 l9 = X.lin + dl[k];
51 c9 = X.col + dc[k];
52 if (Casa[l9][c9] == 0)
53 {
54 S++;
55 Casa[l9][c9] = nr;
56 sc++;
57 C[sc].lin = l9;
58 C[sc].col = c9;
59 }
60 }
61 }
62
63 return S;
64 }
65
66 void Suprafete_camere()
CAPITOLUL 16. ONI 2016 200

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

Linia reprezent rii lui 'A' are indicele 4. Cript-ul


caracterului 'A' este 100010004
Se procedeaz  analog pentru 'B'
2 VI 101110001-cript-ul caracterului 'V'
101110001111000002 111000002-cript-ul caracterului 'I'

Tabela 17.1: cript

Timp maxim de executare/test: 0.15 secunde


Memorie: total 2 MB din care pentru stiv  1 MB
Dimensiune maxim  a sursei: 10 KB

17.1.1 Indicaµii de rezolvare

prof. Lucia Miron - Colegiul C. Negruzzi Iasi

Soluµia 1 - (100 puncte)

Rezolvarea primei cerinµe, presupune simularea algoritmului de criptare descris în enunµul


problemei. Reprezentam pe 8 biµi, adic  în baza 2 codul ASCII al ecarui caracter din mesaj.
Memor m codul binar într-o matrice de caractere, memor m într-un vector ord, indicele ec rei
linii din matrice, ordon m lexicograc liniile matricei de caractere, construim cript-ul luând în
ordine caracterele ultimei coloane ³i poziµia în vectorul ord a valorii 0.

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

17.1.2 *Rezolvare detaliat 

17.1.3 Cod surs 

Listing 17.1.1: cript_emcerchez_100.cpp

1 //Emanuela Cerchez - 100 puncte


2 #include <fstream>
3 #include <cstring>
4 #include <cassert>
5
6 #define LGMAX 270001
7
8 using namespace std;
9
10 int c;
11 char s[LGMAX];
12
13 ifstream fin("cript.in");
14 ofstream fout("cript.out");
15
16 char M[8][9];
17 int ord[8];
18 char uc[9];
19
20 void criptare();
21 void decriptare();
22
23 int main()
24 {int lg;
25 fin>>c; fin.get();
26 assert(c==1 || c==2);
27 fin.getline(s,LGMAX);
28 lg=strlen(s);
29 if (c==1) {assert(lg<=30000); criptare();}
30 else {assert (lg<=270000 && lg%9==0);decriptare();}
31 fout<<’\n’; fout.close();
32 return 0;
33 }
34
35 void criptare()
36 {int i, j, k, aux, poz;
37 for (i=0; s[i]; i++)
38 { assert (s[i]>=32 && s[i]<=127);
39 for (j=7; j>=0; j--)
40 {M[0][j]=(s[i]&1)+’0’; s[i]>>=1;}
41 for (k=1; k<8; k++)
42 {for (j=0; j<7; j++) M[k][j]=M[k-1][j+1];
43 M[k][7]=M[k-1][0];}
44 for (k=0; k<8; k++) ord[k]=k;
45 for (k=0; k<8; k++)
46 for (j=k+1; j<8; j++)
47 if (strcmp(M[ord[k]],M[ord[j]])>0)
48 {aux=ord[k]; ord[k]=ord[j]; ord[j]=aux;}
49 for (k=0; k<8; k++)
50 for (j=k+1; j<8; j++)
51 if (strcmp(M[ord[k]],M[ord[j]])==0&&ord[k]>ord[j])
52 {aux=ord[k]; ord[k]=ord[j]; ord[j]=aux;}
53 for (k=0; k<8; k++)
54 {fout<<M[ord[k]][7];
55 if (!ord[k]) poz=k;}
56 fout<<poz;
57 }
58 }
59
60 void decriptare()
61 {int i, j, poz, nr0, cod;
62 char *q;
63 for (i=0; s[i]; i++)
64 { nr0=0; cod=0;
65 for (j=0; j<8; j++, i++)
CAPITOLUL 17. ONI 2015 205

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 }

Listing 17.1.2: cript_LuciaMiron.cpp

1 //Lucia Miron, 100 puncte


2 #include <fstream>
3 #include<cstring>
4
5 using namespace std;
6
7 ifstream fin("cript.in");
8 ofstream fout("cript.out");
9
10 char s[30001], ss[10],t[270001],css;
11 int c,i,j;
12
13 void cript(char c, char cod[10])
14 {
15 int n,ord[10],ax,i,j;
16 char s[10][10],aux[10];
17
18 n=c;
19 for(i=7; i>=0; i--)
20 {
21 s[0][i]=’0’+n%2;
22 n=n/2;
23 }
24
25 s[0][8]=’\0’;
26 for(i=1;i<=7;i++)
27 {
28 for(j=0;j<7;j++)
29 s[i][j]=s[i-1][j+1];
30 s[i][7]=s[i-1][0];
31 s[i][8]=’\0’;
32 }
33
34 //ordonez lexicografic sirul s[]
35 for(i=0; i<=7; i++)
36 ord[i]=i;
37
38 for(i=0; i<7; i++)
39 for(j=i+1; j<=7; j++)
40 if(strcmp(s[i],s[j])>0)
41 {
42 strcpy(aux,s[i]);
43 strcpy(s[i],s[j]);
44 strcpy(s[j],aux);
45 ax=ord[i];
46 ord[i]=ord[j];
47 ord[j]=ax;
48 }
49
50 for(i=0; i<7; i++)
51 for(j=i+1; j<=7; j++)
52 if(strcmp(s[i],s[j])==0&&ord[i]>ord[j])
53 {
54 strcpy(aux,s[i]);
55 strcpy(s[i],s[j]);
CAPITOLUL 17. ONI 2015 206

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 }

Listing 17.1.3: cript_odumitrascu.cpp

1 //sursa cript Octavian Dumitrascu - 100 puncte


2 #include <fstream>
3 #include <cstring>
4 #include <algorithm>
5
6 #define LGMAX 300001
7
8 using namespace std;
9
10 int s, i, p, n, j, k, r , y , z, q, t, q1, a[15];
11 char sir[ 30005 ], b[15];
12 char cript[ 300005 ];
13 char sol_char[140][15];
14 int sol[140];
15
16 ifstream fin("cript.in");
17 ofstream fout("cript.out");
18
19 int main()
20 {
21 char caracter;
22 fin>>p; fin.get(caracter);
23 for ( i = 32 ; i <= 127 ; i++)
24 {
25 z = y = i ;
26 if (i == 65)
27 i = i;
28
29 for (j = 0; j < 8; j++)
30 {
31 a[ j ] = y;
32 r = y / 128;
33 y = ( y << 1 )%256 + r;
34 }
35
36 sort (a, a + 8);
37
38 for (j = 0; j < 8; j++)
39 if (a[ j ] == z)
40 {
41 q = j;
42 break;
43 }
44
45 q1 = q;
46 q = (q << 8);
47 s = 0;
48 for (j = 0; j < 8; j++)
49 {
50 s = s * 2 + (a[ j ] & 1);
51 if ( (a[ j ] & 1) == 0)
52 b[ j ] = ’0’;
53 else
54 b[ j ] = ’1’;
55 }
56
57 sol[ i ] = s + q;
58 b[ 8 ] = q1 + 48;
59 b[ 9 ] = ’\0’;
60 strcpy(sol_char[i], b);
61 }
62
63 if (p == 1)
64 {
65 fin.getline(sir, LGMAX);
66 n = strlen(sir);
67 for (i = 0; i < n; i++)
68 {
69 fout<<sol_char[ sir[ i ] ];
70 }
71 }
CAPITOLUL 17. ONI 2015 208

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 }

Listing 17.1.4: cript_rcostineanu_100.cpp

1 //Raluca Costineanu 100 puncte


2 #include <fstream>
3 #include <cstring>
4
5 using namespace std;
6
7 ifstream f("cript.in");
8 ofstream g("cript.out");
9
10 int c;
11 char s[9*30001];
12 int codif[200][10];
13
14 int cmp(int a[10],int b[10])
15 {
16 int i;
17 for(i=0;i<8;i++)
18 if(a[i]<b[i])
19 return -1;
20 else
21 if(a[i]>b[i])
22 return 1;
23 return 0;
24 }
25
26 void codific(char c, int cod[10])
27 {
28 int x=c, i, j, a[10][10];
29
30 for(i=7; i>=0; i--)
31 {
32 a[0][i]=x%2;
33 x=x/2;
34 }
35
36 for(i=1; i<=7; i++)
37 {
38 for(j=0;j<7;j++)
39 a[i][j]=a[i-1][j+1];
40 a[i][7]=a[i-1][0];
41 }
42
43 int nr[10], aux, k;
44
45 // for(i=0;i<=7;i++)
46 // {for(j=0;j<8;j++)
47 // g<<a[i][j];
48 // g<<’\n’;}
CAPITOLUL 17. ONI 2015 209

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

125 for(i=0; s[i]; i++)


126 {
127 for(j=0;j<=8;j++)
128 g<<codif[s[i]][j];
129 //g<<’\n’;
130 }
131 }
132 else
133 {
134 int n=strlen(s), i, j;
135 int cod[10];
136 char codul[10];
137
138 for(i=32; i<=127; i++)
139 {
140 codific(char(i), cod);
141 for(j=0;j<9;j++)
142 codif[i][j]=cod[j];
143 }
144
145 for(i=0;i<n;i=i+9)
146 {
147 strncpy(codul, s+i, 9);
148 codul[9]=0;
149 for(j=0;j<9;j++)
150 cod[j]=codul[j]-’0’;
151 g<<decodific(cod);
152 }
153 }
154
155 return 0;
156 }

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)

Timp maxim de executare/test: 0.1 secunde


Memorie: total 2 MB din care pentru stiv  1 MB
Dimensiune maxim  a sursei: 10 KB

17.2.1 Indicaµii de rezolvare

prof. Emanuela Cerchez, Colegiul Naµional "Emil Racoviµ " Ia³i

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).

17.2.2 *Rezolvare detaliat 

17.2.3 Cod surs 

Listing 17.2.1: scadere_100_emcerchez.cpp

1 //Emanuela Cerchez 100 puncte


2 #include <fstream>
3 #include <cstring>
4
5 #define NMAX 5001
6 #define LGMAX 40001
7 #define INF 1000000000
8
9 using namespace std;
10
11 ifstream fin("scadere.in");
12 ofstream fout("scadere.out");
13
14 char s[LGMAX], snr[10];
15 int x[NMAX];
16 int st[LGMAX];
17 int n, cerinta;
18 int rez;
19 void sir(int x);
20 int evalexp();
21
22 int main()
23 {int i, nrp=0;
24 fin>>cerinta>>n;
25 for (i=1; i<=n; i++) fin>>x[i];
26 if (cerinta==1)
27 {
28 rez=x[1]-x[2];
29 for (i=3; i<=n; i++)
30 if (x[i]>=0) rez+=x[i];
31 else rez-=x[i];
32 fout<<rez<<’\n’;
33 fout<<"x1-";
34 for (i=3; i<=n; i++)
35 {
36 if (x[i]>=0)
37 {if (nrp%2==0)
38 {fout<<"("; nrp++;}
39 }
40 else
41 {if (nrp%2)
42 {fout<<"("; nrp++;}
43 }
44 fout<<"x"<<i-1<<"-";
45 }
46 fout<<"x"<<n;
47 for (i=0; i<nrp; i++) fout<<")";
48 fout<<’\n’;
49 fout.close();
50 return 0;}
51
52 fin>>s;
53 rez=evalexp();
54 fout<<rez<<’\n’;
55 fout.close();
56 return 0;
57 }
CAPITOLUL 17. ONI 2015 213

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 }

Listing 17.2.2: scadere_100_odumitrascu.cpp

1 //scaderi sursa Octavian Dumitrascu 100 puncte


2 #include <cstdio>
3 #include <cstring>
4
5 using namespace std;
6
7 int m, t, nr_minus, paranteze, q, j, p, i, s, n, s1, start, stop,
8 x[ 5005 ], semn[ 5005 ], y[ 5005 ], st[ 5005 ];
9 char sir[ 40005 ];
10
11 int main()
12 {
13 freopen("scadere.in", "r", stdin);
14 freopen("scadere.out", "w", stdout);
15
16 scanf("%d\n",&p);
17 scanf("%d\n", &n);
18 for (i = 1; i <= n; i++)
19 scanf("%d\n",&x[ i ]);
20
21 if (p == 1)
22 {
23 s = x[1];
24 start = 2;
25 stop = 2;
26 s1 = 0;
27 j=2;
28
29 for (i = 2; i <= n; i++)
30 if (x[ i ] > 0)
31 {
32 s1 -= x[ i ];
33 stop ++;
34 }
35 else
36 {
37 j = i - 1;
38 break;
39 }
40
41 if (i > n)
42 {
43 semn[start] = 1;
44 semn[stop] = -1;
45 s = s - s1 - 2 * x[2];
46 }
47 else
CAPITOLUL 17. ONI 2015 214

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

Timp maxim de executare/test: 0.2 secunde


Memorie: total 4 MB din care pentru stiv  2 MB
Dimensiune maxim  a sursei: 10 KB

17.3.1 Indicaµii de rezolvare

Octavian Dumitra³cu, Colegiul Naµional "Dinicu Golescu" Câmpulung Muscel

Vom transforma timpii în secunde.


Vom construi un vector h cu 24x60x60 componente. Pentru ecare moment de timp vom reµine
în hi=num rul de posturi care încep s  emit  publicitate la momentul i.
Pentru ecare interval de timp din list  incep, sf  (unde sf incep  d) vom incrementa
hincep hsf .
³i voi decrementa
Suma elementelor de la 1 la x reprezint  câte posturi transmit publicitate la momentul x.
Soluµia este optim  având complexitate O N .

17.3.2 *Rezolvare detaliat 


CAPITOLUL 17. ONI 2015 217

17.3.3 Cod surs 

Listing 17.3.1: tv_odumitrascu_100.cpp

1 //Octavian Dumitrascu - 100 puncte


2 #include <cstdio>
3 #include <algorithm>
4 #include <cstring>
5
6 using namespace std;
7
8 int sf, liber, yy, m1, s1, h1, d, c, ss, n, ma, p,
9 timp, start, stop, i, h[100005];
10 char s[10];
11
12 int main()
13 {
14 freopen("tv.in", "r", stdin);
15 freopen("tv.out", "w", stdout);
16
17 scanf("%d\n%d\n", &p, &n);
18
19 for (i=1; i<=n; i++)
20 {
21 scanf("%d ",&d);
22 gets(s);
23 h1=(s[0]-48)*10+s[1]-48;
24 m1=(s[3]-48)*10+s[4]-48;
25 s1=(s[6]-48)*10+s[7]-48;
26 start = s1 + m1*60 + h1*60*60;
27 stop = start + d;
28 h[start]++;
29 h[stop]--;
30 }
31
32 ss = 0;
33 liber = 0;
34 ma = 0;
35 for (i = 0; i < 60*60*24; i++)
36 {
37 ss += h[i];
38 if (ss > ma)
39 {
40 ma = ss;
41 timp = i;
42 }
43
44 if (ss == 0)
45 liber++;
46 }
47
48 if (p == 1)
49 yy = liber;
50 else
51 yy = timp;
52
53 strcpy(s,"");
54 h1 = yy/3600;
55 m1 = yy%3600/60;
56 s1 = yy%60;
57 s[0]=h1/10+48;
58 s[1]=h1%10+48;
59 s[2]=’:’;
60 s[3]=m1/10+48;
61 s[4]=m1%10+48;
62 s[5]=’:’;
63 s[6]=s1/10+48;
64 s[7]=s1%10+48;
65 s[8]=’\0’;
66
67 printf("%s\n", s);
68
69 return 0;
70 }
Capitolul 18

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

Timp maxim de executare/test: 2.0 secunde


Memorie: total 16 MB din care pentru stiv  16 MB
Dimensiune maxim  a sursei: 10 KB
218
CAPITOLUL 18. ONI 2014 219

18.1.1 Indicaµii de rezolvare

???-???

Consider m ³irul numerelor citite memorat în vectorul A1..N . Algoritmul construie³te în


O N un vector St1..N , în care elementul Sti memoreaz  indicele celui mai apropiat element
mai mare decât Ai situat în vectorul A de la poziµia 1..i  1. În mod identic în urma unei noi
parcurgeri a vectorului A, se va construi vectorul Dr 1..N , în care elementul Dr i memoreaz 
indicele celui mai apropiat element mai mare decât Ai situat în vectorul A de la poziµia i  1..N .

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.

Pentru exemplicare vom construi vectorul St pentru vectorul iniµial A 2, 7, 4, 8, 6.


Not m cu nr , num rul de elemente din vectorul candidaµilor Cnd. Când indicele i este introdus
în vectorul Cnd, toate elementele ai caror indici sunt deja salvaµi vor  extrase dac  sunt mai mici
decât Ai. Operaµia se realizeaz  decrementând valoare indicelui nr atâta timp cât ACndnr  &
Ai. La nal, Cndnr  1 reprezint  indicele primului element mai mare decât Ai. Iniµializ m
Cnd0 1.
Pentru asta vom gestiona vectorul Cnd astfel:

A1 2 este plasat în vectorul Cnd1 1, nr 1. Elementul St1 1 deoarece nu are


element mai mare situat în stânga lui.

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.

Acesta conµine acum indicii 2, 3. Deasemenea St3 Cnd1 2.


A4 8, acest element este mai mare decât ambele elemente aate în Cnd, deci le va extrage
pe toate. Vectorul Cnd va conµine doar indicele (4). Fiind plasat pe prima poziµie ³tim c 
St4 1 deoarece nu are element mai mare situat în stânga lui.
A5 6, acesta poate reprezenta maximul unui element aat dup  el, deci este salvat în Cnd
pe poziµia a doua. Vectorul Cnd conµine acum indicii 4, 5. Deasemenea St5 Cnd1 4.
Astfel indicele celui mai apropiat maxim din stânga este primul element din Cnd care nu a fost
extras la introducerea lui 5.

18.1.2 *Rezolvare detaliat 

18.1.3 Cod surs 

Listing 18.1.1: codat_mn.cpp

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 }

Listing 18.1.2: codat_patratic.cpp

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 }

Listing 18.1.3: codat_stack.cpp

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)

Cifrele romane sunt scrise cu majusculele M, D, C, L, X, V, I, iar valorile corespunz toare


lor sunt în ordine: 1000, 500, 100, 50, 10, 5, 1. Valoarea unui num r scris cu cifre romane se
calculeaz  parcurgând de la stânga la dreapta cifrele num rului astfel:
- cifra curent  se adun  la valoarea obµinut  pân  în acel moment, dac  cifra urm toare este
mai mic  sau egal  cu ea;
- cifra curent  se scade din valoarea obµinut  pân  în acel moment, dac  cifra urm toare este
mai mare decât ea;
- ultima cifr  se adun  întotdeauna la valoarea obµinut  pân  în acel moment.

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)

Cuvintele mesajului decodicat, în ordinea din poveste, sunt:


La Olimpiada comisia decide prima
CAPITOLUL 18. ONI 2014 224

Timp maxim de executare/test: 0.5 secunde


Memorie: total 2 MB din care pentru stiv  2 MB
Dimensiune maxim  a sursei: 10 KB

18.2.1 Indicaµii de rezolvare

??? - ???

Denesc o structur  care s  reµin  pagina, rândul, poziµia cuvântului pe rând.


Denesc un tablou de tipul structurii descrise mai sus, care va reµine pentru ecare cod, pagina,
rândul ³i num rul cuvântului de pe rând.
Citim primul num r din ³ier, care reprezint  cerinµa, apoi citim pe rând urm toarele trei linii
din ³ierul de date, care conµin respectiv paginile, rândurile ³i num rul cuvântului pe linie.

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];

La sfâr³it adun m ultima cifr .

Memor m numerele astfel obµinute în tablou.

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.

18.2.2 *Rezolvare detaliat 

18.2.3 Cod surs 

Listing 18.2.1: nod.cpp

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 }

Listing 18.2.2: nod_dl_pct1_2.cpp

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

55 char x[1000], *p;


56 p=strtok(s," ");
57
58 while (p)
59 {
60 strcpy(x,p);
61 V[++n]=NrRo(x);
62 p=strtok(NULL," ");
63 }
64 }
65
66 bool cmp(tag a, tag b)
67 {
68 if(a.pg < b.pg) return true;
69 if(a.pg == b.pg && a.rd<b.rd) return true;
70 if(a.pg == b.pg && a.rd==b.rd && a.cv<b.cv) return true;
71 return false;
72 }
73
74 int main()
75 {
76 freopen("nod.in", "r", stdin);
77 freopen("nod.out", "w", stdout);
78
79 scanf("%d\n", &test);
80 gets(Pag);
81
82 int x=strlen(Pag);
83
84 for(int t=0; t<x; t++)
85 assert(strchr(romane,Pag[t]));
86
87 PuneNr(P, np, Pag);
88 gets(Rand);
89 x=strlen(Rand);
90
91 for(int t=0; t<x; t++)
92 assert(strchr(romane,Rand[t]));
93
94 PuneNr(R,nr,Rand);
95 gets(Cuv);
96 x=strlen(Cuv);
97
98 for(int t=0; t<x; t++)
99 assert(strchr(romane,Cuv[t]));
100
101 PuneNr(C,nc,Cuv);
102
103 for(i=1; i<=np; i++)
104 {
105 L[i].pg=P[i];
106 L[i].rd=R[i];
107 L[i].cv=C[i];
108
109 }
110
111 assert(np>=1&&np<=20);
112
113 if(test==1)
114 {
115 for(i=1; i<=np;i++)
116 {
117 printf("%d", L[i].pg);
118 if(i<np)
119 printf(" ");
120 else
121 printf("\n");
122 }
123
124 for(i=1; i<=np;i++)
125 {
126 printf("%d", L[i].rd);
127 if(i<np)
128 printf(" ");
129 else
130 printf("\n");
CAPITOLUL 18. ONI 2014 229

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 }

Listing 18.2.3: nod_dt_ok.cpp

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

Timp maxim de executare/test: 0.5 secunde


Memorie: total 32 MB din care pentru stiv  32 MB
Dimensiune maxim  a sursei: 10 KB

18.3.1 Indicaµii de rezolvare

prof. Marius Nicoli, C.N. Fraµii Buze³ti, Craiova

Se memoreaza num rul total de 1 de pe ecare coloan  într-un verctor V. Pentru ecare


poziµie i calcul m maxS i ca ind cea mai mare valoare din V aat  între poziµiile 1 ³i i. De
asemenea, calcul m maxD i = cea mai mare valoare din V care se g se³te între poziµiile i ³i N.
Cei 2 vectori se calculeaz  printr-un algoritm de determinare a maximului dintr-un vector.
Pentru o secvenµ  K xat  începând cu poziµia i, în lµimea pl cii r mase dup  eliminarea
secvenµei este cea mai mare dintre valorile maxS i  1 ³i maxDi  K . Stabilind începutul
secvenµei în ecare poziµie posibil  determin m valoarea Hmin cerut  la prima cerinµ .

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

18.3.2 *Rezolvare detaliat 

18.3.3 Cod surs 

Listing 18.3.1: placa.cpp

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 }

Listing 18.3.2: placa1.cpp

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 }

Listing 18.3.3: placa2.cpp

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 }

Listing 18.3.4: placa3.cpp

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 }

Listing 18.3.5: placa4.cpp

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 }

Listing 18.3.6: placa5.cpp

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 }

Listing 18.3.7: placa6.cpp

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 }

Listing 18.3.8: placa8.cpp

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 }

Listing 18.3.9: placa10.cpp

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

secvp.in secvp.out Explicaµii


7 3 9 Pentru a transforma 15 în num r prim sunt necesare 2 incremen-
15 3 8 26 22 10 14 3 2 t ri
Pentru a transforma 3 în num r prim sunt necesare 0 operaµii
Pentru a transforma 8 în num r prim e necesar  1 decrementare
Pentru a transforma 26 în num r prim sunt necesare 3 decremen-
t ri
Pentru a transforma 22 în num r prim e necesar  1 incrementare
Pentru a transforma 10 în num r prim e necesar  1 incrementare
Pentru a transforma 14 în num r prim e necesar  1 decrementare
Num rul total de operaµii necesare este 9.
Num rul minim de operaµii necesare pentru a obµine o secvenµ  de
lungime K este 3.
Cele dou  secvenµe de lungime K ce necesit  3 operaµii sunt a1 ,
a2 , a3 ³i a5 , a6 , a7 .

Timp maxim de executare/test: 0.5 secunde


Memorie: total 4 MB din care pentru stiv  4 MB
Dimensiune maxim  a sursei: 15 KB

19.1.1 Indicaµii de rezolvare

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.

19.1.2 *Rezolvare detaliat 

19.1.3 Cod surs 

https://infogenius.ro/problema-secvp-oni-2013-clasa-7/

Listing 19.1.1: secvp.cpp

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

23 for (int i = 0; ; i++)


24 if (!sieve[x - i] || !sieve[x + i])
25 return i;
26 }
27
28 /// Ciurul lui Eratostene
29 void erat()
30 {
31 int i, j;
32 sieve[0] = sieve[1] = true;
33
34 for (i = 2; i * i <= NRMAX; i++)
35 if (!sieve[i])
36 for (j = i * i; j <= NRMAX; j += i)
37 sieve[j] = true;
38 }
39
40 /// Functia care citeste datele si rezolva prima cerinta
41 void read()
42 {
43 int i, x, MinInc, sum = 0;
44 erat();
45
46 fin >> n >> k;
47 for (i = 1; i <= n; i++)
48 {
49 fin >> x;
50 MinInc = minInc(x);
51 inc[i] = MinInc;
52 sum += MinInc;
53 }
54
55 fout << sum << ’\n’;
56 }
57
58 /// Functia care rezolva a doua cerinta
59 void solve()
60 {
61 int i, u, apMin, sumMin, sum = 0;
62
63 // Calculam suma primelor k elemente:
64 for (i = 1; i <= k; i++)
65 sum += inc[i];
66
67 sumMin = sum;
68 apMin = 1;
69
70 // u reprezinta indicele ultimului element
71 // al secventei curente, iar sum suma
72 // elementelor acesteia.
73
74 for (u = k + 1; u <= n; u++)
75 {
76 // Actualizam sum in O(1):
77 sum += inc[u] - inc[u - k];
78
79 if (sum < sumMin)
80 {
81 sumMin = sum;
82 apMin = 1;
83 }
84 else
85 if (sum == sumMin)
86 apMin++;
87 }
88
89 fout << sumMin << ’ ’ << apMin << ’\n’;
90 fout.close();
91 }
92
93 int main()
94 {
95 read();
96 solve();
97 return 0;
98 }
CAPITOLUL 19. ONI 2013 247

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

Timp maxim de executare/test: 0.1 secunde


Memorie: total 2 MB din care pentru stiv  2 MB
Dimensiune maxim  a sursei: 10 KB

19.2.1 *Indicaµii de rezolvare

19.2.2 *Rezolvare detaliat 


CAPITOLUL 19. ONI 2013 248

19.2.3 *Cod surs 

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.

Figura 19.1: cursa

Î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 depǎ³ite î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).

Timp maxim de executare/test: 0.1 secunde


Memorie: total 4 MB din care pentru stiv  4 MB
Dimensiune maxim  a sursei: 10 KB

19.3.1 *Indicaµii de rezolvare

19.3.2 *Rezolvare detaliat 

19.3.3 *Cod surs 


Capitolul 20

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

bile.in bile.out Explicaµii


6 7 5 8
2 3 0
2 5 10
4 2 0
4 4 9
5 6 0
4 8
6
4
5
8
3
5

Timp maxim de executare/test: 0.1 secunde


Memorie: total 8 MB din care pentru stiv  8 MB
Dimensiune maxim  a sursei: 5 KB

20.1.1 Indicaµii de rezolvare

prof. Nistor Moµ

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.

20.1.2 *Rezolvare detaliat 

20.1.3 Cod surs 

Listing 20.1.1: bile.cpp

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

a 1 & M & 200;


a 1 & N & 1000000;
a 1 & nri & 200000 1 & i & M ;
a 1 & M ˜ nri & 320000 1 & i & M ;
a 1 & fk & N , 1 & k & nri ;
a exist  întotdeauna cel puµin un proiect coordonat de o rm .

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

Timp maxim de executare/test: 0.2 secunde


Memorie: total 1 MB din care pentru stiv  1 MB
Dimensiune maxim  a sursei: 5 KB

20.2.1 Indicaµii de rezolvare

Prof. Lucia Miron

Soluµia are complexitate O M ˜ max nri ; 1 & i & M


Putem descompune problema în dou  subprobleme ³i anume:

a) Pentru început trebuie s  determin m pentru ecare proiect, dac  exist , rma care îl
coordoneaz ,

b) Trebuie s  determin m toate rmele care coordoneaz  num rul maxim de proiecte

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.

Pentru determinarea elementului majoritar utiliz m urm toul algoritm:

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.

Pentru a rezolva a doua subpoblem , pe m sura ce determin m un elemnt majoritar îl vom


ad uga la vectorul de rme coordonatoare, dac  este primul proiect coordonat de aceasta sau
increment m num rul de proiecte coordonat de aceasta, dac  apare deja în vectorul V (not m cu
V vectorul de rme coordonatoare ³i cu NR vectorul cu num rul de proiecte coordonate).

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 .

20.2.2 *Rezolvare detaliat 

20.2.3 Cod surs 

Listing 20.2.1: proiecte1.cpp

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 }

Listing 20.2.2: proiecte2.cpp

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

Figura 20.1: zigzag

2. Se iau caracterele pe linii ³i se formeaz  mesajul codicat: ODTL EAIIA MCMDIRAPA-


NOIF

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

Timp maxim de executare/test: 0.1 secunde


Memorie: total 2 MB din care pentru stiv  1 MB
Dimensiune maxim  a sursei: 5 KB

20.3.1 Indicaµii de rezolvare

prof. Daniel Popa

Pentru a decodica mesajul se creeaz  un vector de decodicare. Se completeaz  o matrice


(cu c linii ³i cu n div (c-1)+1 coloane) cu numerele de ordine exact a³a cum ar trebui puse
literele ³i se parcurge pe linii, obµinându-se astfel vectorul de decodicare. Pentru a reduce spaµiul
de memorie necesar NU se completeaz  efectiv o matrice ci doar se deduc regulile de completare:
1. Pe prima coloana vom avea numerele de la 1 la c
2. Pe coloana a doua se pun pe primele c1 linii diferenµa dintre2 ˜ c ³i num rul liniei
3. Pe celelalte coloane dac  sunt pare se pune valoarea 2*c-i+(j-2) div 2 *dt, unde
dt 2 ˜ c  2, altfel se pune valoarea i+(j-1) div 2*dt.
Este posibil ca unele din aceste valori calculate s  e peste valoarea lui n ³i atunci nu se
folosesc.
1 7 13 19
2 6 8 12 14 18 20
3 5 9 11 15 17 21
4 10 16 22

20.3.2 *Rezolvare detaliat 

20.3.3 Cod surs 

Listing 20.3.1: zigzag.cpp

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:

Figura 21.1: joc

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

Timp maxim de executare/test: 1.0 secunde

21.1.1 Indicaµii de rezolvare

prof. Roxana Tîmplaru - Liceul de Informatic  “tefan Odobleja Craiova

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.1.2 *Rezolvare detaliat 

21.1.3 *Cod surs 

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:

Figura 21.2: mesaj

Litera cerut  este F ³i mesajul codicat este:


SAAO T PTDMCOAANCU DNIICL LFALIIEASMA REINAO

Timp maxim de executare/test: 1.0 secunde

21.2.1 Indicaµii de rezolvare

prof. Florin Moldovanu - Colegiul Naµional Roman Vod  Roman

- 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.2.2 *Rezolvare detaliat 


CAPITOLUL 21. ONI 2011 262

21.2.3 *Cod surs 

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 L˜C 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).

Timp maxim de executare/test: 1.0 secunde

21.3.1 Indicaµii de rezolvare

prof. Marius Nicoli, CN Fraµii Buze³ti - Craiova

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 .

21.3.2 *Rezolvare detaliat 

21.3.3 *Cod surs 


Capitolul 22

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).

Timp maxim de executare/test: 1.0 secunde


264
CAPITOLUL 22. ONI 2010 265

22.1.1 Indicaµii de rezolvare

Popescu Anastasiu Doru - profesor Colegiul Naµional Radu Greceanu Slatina


'index[person]Doru Popescu Anastasiu

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.

22.1.2 *Rezolvare detaliat 

22.1.3 Cod surs 

Listing 22.1.1: CHAR.CPP

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).

Timp maxim de executare/test: 1.0 secunde

22.2.1 Indicaµii de rezolvare

prof. Cristina Iordaiche, Liceul Grigore Moisil Timi³oara

Se parcurge traseul dat ³i pentru ecare semafor se determin  culoarea pe


care o are acesta în momentul în care po³ta³ul a ajuns în dreptul lui.
Dac  semaforul are culoarea:
a verde, po³ta³ul trece mai departe
a galben sau ro³u, se calculeaz  num rul de secunde r mase pân  când
acesta î³i va schimba culoarea în verde
a tocmai s-a schimbat din verde în ro³u, se a³teapt  8s pân  se face din nou
verde ³i se poate trece mai departe
a tocmai s-a schimbat din galben în verde, se trece mai departe

22.2.2 *Rezolvare detaliat 

22.2.3 Cod surs 

Listing 22.2.1: MARATON.CPP

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 }

Listing 22.2.2: MARAton2.CPP

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

Timp maxim de executare/test: 1.0 secunde

22.3.1 Indicaµii de rezolvare

prof. Tîmplaru Roxana - profesor Liceul de Informatic  “tefan Odobleja Craiova

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)

22.3.2 *Rezolvare detaliat 

22.3.3 Cod surs 


CAPITOLUL 22. ONI 2010 272

Listing 22.3.1: Roboti.cpp

1 // Implementare Simoiu Robert - 100 pct. Traducere Pascal -> C++


2 #include <cstdio>
3
4 const char FIN[] = "roboti.in";
5 const char FOU[] = "roboti.out";
6 const int MAX = 55;
7
8 int m, n, nr, l, c;
9 int x[MAX], y[MAX], tr[MAX][MAX];
10 char ori[MAX], depl[MAX][MAX];
11 bool exista[MAX];
12
13 void date()
14 {
15 int i;
16
17 scanf("%d %d\n", &l, &c);
18 scanf("%d\n", &n);
19 nr = n;
20 for (i = 1; i <= n; i++)
21 {
22 scanf("%d %d %c\n", &x[i], &y[i], &ori[i]);
23 tr[x[i]][y[i]] = 1;
24 exista[i] = 1;
25 }
26
27 scanf("%d\n", &m);
28 for (i = 1; i <= n; i++)
29 fgets(depl[i] + 1, MAX , stdin);
30 }
31
32 void miscare_l(char c, char *c_nou)
33 {
34 switch ( c )
35 {
36 case ’E’ :
37 *c_nou = ’N’;
38 break ;
39 case ’V’ :
40 *c_nou = ’S’;
41 break ;
42 case ’S’ :
43 *c_nou = ’E’;
44 break ;
45 case ’N’ :
46 *c_nou = ’V’;
47 break ;
48 }
49 }
50
51 void miscare_r(char c, char *c_nou)
52 {
53 switch ( c )
54 {
55 case ’E’ :
56 *c_nou = ’S’;
57 break ;
58 case ’V’ :
59 *c_nou = ’N’;
60 break ;
61 case ’S’ :
62 *c_nou = ’V’;
63 break ;
64 case ’N’ :
65 *c_nou = ’E’;
66 break ;
67 }
68 }
69
70 void miscare_f(int l, int c, char ch, int *l_nou, int *c_nou)
71 {
72 switch ( ch )
73 {
74 case ’E’ :
CAPITOLUL 22. ONI 2010 273

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

151 int main()


152 {
153 freopen(FIN,"r",stdin);
154 freopen(FOU,"w",stdout);
155
156 date(), deplasare(), afisare();
157
158 return 0;
159 }
275
Anexa A

Un pic de matematic !

A.1 ...

A.1.1 Prezentare general 

...

A.1.2 Exemple

...

276
Anexa B

Un pic de programare!

B.1 ...

B.1.1 Prezentare general 

...

B.1.2 Exemple

...

277
Glosar

³menul lui Mars, 165 operatori pe biµi, 192


ordonare lexicograc, 202
32768, 177

permutare circular , 202


algoritm de sortare, 251
algoritm de tip umplerea rucsacului, 192
recursivitate, 9, 10, 15
algoritm de tip succesor, 192
algoritmi de umplere, 192
scriere în baza 2, 247
algoritmi recursivi, 192
sortare, 165
stiv , 211
baza 2, 168
strchr, 232
bordare matrice, 3
strcpy, 232
c utare binar , 165, 233 strlen, 232
cifra dominant , 164 strtok, 232
ciurul lui Eratostene, 245 sume parµiale, 165
cod ASCII, 202, 256
tehnica backtracking, 192
divizori, 16 tip long long int, 164
trage cu tunul, iv
getline, 232
Greedy, 164
vector de frecvenµe, 168, 171

I.d.k.: vector de structuri, 263

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

[4] Atanasiu, A.; Concursuri de informatic . Editura Petrion, 1995

[5] Bell D., Perr M.; Java for Students, Second Edition, Prentice Hall, 1999

[6] Calude C.; Teoria algoritmilor, Ed. Universit µii Bucure³ti, 1987

[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

[14] Erickson J.; Combinatorial Algorithms; http://www.uiuc.edu/~jeffe/

[15] Flanagan, D.; Java in a Nutshell, O'Reilly, 1997.

[16] Giumale C., Negreanu L., C linoiu S.; Proiectarea ³i analiza algoritmilor. Algoritmi de sortare,
Ed. All, 1997

[17] Halim S., Halim F., Competitive programming, 2013

[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

[23] Laaksonen A.; Guide to competitive programming, Springer, 2017

[24] Livovschi, L.; Georgescu H.; Analiza ³i sinteza algoritmilor. Ed. Enciclopedic , Bucure³ti,
1986.

[25] Niemeyer, P., Peck J.; Exploring Java, O'Reilly, 1997.

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

[29] R bâea, A.;


https://math.univ-ovidius.ro/Doc/Admitere/CentruPregatire/
2007/Info/Lista_probleme_2000-2007.pdf
[30] R bâea, A.;
https://math.univ-ovidius.ro/Doc/Admitere/CentruPregatire/
2007/Info/Rezolvari_C09.pdf

[31] R bâea, A.;


https://math.univ-ovidius.ro/Doc/Admitere/CentruPregatire/
2007/Info/Rezolvari_C10.pdf
[32] R bâea, A.;
https://math.univ-ovidius.ro/Doc/Admitere/CentruPregatire/
2007/Info/Rezolvari_C11.pdf

[33] R bâea, A.;


https://math.univ-ovidius.ro/Doc/Admitere/CentruPregatire/
2007/Info/Rezolvari_Baraj.pdf
[34] Skiena S.S., Revilla M.A.; Programming challenges - The Programming Contest Training
Manual, Springer, 2003

[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

[39] V duva, C.M.; Programarea in JAVA. Microinformatica, 1999

[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

[42] Vlada, M.; Grafuri neorientate ³i aplicaµii. Gazeta de Informatic , 1993

[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.

[45] Winston, P.H., Narasimhan, S.; On to JAVA, Addison-Wesley, 1996

[46] Wirth N.; Algorithms + Data Structures = Programs, Prentice Hall, Inc 1976

[47] *** - Gazeta de Informatic , Editura Libris, 1991-2005

[48] *** -
https://github.com/DinuCr/CS/blob/master/Info/stuff%20stuff/Re
zolvari_C09.pdf
[49] *** - https://dokumen.tips/documents/rezolvaric09.html

[50] *** - https://www.scribd.com/doc/266218102/Rezolvari-C09


[51] *** - https://www.scribd.com/document/396362669/Rezolvari-C10
[52] *** - https://www.scribd.com/document/344769195/Rezolvari-C11
[53] *** - https://www.scribd.com/document/364077679/Rezolvari-C11-pdf

[54] *** - https://needoc.net/rezolvari-c11-pdf


BIBLIOGRAFIE 281

[55] *** - https://vdocumente.com/algoritmi-i-structuri-de-date.html


[56] *** -
https://pdfslide.net/documents/algoritmi-si-structuri-de-date-
1-note-de-cuprins-1-oji-2002-clasa-a-ix-a-1-11.html
[57] *** - https://www.infoarena.ro/ciorna

[58] *** - https://infoarena.ro/olimpici


[59] *** - https://www.infogim.ro/
[60] *** - https://www.pbinfo.ro/

[61] *** - http://www.cplusplus.com/


[62] *** - http://www.cplusplus.com/doc/tutorial/operators/
[63] *** - http://www.info1cup.com/
[64] *** - http://www.olimpiada.info/

[65] *** - http://www.usaco.org/


[66] *** - http://algopedia.ro/
[67] *** - http://campion.edu.ro/
[68] *** - http://varena.ro/
[69] *** - http://rmi.lbi.ro/rmi_2019/
[70] *** - https://codeforces.com/
[71] *** - https://cpbook.net/
[72] *** - https://csacademy.com/
[73] *** - https://gazeta.info.ro/revigoram-ginfo/
[74] *** - https://oj.uz/problems/source/22
[75] *** - https://profs.info.uaic.ro/~infogim/2019/index.html
[76] *** - https://wandbox.org/
[77] *** - https://en.cppreference.com/w/cpp/language/operator_alternative
[78] *** - https://en.cppreference.com/w/cpp/algorithm

[79] *** - https://www.ejoi2019.si/


[80] *** - https://en.wikipedia.org/wiki/Algorithm
[81] *** - https://en.wikipedia.org/wiki/List_of_algorithms
[82] *** - https://en.wikipedia.org/wiki/List_of_data_structures
Lista autorilor
problemelor ³i indicaµiilor

Alin Burµa, 192 Lucia Miron, 203, 253

Carmen Minc , 3, 65 Maria Niµ , 145


Costineanu Raluca, 54 Marinel “erban, 192
Cristina Iordaiche, 138, 181, 268 Marius Nicoli, 37, 100, 165, 233, 263
Cristina Sichim, 68 Mircea Rotar, 171

Dana Lica, 45 Nicu Vad Laurenµiu, 83


Daniel Popa, 257 Nistor Moµ, 121, 251

Emanuela Cerchez, 30, 74, 108, 117, 157, Octavian Dumitra³cu, 203, 216
211
Eugen Nodea, 111 Pintea Adrian Doru, 168

Filonela Balasa, 23 Roxana Tîmplaru, 129, 135, 260, 271


Flavius Boian, 16
Florentina Ungureanu, 152, 177 Sanda Junea, 93
Florin Moldovanu, 261 Stelian Ciurea, 173

282

S-ar putea să vă placă și