Documente Academic
Documente Profesional
Documente Cultură
date la olimpiade
în
2020
2019 2018 2017 2016 2015
2014 2013 2012 2011 2010
2009 2008 2007 2006 2005
2004 2003 2002 2001 2000
la clasa a 9-a
9 decembrie 2020
Dedicaµie
1
to myself ...
in a time when ...
I will not be able ...
2
to be.
3
When I Die Nobody Will Remember Me
1
I Dedicate This Book to Myself By Carol Lynne
2
To be, or not to be ..., Hamlet, Act III, Scene I, William Shakespeare, 1564-1616
3
https://www.youtube.com/watch?v=eMtcDkSh7fU
ii
Prefaµ
Stilul acestor c rµi este ... ca ³i cum a³ vorbi cu nepoµii mei (³i chiar cu mine însumi!) ... încercând
împreun s g sim o rezolvare cât mai bun pentru o problem dat la olimpiad .
Ideea, de a scrie aceste culegeri de probleme date la olimpiadele de informatic , a ap rut acum
câµiva ani când am întrebat un student (care nu reu³ea s rezolve ni³te probleme foarte simple):
Ce te faci dac un elev, care ³tie c e³ti student ³i c studiezi ³i informatic , te roag , din când în
când, s -l ajuµi s rezolve câte o problem de informatic dat la gimnaziu la olimpiad , sau pur
³i simplu ca tem de cas , ³i tu, aproape de ecare dat , nu îl poµi ajuta? Eu cred c nu este prea
bine ³i poate c ... te faci ... de râs! Pe vremea mea (!), când eram elev de gimnaziu, un student
era ca un fel de ... zeu! Cu trecerea anilor am înµeles c nu este chiar a³a! i înc ceva: nu am
reu³it s înµeleg de ce, atunci când cineva nu poate s rezolve corect o problem de informatic
de clasa a 6-a, dat la olimpiada de informatic sau ca tem de cas , folose³te aceast scuz : eu
nu am f cut informatic în liceu! ³i acest cineva este zeul sau zeiµa despre care vorbeam!.
4
Sunt convins c este important s studiem cu atenµie cât mai multe probleme rezolvate! Cred
cred c sunt utile ³i primele versiuni în care sunt prezentate chiar ³i numai enunµurile ³i indicaµiile
"ociale" de rezolvare. Acestea se g sesc în multe locuri; aici încerc s le pun pe toate la un loc !
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 ).
11
O mic observaµie: în 2017 a fost prima ediµie a olimpiadei EJOI î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.
10
https://www.top500.org/lists/top500/
11
https://ejoi.org/about/
12
https://stats.ioinformatics.org/olympiads/
13
https://en.wikipedia.org/wiki/International_Mathematical_Olympiad
14
https://www.etsy.com/listing/604809336/john-wayne-quotes-i-am-only-responsible
"Acknowledgements"
15
"I want to thank God most of all because without God I wouldn't be able to do any of this."
Adrian R.
15
I.d.k.: "I don't know who the author is."
v
Despre autor16
nume: R bâea Aurel-Adrian, 18.03.1953 - ...
adresa: Str. Valea Ghinzii nr. 21 B, Bistriµa, România
telefon: +40 728 18 03 53 +40 363 10 25 10
email: adrian1803@gmail.com
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,
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 xxi
Lista tabelelor xxiii
Lista programelor xxiv
2 OJI 2019 36
2.1 abx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
2.1.2 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
2.1.3 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
2.2 deminare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
2.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
2.2.2 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2.2.3 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
2.3 mostenire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
2.3.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
2.3.2 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
2.3.3 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
3 OJI 2018 63
3.1 Cuf r . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
3.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
3.1.2 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
3.1.3 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.2 fadema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
3.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
3.2.2 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
3.2.3 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
vii
3.3 tnia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
3.3.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
3.3.2 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
3.3.3 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
4 OJI 2017 77
4.1 Ace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
4.1.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
4.1.2 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
4.1.3 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
4.2 Admitere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
4.2.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
4.2.2 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
4.2.3 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
4.3 Roboµi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
4.3.1 Indicaµii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
4.3.2 Cod surs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
4.3.3 *Rezolvare detaliat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
xxi
34.2 Pereµi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 716
34.3 Zumzi1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 727
34.4 Zumzi2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 728
34.5 Zumzi3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 732
34.6 Zumzi4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 732
xxiii
Lista programelor
1.1.1 buldoMN_scanf.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.2 buldo_GM.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1.3 buldo_invers_PA_.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1.4 buldo_MD.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1.5 buldo_nlognBD_Bun.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.1.6 buldoMN.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.1.7 buldonlognMN.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.1 cetate_optim_ocial_bogdan_scanf.c . . . . . . . . . . . . . . . . . . . . . . . . 10
1.2.2 cetate_GM.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.2.3 cetate_MD2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.2.4 cetate_optim_1_bogdan.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.2.5 cetate_optim_ocial_bogdan.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.2.6 cetateBFixColMN.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.2.7 cetateMN.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.2.8 fast_unocial_alexandru.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.2.9 fastest_unocial_alexandru.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.3.1 spiral_matrix45pBD.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
1.3.2 spiral_matrix75pBD.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.3.3 spiralmatrix45p.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.3.4 spiralmatrix75p.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.3.5 spiralmatrix90pV1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.3.6 spiralmatrix90pV2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
1.3.7 spiralmatrix90pV3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
1.3.8 spiralmatrixMNo(n).cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
2.1.1 abx_EN_90.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
2.1.2 abx_LB_90.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
2.1.3 abx_LB_hybrid.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
2.1.4 abx_LB_hybrid_fast.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
2.1.5 abx_LB_stable.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
2.1.6 abx_NM.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
2.2.1 deminare_CC3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2.2.2 deminare_EN.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
2.2.3 deminare_GM.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
2.2.4 deminare_LB.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
2.2.5 deminare_MP.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
2.3.1 mostenire_LB.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
2.3.2 mostenire_MLT.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
2.3.3 mostenire_MP.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
3.1.1 cufar-100p.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
3.1.2 cufar-dani-100p.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.2.1 fadema_n6.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
3.2.2 fadema_n4.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
3.2.3 fadema_n3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
3.2.4 fadema_n2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
3.3.1 bruteQN2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
3.3.2 bruteN2+Q.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
3.3.3 bruteQN.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
3.3.4 sursa-dani-NlogN.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.1.1 ace_LS.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
xxiv
4.1.2 ace_MirelaM.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
4.1.3 ace_priv.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
4.1.4 ace_prmc.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
4.1.5 ace_tavi.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
4.2.1 mihai100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
4.2.2 mihai100comments.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
4.2.3 priv100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
4.3.1 roboti_luci.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
4.3.2 roboti_luci_wosort.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
4.3.3 roboti_priv.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
4.3.4 roboti_prmc.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
5.1.1 CC1_cifre.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
5.1.2 CP_cifre.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
5.1.3 MLT_cifre.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
5.2.1 pic_CP1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
5.2.2 picMD.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
5.2.3 picMLT1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
6.1.1 arc1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
6.1.2 arc2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
6.1.3 arc3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
6.1.4 arc4.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
6.2.1 defrag1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
6.2.2 defrag2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
6.2.3 defrag3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
6.2.4 defrag4.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
6.2.5 defrag5.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
6.2.6 defrag6.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
7.1.1 CC2_cool.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
7.1.2 cool_eugen_fs.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
7.1.3 cool_eugen_std.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
7.1.4 cool_n2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
7.2.1 pseudobil.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
7.2.2 pseudobil_EN_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
7.2.3 pseudobil_LS_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
7.2.4 pseudobil2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
8.1.1 beta_CM1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
8.1.2 beta_CM2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
8.1.3 beta_CM3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
8.1.4 beta_GB.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
8.1.5 beta_ZS.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
8.2.1 CC_clepsidru.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
8.2.2 MR_clepsidru.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
8.2.3 PD_clepsidru.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
8.2.4 ZS_clepsidru.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
9.1.1 elicopCC.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
9.1.2 elicopDPA.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
9.1.3 elicopGB.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
9.2.1 roataCC.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
9.2.2 roataPC.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
10.1.1 v1_vase.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
10.1.2 v2_vase.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
10.1.3 v3_vase.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
10.2.1 cri_fstream-100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
10.2.2 cricpp1-100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
10.2.3 cricpp2-100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
10.2.4 cricpp3-100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
11.1.1 livada.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
11.1.2 livada_v2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
11.2.1 numar_v1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
13.1.1 concurs.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
13.2.1 pluricex.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
14.1.1 carteleC.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
14.1.2 cartele1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
14.1.3 cartele2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
14.1.4 cartele3.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
14.2.1 PARITATE.C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
14.2.2 Paritate.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
15.1.1 FLORI.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
15.1.2 ori1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
15.1.3 ori2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
15.2.1 PLUTONC.C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
15.2.2 PLUTCARM.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
15.2.3 PLUTRADU.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
15.2.4 pluton1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
15.2.5 pluton2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
16.1.1 numere.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
16.1.2 numere.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
16.2.1 MaxD1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254
16.2.2 MaxD2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
17.1.1 EXP.PAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
17.1.2 Expresie1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
17.1.3 Expresie2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
17.1.4 Expresie3.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
17.2.1 REACT_QS.PAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
17.2.2 REACTIVI.C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266
17.2.3 reactivp.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
17.2.4 reactivi.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
18.1.1 TEXT.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
18.1.2 text.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
18.2.1 numere.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
18.2.2 numere.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
19.1.1 poarta.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
19.2.1 mouce.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
21.1.1 alex-nnlog.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
21.1.2 alex-nqlog.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
21.1.3 amat_eugen.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294
21.1.4 brut.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296
21.1.5 brut_IQ_9000 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
21.1.6 chiorean_amat.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298
21.1.7 solution.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300
21.1.8 sursa_test.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
21.2.1 comun_back.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
21.2.2 comun_chiorean.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
21.2.3 comun_eugen.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
21.2.4 comun_io.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
21.2.5 comun_nlog_sub.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309
21.2.6 comun_sol.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
21.2.7 sol_nlog.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
21.3.1 pro3_AT1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
21.3.2 pro3_CC1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
21.3.3 pro3_CC2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317
21.3.4 pro3_LB1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
21.4.1 cub_chiorean.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
21.4.2 cub_chiorean_brut.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
21.4.3 cub_chiorean_n3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
21.4.4 cub100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
21.4.5 cub100_int.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
21.5.1 bofrac_CC1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
21.5.2 bofrac_CC2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
21.5.3 bofrac_CC3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328
21.5.4 bofrac_CC4.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
21.5.5 bofrac_CC5.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
21.5.6 bofrac_TC1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
21.6.1 alex.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
21.6.2 telefon-adrian-100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
21.6.3 telefon-bicsi-100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336
21.6.4 tudor_telefon_v2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
22.1.1 1_bazaf.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
22.1.2 2_bazaf.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
22.1.3 3_bazaf.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
22.1.4 4_bazaf.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
22.2.1 mexitate1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
22.2.2 mexitate2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
22.3.1 plaja_N+K.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355
22.3.2 plaja_ternara.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
22.3.3 plaja1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
22.3.4 plaja2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358
22.3.5 plaja3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
22.3.6 plaja4.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
22.4.1 bsrec.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
22.4.2 bsrec2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365
22.5.1 1_numinum_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368
22.5.2 2_numinum_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
22.6.1 rosiimici.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
22.6.2 rosiimici2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
23.1.1 arhipelag_100p_1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
23.1.2 arhipelag_100p_2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380
23.2.1 mirror_100p_1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383
23.2.2 mirror_100p_2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
23.2.3 mirror_100p_3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388
23.2.4 mirror_100p_4.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
23.2.5 mirror_100p_5.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
23.2.6 mirror_100p_6.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
23.3.1 okcpp_97p.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
23.3.2 okcpp_100p_1_doar_linux.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . 400
23.3.3 okcpp_100p_2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
23.4.1 adlic_100p_1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
23.4.2 adlic_100p_2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406
23.4.3 adlic_100p_3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
23.5.1 bomboane_100p_1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410
23.5.2 bomboane_100p_2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
23.5.3 bomboane_100p_3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413
23.6.1 orase_100p.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
24.1.1 civilizatie_BICSI.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422
24.1.2 civilizatie100p.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424
24.2.1 cmmdc_BICSI.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
24.3.1 livada_dan.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
24.3.2 Livada100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431
24.4.1 dif2_bicsi.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435
24.4.2 dif2_eric.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436
24.4.3 dif2_N_log2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437
24.5.1 leduri_bicsi.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
24.5.2 leduri_eric.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441
24.6.1 omogene_eric.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444
24.6.2 omogene_n_4.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445
24.6.3 omogeneMG.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446
25.1.1 cubul_cp1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451
25.1.2 cubul_cp2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
25.1.3 cubul_gcc_2matrici.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
25.1.4 cubul_gcc_umplere_ciur.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . 460
25.1.5 cubul_mot_e.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 462
25.2.1 risc.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467
25.2.2 risc_n2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468
25.2.3 risc_nlogn.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470
25.3.1 roboti_aib.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474
25.3.2 roboti_dp.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
25.3.3 roboti_greedy.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476
25.4.1 casa.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480
25.4.2 casa_slow.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483
25.4.3 casa2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484
25.5.1 lenes.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 488
25.5.2 lenes2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 491
25.5.3 lenes3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494
25.6.1 sipet.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498
26.1.1 harta.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502
26.1.2 harta_Adriana.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504
26.1.3 harta_brut_1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 506
26.1.4 harta_brut_2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508
26.1.5 harta_eugen.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
26.1.6 harta_pit.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
26.1.7 harta1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 512
26.2.1 qvect_eugen_bf.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 516
26.2.2 qvect_eugen_fs.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517
26.2.3 qvect_eugen_std.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 518
26.2.4 qvect_inter.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519
26.2.5 qvect_mink.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521
26.2.6 qvect_qsort.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523
26.2.7 qvect_qsortscanf.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524
26.2.8 qvect_vs.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 526
26.3.1 tg_100p.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 530
26.3.2 tg_on.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531
26.3.3 tg_on_v2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531
26.3.4 tg_on2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532
26.3.5 tg_onsqrtn.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532
26.4.1 CC2_progresie.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
26.4.2 CC3_progresie.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
26.4.3 CM_progresie.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536
26.4.4 EN_progresie.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536
26.4.5 PIT_progresie.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537
26.4.6 SP_progresie.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537
26.5.1 reex_eugen.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 540
26.5.2 reex_LS_brut.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541
26.5.3 reex_LS_Euclid_100p.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542
26.5.4 reex_LS_med.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543
26.5.5 reex_LS_Sr_100p.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544
26.5.6 reex_vs.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545
26.6.1 traseu_carmen_nerec.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548
26.6.2 traseu_carmen_rec.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550
26.6.3 traseu_eugen.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551
26.6.4 traseu_vspit.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 553
27.1.1 aranjare.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 556
27.2.1 gradina.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 558
27.3.1 split.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560
27.4.1 momente.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 564
27.5.1 secvente.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 567
27.6.1 spider.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 570
28.1.1 PIT_7segmente.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 574
28.1.2 CC_7segmente.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575
28.1.3 RH_7segmente.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
28.2.1 PIT_copaci.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 579
28.2.2 RH_copaci.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 580
28.2.3 VI_copaci.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581
28.3.1 PIT1_intersectii.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583
28.3.2 PIT2_intersectii.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 584
28.3.3 brut_intersectii.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
28.3.4 GM_intersectii.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
28.3.5 VI_intersectii.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586
28.4.1 CTpalindrom.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 589
28.4.2 RHpalindrom.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 591
28.4.3 VIpalindrom.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 593
28.5.1 PRIVsstabil_1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 597
28.5.2 PRIVsstabil_2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 598
28.5.3 VI_sstabil.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 598
28.6.1 GMunuab_100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600
28.6.2 GMunuab_back.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
28.6.3 GMunuab_n patrat.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
28.6.4 VI_unuzero.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 602
29.1.1 poligon.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 605
29.2.1 stalpi.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608
29.3.1 tort.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 612
29.4.1 ape.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 614
29.5.1 ec.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 616
29.6.1 furnici.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 620
30.1.1 cern100v1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623
30.1.2 cern100v2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 625
30.2.1 cmmmc60.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 628
30.2.2 cmmmc100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 630
30.3.1 simetric20.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633
30.3.2 simetric40.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 634
30.3.3 simetric100.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635
30.4.1 pesti.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 637
30.5.1 plaja.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 640
30.6.1 tango.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 642
31.1.1 joc.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 646
31.2.1 perspic.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649
31.3.1 rafturi.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 652
31.4.1 br.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655
31.5.1 origami.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 657
31.6.1 patrate.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 660
32.1.1 ab.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 663
32.2.1 iepuras.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 666
32.3.1 palind.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 669
32.3.2 palindvxn.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 670
32.3.3 palindvxv.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 671
32.4.1 auto.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 673
32.4.2 autonk.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 674
32.5.1 div_rares.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676
32.6.1 teatru.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 678
32.6.2 teatru_n2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 679
32.6.3 teatru_n3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 680
33.1.1 agitatie.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 684
33.2.1 coduri.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 686
33.3.1 lacuri.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 690
33.4.1 secv.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 693
33.5.1 sotron.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 696
33.6.1 triunghi.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 698
34.1.1 fact.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 701
34.1.2 factok.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 702
34.1.3 fact.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 703
34.2.1 limbaj.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 705
34.2.2 limbaj1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 707
34.2.3 limbaj2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 709
34.3.1 panouri.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712
34.3.2 panouri1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 713
34.3.3 panouri2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 714
34.4.1 pereti.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 717
34.4.2 peretiok.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 718
34.4.3 pereti.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 719
34.5.1 sant.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 722
34.5.2 sant1.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 723
34.5.3 sant.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 726
34.6.1 zumzi.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 729
34.6.2 zumzi1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 732
34.6.3 zumzi2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 734
35.1.1 bifo0.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 740
35.1.2 bifo1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 741
35.1.3 bifo2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 742
35.2.1 romeo.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 747
35.3.1 seceta1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 749
35.3.2 seceta2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 751
35.3.3 seceta3.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 753
35.3.4 seceta4.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 754
35.4.1 biblos1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 757
35.4.2 biblos2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 758
35.4.3 biblos3.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 759
35.5.1 joc.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 761
35.6.1 pal.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 766
36.1.1 COD_OK.PAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 770
36.1.2 CODURI.PAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 771
36.1.3 coduri.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 772
36.2.1 logic.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 774
36.2.2 logic0.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 775
36.2.3 logic1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 776
36.2.4 logic2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 778
36.3.1 poligon.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 780
36.3.2 poligon.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 782
36.4.1 sablon.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 786
36.4.2 sablon0.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 787
36.4.3 sablon1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 788
36.5.1 sir.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 789
36.5.2 sir.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 790
36.6.1 snipers.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 791
36.6.2 snipers.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 793
37.1.1 seti.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 796
37.1.2 seti0java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 796
37.1.3 seti1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 798
37.2.1 scaune.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 800
37.2.2 scaune1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 801
37.2.3 scaune2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 802
37.3.1 ALLCIRC.C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 805
37.3.2 Circback.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 806
37.3.3 CIRCULAR.C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 807
37.3.4 circular1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 808
37.3.5 circular2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 809
37.4.1 criptare.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 811
37.4.2 criptare1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 812
37.4.3 criptare2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 813
37.5.1 masina.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 815
37.6.1 operatii.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 817
38.1.1 pentagon.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 820
38.1.2 pentagon.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 821
38.2.1 PODBACK.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 824
38.2.2 PODDBIG.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 825
38.2.3 PODIN.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 826
38.2.4 pod1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 827
38.2.5 pod2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 829
38.2.6 pod3.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 830
38.3.1 suma.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 834
38.3.2 suma.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 834
38.3.3 becuri1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 838
38.3.4 becuri2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 840
38.3.5 becuri3.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 841
38.4.1 discuri.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 845
38.4.2 discuri.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 845
38.5.1 cod.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 848
38.5.2 codcomb.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 849
38.5.3 cod.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 849
39.1.1 ferma1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 852
39.1.2 ferma2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 853
39.2.1 fractii.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 855
39.3.1 tablou1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 856
39.3.2 tablou2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 857
39.4.1 competitie.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 859
39.5.1 cuvinte.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 860
39.6.1 grup.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 863
40.1.1 Algoritm-oc.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 866
40.1.2 algoritm1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 867
40.1.3 algoritm.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 869
40.2.1 cod2.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 870
40.2.2 cod-oc.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 872
40.2.3 cod1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 872
40.2.4 cod2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 873
40.2.5 cod3.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 874
40.3.1 comoara-oc.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 876
40.3.2 comoara.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 878
40.4.1 cuburi-oc.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 881
40.4.2 cuburi.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 882
40.5.1 sb.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 884
40.5.2 sbmare.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 885
40.5.3 bo.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 886
40.6.1 KMIHAI.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 889
40.6.2 KOM_MEU.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 890
40.6.3 Kommando-oc.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 891
40.6.4 VERKOMM.pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 893
40.6.5 kommando1.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 894
40.6.6 kommando2.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 895
40.6.7 kommando3.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 896
40.6.8 kommando4.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 898
Partea I
1
Capitolul 1
OJI 2020
1.1 buldo
Problema 1 - buldo 100 de puncte
Dore³ti s nivelezi terenul pe care l-ai cump rat, care are l µimea de 1 metru ³i lungimea de
N metri, ind alc tuit din N zone succesive, ecare zon având lungimea de 1 metru.
Terenul se reprezint ca un ³ir de N numere naturale h1 , h2 , h3 , ..., hN reprezentând în lµimile
în metri pe care le au zonele din terenul iniµial, privite de la stânga spre dreapta.
Pentru a nivela terenul ai închiriat un buldozer care funcµioneaz astfel. Se alege o în lµime
H (num r natural) la care ridic m lama buldozerului. Iniµial buldozerul are pe lam o cantitate
C=0 metri cubi de p mânt. Buldozerul începe s merg de la stânga la dreapta ³i când ajunge la
zona i, în funcµie de în lµimea hi a acesteia, se va aa în una dintre urm toarele situaµii:
Remarc m faptul c H trebuie ales iniµial astfel încât de ecare dat când buldozerul ajunge
în a doua situaµie s aib pe lam sucient p mânt (C ' H hi ).
Dup ce buldozerul parcurge cele N zone de lungime 1 pe lama buldozerului e posibil s mai
r mân p mânt, dar asta nu te intereseaz , pentru c la cap tul din dreapta al terenului este un
râu, ³i p mântul r mas se va v rsa acolo.
Cerinµe
Scrieµi un program care calculeaz în lµimea maxim H la care poate ridicat lama, astfel
încât terenul s poat nivelat la acea în lµime.
Date de intrare
Fi³ierul de intrare buldo.in conµine pe prima linie num rul natural N , iar pe a doua linie,
separate prin câte un spaµiu, cele N numere naturale h1 , h2 , h3 , ..., hN , cu semnicaµia din enunµ.
Date de ie³ire
Fi³ierul de ie³ire buldo.out va conµine o singur linie, pe care va scris num rul natural H
cerut.
Restricµii ³i preciz ri
a 1&N & 100 000
a În lµimile sunt numere naturale, 1 & hi & 1000 000 000, pentru orice i, 1 & i & N .
a Pentru teste în valoare de 50 de puncte, N & 1 000 ³i hi & 1 000, pentru orice i, 1 & i & N .
Exemple:
2
CAPITOLUL 1. OJI 2020 3
Soluµia 1
Pentru ecare în lµime posibil la care se poate xa lama la prima fâ³ie simul m deplasarea la
dreapta. Timp de executare de ordin H*N (H = în lµimea maxim pentru fâ³ii iar N = num rul
de f ³ii). Aceteast soluµie nu se încadreaz în timp pe toate testele.
Soluµia 2
Observ m c putem c uta binar rezultatul, având o înbun t µire semnicativ deoarece nu mai
suntem obligaµi s test m toate în lµimile posibile.
Soluµia 3
Dac la poziµia curent i consider m s = suma valorilor din ³ir, de la început ³i pân la poziµia
i, atunci s©i este în lµimea maxim la care putem trece cu lama pe acolo. Soluµia este reprezentat
minimul dintre valorile s©i. Timpul de executare este de ordin N .
Implementarea corect a unor abord ri ca a doua ³i a treia de mai sus aduc punctaj maxim.
22 for (i=3;i<=n;i++)
23 {
24 ///f[i] = 1 + (1LL*f[i-1]*f[i-2] + f[i-1] + f[i-2]) % MOD;
25 scanf("%lld ", &c);
26 s += c;
27 sol = min(sol, s/i);
28 a = b;
29 b = c;
30 }
31
32 printf("%lld\n", sol);
33 return 0;
34 }
25
26 }
27
28 int r=h[i]-v[m];
29 c[m]++;
30
31 /// cat timp am suficient sa ridic ultimul nivel la penultimul nivel
32 do
33 {
34 int64_t need = 1LL*c[m]*(v[m-1]-v[m]);
35 if(need<=1LL*r)
36 {
37 c[m-1]+=c[m];
38 r-=need;
39 m--;
40 continue;
41 }
42
43 int hplus=r/c[m];
44 v[m]+=hplus;
45 r=r%c[m];
46 if(r==0)
47 break;
48 m++;
49 v[m]=v[m-1];
50 v[m-1]++;
51 c[m]=c[m-1]-r;
52 c[m-1]=r;
53 break;
54
55 } while(1);
56 }
57
58 g<<v[m];
59 return 0;
60 }
37 c+=a[i]-h;
38 }
39 };
40
41 out << h << endl;
42 return 0;
43 }
7
8 long long a, b, c, i, sol, n, s;
9
10 int main ()
11 {
12 fin>>n;
13 fin>>a;
14 if (n == 1)
15 {
16 fout<<a<<"\n";
17 return 0;
18 }
19 fin>>b;
20 s = a;
21 sol = a;
22 s += b;
23 sol = min(sol, s/2);
24 for (i=3;i<=n;i++)
25 {
26 fin>>c;
27 s += c;
28 sol = min(sol, s/i);
29 a = b;
30 b = c;
31 }
32
33 fout<<sol;
34 return 0;
35 }
44 fout<<dr;
45 return 0;
46 }
1.2 cetate
Problema 2 - cetate 100 de puncte
Cetatea Vizima din regatul Temeria poate reprezentat printr-o matrice cu N linii ³i M
coloane, numerotate începând cu 1. Vizima este o cetate înoritoare, fapt datorat num rului
mare de negustori ³i me³teri prezenµi. Din acest motiv, ec rei celule din matrice îi este atribuit
un prot corespunz tor zonei respective. Regele Foltest dore³te s reconstruiasc zidurile cet µii,
dar cum r zboiul cu Imperiul Nilfgaard bate la u³ ³i resursele regatului sunt limitate, el trebuie
s aleag o porµiune pe care s o poat ap ra, reprezentat ca o submatrice.
O submatrice este identicat printr-o conguraµie de patru numere i1 , j1 , i2 , j2 (1 & i1 & i2 &
N , 1 & j1 & j2 & M ), în aceast ordine, ³i este format din elementele situate pe liniile consecutive
i1 , i1 1, ..., i2 ³i pe coloanele consecutive j1 , j1 1, ..., j2 ale matricei prin care este reprezentat
cetatea. Laturile submatricei sunt egale cu num rul de linii, respectiv de coloane din care a preluat
elemente, iar protul submatricei este suma valorilor din celulele sale.
Cerinµe
Scrieµi un program care, cunoscând matricea cet µii ³i o valoare K , determin :
1) protul maxim al unei submatrice cu laturile egale cu K , precum ³i conguraµia prin care
se identic ea;
2) protul maxim al unei submatrice cu laturile cel mult egale cu K , precum ³i conguraµia
prin care se identic ea.
Date de intrare
Fi³ierul de intrare cetate.in conµine pe primul rând o valoare c egal cu 1 sau 2, reprezentând
cerinµa ce urmeaz a rezolvat .
Urm toarea linie conµine în ordine N , M ³i K , cu semnicaµia din enunµ, iar pe urm toarele
N linii se a câte M numere, reprezentând valorile din matricea dat . Numerele aate pe aceea³i
linie a ³ierului sunt separate prin câte un spaµiu.
Date de ie³ire
Fi³ierul de ie³ire cetate.out va conµine pe prima linie protul maxim cerut, conform cerinµei,
iar pe a doua linie va conµine 4 numere naturale, reprezentând conguraµia prin care se identic
submatricea obµinut . Dac exist mai multe submatrice conform cerinµei, se va lua în considerare
cea pentru care conguraµia format din cele 4 numere de mai sus este minim lexicograc .
Restricµii ³i preciz ri
a 1 & N, M & 400; 1 & K & min N, M
9 9
a Valorile date pentru matricea cet µii se a în intervalul 10 , 10
a Pentru teste în valoare de 20 de puncte, c 1, iar pentru restul testelor, în valoare de 70 de
puncte, c 2. Pentru teste în valoare de 8 puncte, c 1 ³i 1 & N, M & 70. Pentru teste în
valoare de 25 de puncte, c 2 ³i 1 & N, M & 70
a Conguraµia x1 , x2 , x3 , x4 este mai mic din punctul de vedere lexicograc decât con-
guraµia y1 , y2 , y3 , y4 dac exist p astfel încât xp < yp ³i x1 y1 , x2 y2 ... xp1 =
yp1 .
Exemple:
CAPITOLUL 1. OJI 2020 9
Soluµie cerinµa 1
Pentru cerinµa 1 este sucient s precalcul m pentru ecare poziµie (i, j ) din matrice suma
submatricii determinate de colµurile 1, 1 i, j . Acest lucru se poate face u³or în O N M
aplicând formula
Fix m colµul stânga jos pentru matricea p trat de dimensiune K , iar suma corespunz toare va
Complexitate: O N M
Soluµie cerinµa 2
Dac x m în toate modurile posibile cele 2 colµuri ale submatricii ³i ne folosim de sumele
2
parµiale de mai sus, obµinem o complexitate de O N M K care obµine în jur de 25 puncte.
Ideea rezolv rii const în xarea liniilor submatricei c utate în O N K .
Tot ce mai r mâne de f cut este g sirea coloanelor optime. Folosind sume parµiale pe coloane,
putem reduce acum problema la determinarea unei subsecvenµe de lungime maxim K de sum
maxim .
Ne vom referi de acum la aceast problem mai simpl : dându-se un vector cu M elemente
s se determine subsecvenµa de sum maxim , de lungime maxim K .
Pentru ecare poziµie i din vector, reµinem suma primelor i elemente (sume parµiale pe pre-
x). Având xat cap tul dreapta al secvenµei c utate i, ne intereseaza suma parµial minim
corespunz toare unei poziµii aate între i K ³i i 1 (e aceasta poziµie j ). Astfel subsecvenµa
de suma maxim , care are cap tul dreapta i, are cap tul stânga j 1, iar suma ei este diferenµa
dintre suma parµial de la poziµia i ³i cea de la poziµia j .
R mâne de v zut cum putem determina aceast sum parµial minim în timp optim.
Consider m ³irul sumelor parµiale pe prex. îl împ rµim în secvenµe de câte K elemente. Pentru
ecare secvenµ calcul m minim parµial pe sux ³i minim parµial pe prex. Orice subsecvenµ de
dimensiune K poate scris ca reuniunea dintre un sux ³i un prex a dou secvenµe consecutive.
Astfel putem aa minimul orc rei subsecvenµe în timp constant, iar precalcularea se poate face
liniar.
Obµinem astfel complexitatea nala: O N M K ³i punctajul maxim.
84 else
85 act(v[j]-v[pr[right]],
86 i1, pr[right]+1, i2, j);
87 }
88 }
89 }
90 }
91
92 long long best_sum;
93 int i1, i2, j1, j2;
94
95 best_sum=sol.p1,i1=sol.p2,j1=sol.p3,i2=sol.p4,j2=sol.p5;
96
97 out << best_sum << ’\n’;
98 out << i1 << ’ ’ << j1 << ’ ’ << i2 << ’ ’ << j2 << ’\n’;
99
100 return 0;
101 }
102 /*
103 execution time : 2.203 s
104 */
52
53 long long sMax=a[1][1],iMax=1,j1Max=1,j2Max=1,kMax=1;
54
55 for(int ik=1;ik<=k;ik++)
56 {
57 for(int i=1;i<=n-ik+1;i++)
58 {
59 s1[i][1]=a[i][1];
60 for(int j=2;j<=m;j++)
61 {
62 s1[i][j]=s1[i][j-1]+a[i][j];
63 }
64
65 s2[i][m]=a[i][m];
66 for(int j=m-1;j>0;j--)
67 {
68 s2[i][j]=s2[i][j+1]+a[i][j];
69 }
70
71 s2Max1[i][1]=s2[i][1];
72 s2MaxId1[i][1]=1;
73 for(int j=2;j<=m;j++)
74 {
75 if(s2[i][j]>s2Max1[i][j-1]||j%k==1)
76 {
77 s2Max1[i][j]=s2[i][j];
78 s2MaxId1[i][j]=j;
79 }
80 else
81 {
82 s2Max1[i][j]=s2Max1[i][j-1];
83 s2MaxId1[i][j]=s2MaxId1[i][j-1];
84 }
85 }
86
87 s2Max2[i][m]=s2[i][m];
88 s2MaxId2[i][m]=m;
89 for(int j=m-1;j>0;j--)
90 {
91 if(s2[i][j]>=s2Max2[i][j+1]||j%k==1)
92 {
93 s2Max2[i][j]=s2[i][j];
94 s2MaxId2[i][j]=j;
95 }
96 else
97 {
98 s2Max2[i][j]=s2Max2[i][j+1];
99 s2MaxId2[i][j]=s2MaxId2[i][j+1];
100 }
101 }
102
103 for(int j=1;j<=m;j++)
104 {
105 if(j<=k)
106 {
107 s2Max[i][j]=s2Max1[i][j];
108 if(s2Max[i][j-1]==s2Max1[i][j])
109 {
110 s2MaxId[i][j]=s2MaxId1[i][j-1];
111 }
112 else
113 {
114 s2MaxId[i][j]=s2MaxId1[i][j-1];
115 }
116 }
117 else
118 {
119 if(s2Max1[i][j]>=s2Max2[i][j-k+1])
120 {
121 s2Max[i][j]=s2Max1[i][j];
122 s2MaxId[i][j]=s2MaxId1[i][j];
123 }
124 else
125 {
126 s2Max[i][j]=s2Max2[i][j-k+1];
127 s2MaxId[i][j]=s2MaxId2[i][j-k+1];
CAPITOLUL 1. OJI 2020 15
128 }
129 }
130 }
131
132 for(int j=2;j<=m;j++)
133 {
134 if(s1[i][j]+s2Max[i][j]-s2[i][1]==sMax)
135 {
136 if(iMax>i || iMax==i && j1Max>s2MaxId[i][j])
137 {
138 iMax=i;j1Max=s2MaxId[i][j];j2Max=j;kMax=ik-1;
139 }
140 }
141 else
142 {
143 if(s1[i][j]+s2Max[i][j]-s2[i][1]>sMax)
144 {
145 sMax=s1[i][j]+s2Max[i][j]-s2[i][1];
146 iMax=i;
147 j1Max=s2MaxId[i][j];
148 j2Max=j;kMax=ik-1;
149 }
150 }
151 }
152
153 for(int j=1;j<=m;j++)
154 {
155 a[i][j]+=aa[i+ik][j];
156 }
157 }
158 }
159
160 out<<sMax<<’\n’<<iMax<<’ ’<<j1Max<<’ ’<<iMax+kMax<<’ ’<<j2Max<<’\n’;
161
162 return 0;
163 }
164 /*
165 execution time : 5.510 s
166 */
1 /*========================================================================
2 * Autor: stud. Iordache Ioan-Bogdan, Universitatea din Bucuresti
3 * Complexitate: O(N*M*K)
4 * Punctaj asteptat: 90p
5 *=======================================================================*/
6 #include <fstream>
7 #include <iostream>
8
9 using namespace std;
10
11 const int DIM = 505;
12 const long long INF = (1LL << 62);
13
14 int n, m, k, a[DIM][DIM];
15 long long sum[DIM][DIM], v[DIM], min_prefix[DIM], min_suffix[DIM];
16
17 int main()
18 {
19 #ifndef TESTING
20 ifstream cin("cetate.in");
21 ofstream cout("cetate.out");
22 #endif
23
24 int op;
25 cin >> op;
26 cin >> n >> m >> k;
27 for (int i = 1; i <= n; ++i)
28 for (int j = 1; j <= m; ++j)
29 cin >> a[i][j];
30
31 long long best = -INF;
32 int h1 = 0, w1 = 0, h2 = 0, w2 = 0;
33
34 if (op == 1)
35 {
36 for (int i = 1; i <= n; ++i)
37 for (int j = 1; j <= m; ++j)
38 sum[i][j] = a[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
39 for (int i = k; i <= n; ++i)
40 {
41 for (int j = k; j <= m; ++j)
42 {
43 long long curr = sum[i][j] - sum[i - k][j] - sum[i][j - k]
44 + sum[i - k][j - k];
45 if (curr > best)
46 {
47 best = curr;
48 h1 = i - k + 1, w1 = j - k + 1, h2 = i, w2 = j;
49 }
50 }
51 }
52
53 cout << best << ’\n’;
54 cout << h1 << ’ ’ << w1 << ’ ’ << h2 << ’ ’ << w2 << ’\n’;
55 return 0;
56 }
57
58 for (int i = 1; i <= n; ++i)
59 for (int j = 1; j <= m; ++j)
60 sum[i][j] = a[i][j] + sum[i - 1][j];
61
62 for (int i1 = 1; i1 <= n; ++i1)
63 {
64 for (int i2 = i1; i2 < i1 + k && i2 <= n; ++i2)
65 {
66 for (int j = 1; j <= m; ++j)
67 v[j] = v[j - 1] + sum[i2][j] - sum[i1 - 1][j];
68
69 for (int j = 1; j <= m; ++j)
70 {
71 if (j % k == 0 || v[j] < v[min_prefix[j - 1]])
72 min_prefix[j] = j;
73 else
74 min_prefix[j] = min_prefix[j - 1];
75 }
CAPITOLUL 1. OJI 2020 18
76
77 for (int j = m; j >= 0; --j)
78 {
79 if (j == m || (j + 1) % k == 0 || v[j] <= v[min_suffix[j+1]])
80 min_suffix[j] = j;
81 else
82 min_suffix[j] = min_suffix[j + 1];
83 }
84
85 for (int j = 1; j <= m; ++j)
86 {
87 if (j < k)
88 {
89 long long curr = v[j] - v[min_prefix[j - 1]];
90 if (best < curr
91 || (best==curr && h1==i1 && min_prefix[j-1]+1 < w1))
92 {
93 best = curr;
94 h1 = i1, w1 = min_prefix[j - 1] + 1, h2 = i2, w2 = j;
95 }
96 continue;
97 }
98
99 int left = max(0, j - k);
100 int right = j - 1;
101 long long curr;
102 int curr_w1;
103 if (v[min_suffix[left]] <= v[min_prefix[right]])
104 curr = v[j] - v[min_suffix[left]],
105 curr_w1 = min_suffix[left] + 1;
106 else
107 curr = v[j] - v[min_prefix[right]],
108 curr_w1 = min_prefix[right] + 1;
109
110 if (best < curr
111 || (best == curr && h1 == i1 && curr_w1 < w1))
112 {
113 best = curr;
114 h1 = i1, w1 = curr_w1, h2 = i2, w2 = j;
115 }
116 }
117 }
118 }
119
120 cout << best << ’\n’;
121 cout << h1 << ’ ’ << w1 << ’ ’ << h2 << ’ ’ << w2 << ’\n’;
122
123 return 0;
124 }
125 /*
126 execution time : 2.028 s
127 */
21 fin>>a[i][j];
22
23 sol = 1LL*DIM*DIM*-1000000000;
24 if (t == 1)
25 {
26
27 for (i=1;i<=n;i++)
28 for (j=1;j<=m;j++)
29 a[i][j] += a[i][j-1] + a[i-1][j] - a[i-1][j-1];
30
31 for (i=k;i<=n;i++)
32 for (j=k;j<=m;j++)
33 {
34 long long suma = a[i][j]-a[i-k][j]-a[i][j-k]+a[i-k][j-k];
35 if (suma > sol)
36 {
37 sol = suma;
38 i1 = i-k+1;
39 j1 = j-k+1;
40 i2 = i;
41 j2 = j;
42 }
43 }
44
45 fout<<sol<<"\n";
46 fout<<i1<<" "<<j1<<" "<<i2<<" "<<j2<<"\n";
47 }
48 else
49 {
50 for (j=2;j<=m;j++)
51 for (i=1;i<=n;i++)
52 a[i][j] += a[i][j-1];
53
54 for (c1 = 1; c1<=m; c1++)
55 for (c2 = c1; c2<=m && c2-c1+1 <= k; c2++)
56 {
57 v[1] = a[1][c2] - a[1][c1-1];
58
59 for (i=2;i<=n;i++)
60 v[i] = a[i][c2] - a[i][c1-1];
61
62 s = v[1];
63 p = 1;
64 if (v[1] > sol)
65 {
66 sol = v[1];
67 i1 = 1;
68 j1 = c1;
69 i2 = 1;
70 j2 = c2;
71 }
72
73 for (i=2;i<=n;i++)
74 {
75 if (s + v[i] >= v[i])
76 {
77 s += v[i];
78 if (i-p+1 > k)
79 {
80 s-=v[p];
81 p++;
82 while (p!=i && v[p] < 0)
83 {
84 s -= v[p];
85 p++;
86 }
87 }
88 }
89 else
90 {
91 s = v[i];
92 p = i;
93 }
94
95 if (s > sol)
96 {
CAPITOLUL 1. OJI 2020 20
97 sol = s;
98 i1 = p;
99 j1 = c1;
100 i2 = i;
101 j2 = c2;
102 }
103 }
104
105 }
106
107 fout<<sol<<"\n";
108 fout<<i1<<" "<<j1<<" "<<i2<<" "<<j2<<"\n";
109 }
110
111 return 0;
112 }
113 /*
114 execution time : 0.892 s
115 */
54
55 for (c1 = 1; c1<=m; c1++)
56 for (c2 = c1; c2<=m && c2-c1+1 <= k; c2++)
57 {
58 v[1] = a[1][c2] - a[1][c1-1];
59 if (v[1] > sol)
60 {
61 sol = v[1];
62 i1 = 1;
63 j1 = c1;
64 i2 = 1;
65 j2 = c2;
66 ///cout<<1<<" "<<sol<<"\n";
67 }
68
69 for (i=2;i<=n;i++)
70 v[i] = v[i-1] + a[i][c2] - a[i][c1-1];
71 p = 1;
72 u = 1;
73 d[1] = 0;
74 for (i=1;i<=n;i++)
75 {
76 if (v[i] - v[i-1] > sol)
77 {
78 sol = v[i] - v[i-1];
79 i1 = i;
80 j1 = c1;
81 i2 = i;
82 j2 = c2;
83 ///cout<<2<<" "<<sol<<"\n";
84 }
85
86 if (k > 1)
87 {
88
89 if (v[i] - v[d[p]] > sol)
90 {
91 sol = v[i] - v[d[p]];
92 i1 = d[p]+1;
93 j1 = c1;
94 i2 = i;
95 j2 = c2;
96 ///cout<<3<<" "<<sol<<"\n";
97 }
98
99 while (p <= u && v[i] < v[ d[u] ])
100 u--;
101 d[++u] = i;
102 if (i-d[p] == k)
103 p++;
104 }
105 }
106 }
107
108 fout<<sol<<"\n";
109 fout<<i1<<" "<<j1<<" "<<i2<<" "<<j2<<"\n";
110 }
111
112 return 0;
113 }
114 /*
115 execution time : 2.173 s
116 */
10 #include <algorithm>
11
12 FILE *fin = fopen("cetate.in", "r"), *fout = fopen("cetate.out", "w");
13
14 #define BUF_SIZE 1 << 17
15
16 int pos = BUF_SIZE;
17 char buf[BUF_SIZE];
18
19 inline char nextch()
20 {
21 if (pos == BUF_SIZE)
22 fread(buf, BUF_SIZE, 1, fin), pos = 0;
23 return buf[pos++];
24 }
25
26 inline int read()
27 {
28 char ch = nextch();
29 while (ch != ’-’ && !isdigit(ch)) ch = nextch();
30 int s = 1;
31 if (ch == ’-’) s = -1, ch = nextch();
32 int x = ch - ’0’;
33 while (isdigit(ch = nextch())) x = 10 * x + ch - ’0’;
34 return s * x;
35 }
36
37 #define LIM 501
38
39 int n;
40 long long aib[LIM], s[LIM][LIM];
41
42 inline void update(int p, long long x)
43 {
44 while (p <= n)
45 {
46 aib[p] = std::max(aib[p], x);
47 p += p & (-p);
48 }
49 }
50
51 inline long long query(int p)
52 {
53 long long ans = aib[p];
54 do
55 {
56 p -= p & (-p);
57 ans = std::max(ans, aib[p]);
58 } while (p);
59 return ans;
60 }
61
62 int main()
63 {
64 int c = read();
65 int nrlin = read();
66 int nrcol = read();
67 int k = read();
68
69 if (c != 2)
70 return 0;
71 n = nrcol;
72
73 for (int i = 1; i <= nrlin; i++)
74 for (int j = 1; j <= nrcol; j++)
75 s[i][j] = read() + s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
76
77 long long ans = s[1][1];
78 int sol1 = 1, sol2 = 1, sol3 = 1, sol4 = 1;
79 for (int i = 1; i <= nrlin; i++)
80 {
81 for (int l = i; l <= nrlin && l - i < k; l++)
82 {
83 memset(aib, 0x80, sizeof(aib[0]) * (nrcol + 1));
84 for (int j = nrcol; j > 0; j--)
85 {
CAPITOLUL 1. OJI 2020 23
50 }
51
52 inline void urcare(int p)
53 {
54 if (p > n) return ;
55 while (p > 1 && d[heap[p]] > d[heap[p / 2]]) mySwap(p, p / 2);
56 }
57
58 inline void coborare(int p)
59 {
60 int q;
61 bool f = 1;
62 while (f && (q = 2 * p) <= n)
63 {
64 q += (q < n && d[heap[q + 1]] > d[heap[q]]);
65 if (d[heap[q]] > d[heap[p]]) mySwap(p, q);
66 else f = 0;
67 }
68 }
69
70 inline void baga(int p, long long val)
71 {
72 heap[++n] = p;
73 d[p] = val;
74 poz[p] = n;
75 urcare(n);
76 }
77
78 inline void scoate(int p)
79 {
80 int u = poz[p];
81 heap[u] = heap[n];
82 poz[heap[n--]] = u;
83 coborare(u);
84 urcare(u);
85 }
86
87 int main()
88 {
89 int c = read();
90 int nrlin = read();
91 int nrcol = read();
92 int k = read();
93
94 if (c != 2)
95 return 0;
96
97 for (int i = 1; i <= nrlin; i++)
98 for (int j = 1; j <= nrcol; j++)
99 s[i][j] = read() + s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
100
101 long long ans = s[1][1];
102 int sol1 = 1, sol2 = 1, sol3 = 1, sol4 = 1;
103 for (int i = 1; i <= nrlin; i++)
104 {
105 for (int l = i; l <= nrlin && l - i < k; l++)
106 {
107 n = 0;
108 for (int j = nrcol; j > 0; j--)
109 {
110 baga(j, s[l][j] - s[i - 1][j]);
111 if (j + k <= nrcol) scoate(j + k);
112 long long val = d[heap[1]] - (s[l][j - 1] - s[i - 1][j - 1]);
113 if (val > ans || (val == ans && i == sol1 && j < sol2))
114 sol1 = i, sol2 = sol4 = j, sol3 = l, ans = val;
115 }
116 }
117 }
118
119 while (s[sol3][sol4] - s[sol3][sol2 - 1] -
120 s[sol1 - 1][sol4] + s[sol1 - 1][sol2 - 1] != ans)
121 sol4++;
122
123 fprintf(fout, "%lld\n%d %d %d %d\n", ans, sol1, sol2, sol3, sol4);
124
125 fclose(fin);
CAPITOLUL 1. OJI 2020 25
126 fclose(fout);
127 return 0;
128 }
129 /*
130 execution time : 4.947 s
131 */
1.3 spiralmatrix
Problema 3 - spiralmatrix 100 de puncte
Parcurgând elementele unei matrice p tratice de dimensiune n în spiral , pornind din colµul
din stânga-sus, în sens orar, de la margini c tre interior, se obµine ³irul strict cresc tor format din
2
toate valorile de la 1 la n , ca în gura de mai jos. Din ³irul dat se obµin dou sub³iruri disjuncte,
de lungime egal , cu num r maxim de termeni. Primul sub³ir este format din numere consecutive
din prima jum tate a ³irului, ³i trebuie s conµin în mod obligatoriu valoarea 1, iar al doilea
este format din numere consecutive din a doua jum tate a ³irului ³i trebuie s conµin în mod
2
obligatoriu valoarea n .
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
Cerinµe
S se ae poziµia în matrice a celui mai mare termen din primul sub³ir ³i a celui mai mic
termen din al doilea sub³ir.
Date de intrare
Fi³ierul de intrare spiralmatrix.in conµine num rul natural n.
Date de ie³ire
În ³ierul de ie³ire spiralmatrix.out se vor scrie:
- pe prima linie dou numere, separate printr-un spaµiu, reprezentând mai întâi linia ³i apoi
coloana pe care se a în matrice cel mai mare termen al primului sub³ir;
- pe a doua linie alte dou numere, separate printr-un spaµiu, reprezentând mai întâi linia ³i
apoi coloana pe care se a în matrice cel mai mic termen al celui de al doilea sub³ir.
Restricµii ³i preciz ri
a 1 $ n $ 1000 000 000;
a Pentru teste în valoare de 45 de puncte n este impar;
a Pentru teste în valoare de 45 de puncte n $ 1 000;
a Pentru teste în valoare de 75 de puncte n $ 1000 000;
a Liniile sunt numerotate de sus în jos începând cu 1, iar coloanele sunt numerotate de la
stânga la dreapta începând cu 1;
a Punctajul pe un test se obµine doar dac sunt corecte toate cele 4 valori.
Exemple:
CAPITOLUL 1. OJI 2020 26
spiralmatrix.inspiralmatrix.out
Explicaµii
5 52 Primul sub³ir este format din valorile de la 1 la 12. Valoarea 12
41 se g se³te pe linia 5 ³i coloana 2.
Al doilea sub³ir este format din valorile de la 14 la 25. Valoarea
14 se g se³te pe linia 4 ³i coloana 1.
Varianta 1 - 45p
2
Complexitate O n
Structuri de date utilizate: matrice
Declar m o matrice de dimensiune nn ³i o parcurgem în spiral conform enunµului completând
2
valorile. Când ajungem la n ©2 p str m num rul liniei ³i al coloanei curente, aceasta este poziµia
ultimului element al primului sub³ir. Pentru a g si poziµia primului element al celui de al doilea
sub³ir, mai parcurgem înc unul sau doi pa³i in funcµie de paritatea lui n:
Matricea poate parcurs si f r s e efectiv declarat în memorie, deoarece elementele aii
ale ec rei spire k respect condiµia: k & i, j & n k 1
Varianta 2 - 75p
Complexitate O n
În loc s parcurgem matricea element cu element o parcurgem s rind de pe o spir pe urm -
2
toarea pân când g sim spira pe care se a elementul c utat (adic n ©2). Dup ce am g sit
spira, o parcurgem element cu element pân g sim valoarea respectiv .
Pentru calculul valorii de început a ec rei spire folosim urm torul raµionament:
Primul element de pe prima spir este 1.
Prima spir are 4 n 1 elemente, deci primul element de pe spira a doua, a22 are
valoarea egal cu a11 4 n 1.
A doua spir are 4 n 3 elemente, deci primul element de pe spira a treia a33 are
valoarea egal cu a22 4 n 3
...
In general se poate demonstra prin inducµie c : ai 1i 1 aii 4 n 2 i 1,
pentru i 1, 2, ..., n©2
Varianta 3 - 90p
Complexitate O log n
În loc s parcurgem matricea s rind de pe o spir pe urm toarea, vom folosi c utare binar
2
pentru a g si spira pe care se a elementul c utat (adic n ©2). Dup ce am g sit spira, putem
calcula pe care dintre cele 4 laturi ale spirei se g se³te valoarea c utat ³i apoi locul exact.
Pentru calculul valorii de început a ec rei spire folosim urm torul raµionament:
2
ai 1i 1 1 4 n 1 4 n 3 ... 4 n 2 i 1 14in4i
Varianta 4 - 90p
Complexitate O log n
CAPITOLUL 1. OJI 2020 27
Deoarece cele dou sub³iruri au aceea³i lungime, indiferent în ce direcµie parcurgem spirala
e c o parcurgem de la exterior c tre interior (ca în enunµ) e c o parcurgem de la interior
c tre exterior locul de împ rµire în cele dou sub³iruri se va aa în acela³i loc în matrice, doar c
inversat (adic în locul ultimului element al primului sub³ir se va aa primul element al celui de
al doilea sub³ir ³i viceversa). Asta înseamn c ne putem folosi de o matrice în care valorile sunt
dispuse în spiral de la interior spre exterior. Într-o astfel de matrice primul element al matricei
2 2
este n , al doilea n 1 ³.a.m.d., iar elementul de început al ec rei spire este un p trat perfect:
2
a11 n
2 2 2
a22 a11 4 n 1 n 4 n 1 n 4 n 4 n 2
...
2
Pentru a g si spira pe care se a elementul n ©2 folosim c utarea binar .
Odat g sit spira prin calcul direct putem calcula pe care dintre cele 4 laturi ale spirei se
g se³te valoarea c utat ³i apoi locul exact.
Varianta 5 - 90p
Complexitate O 1
În loc s folosim c utarea binar pentru a g si spira pe care se a elementul c utat o calcul m
2
direct prin împ rµirea lui n la radical din 2.
47
48 for(j=n-t;j>=t and gasit==false;j--) //linia n-t+1
49 { k++;
50 if(k==elem_cautat1){sol1i=n-t+1;sol1j=j;}
51 if(k==elem_cautat2){sol2i=n-t+1;sol2j=j;gasit=true;}
52 }
53
54 for(i=n-t;i>t and gasit==false;i--) //col n-t+1
55 { k++;
56 if(k==elem_cautat1){sol1i=i;sol1j=t;}
57 if(k==elem_cautat2){sol2i=i;sol2j=t;gasit=true;}
58 }
59 }
60
61 fo<<sol1i<<" "<<sol1j<<’\n’;
62 fo<<sol2i<<" "<<sol2j<<’\n’;
63
64 return 0;
65 }
54 { k++;
55 if(k==elem_cautat1){sol1i=i;sol1j=t;}
56 if(k==elem_cautat2){sol2i=i;sol2j=t;gasit=true;}
57 }
58 }
59 }
60 fo<<sol1i<<" "<<sol1j<<’\n’;
61 fo<<sol2i<<" "<<sol2j<<’\n’;
62 return 0;
63 }
16
17 int k=1;
18 while(p2<nf)
19 {
20 k++;
21 p2=p2+4*(n-2*k+1);
22 }
23
24 l=k,c=k-1;
25 nc=p2-4*(n-2*k+1);
26 int ncc=0;
27 while(nc<nf)
28 {
29 l=l+dl;c=c+dc;nc++;ncc++;
30 if(l+dl<k || n-k+1<l+dl || c+dc<k || n-k+1<c+dc)
31 {
32 if(dl==0 && dc==1){dl=1;dc=0;}
33 else{if(dl==1 && dc==0){dl=0;dc=-1;}
34 else{if(dl==0 && dc==-1){dl=-1;dc=0;}
35 else{dl=0;dc=1;}}}
36 }
37 }
38
39 l0=l;c0=c;
40 if(ncc==4*(n-2*k+1))k++;
41 if(l+dl<k || n-k+1<l+dl || c+dc<k || n-k+1<c+dc)
42 {
43 if(dl==0 && dc==1){dl=1;dc=0;}
44 else{if(dl==1 && dc==0){dl=0;dc=-1;}
45 else{if(dl==0 && dc==-1){dl=-1;dc=0;}
46 else{dl=0;dc=1;}}}
47 }
48
49 l=l+dl;c=c+dc;
50 l1=l;c1=c;
51 if(l+dl<k || n-k+1<l+dl || c+dc<k || n-k+1<c+dc)
52 {
53 if(dl==0 && dc==1){dl=1;dc=0;}
54 else{if(dl==1 && dc==0){dl=0;dc=-1;}
55 else{if(dl==0 && dc==-1){dl=-1;dc=0;}
56 else{dl=0;dc=1;}}}
57 }
58
59 l=l+dl;c=c+dc;
60 l2=l;c2=c;
61 out << l0 << ’ ’ << c0 << endl;
62 if(n%2==0)out << l1 << ’ ’ << c1 << endl;
63 else out << l2 << ’ ’ << c2 << endl;
64
65 return 0;
66 }
22 {
23 dl=1;dc=0;
24 l=c=n/2-p2/2+1;c--;
25 if(nc<=p2+1){l+=nc-1;}
26 else{l+=p2;c+=nc-p2-1;}
27 }
28 else
29 {
30 l=c=n/2+1+p2/2;
31 dl=-1;dc=0;
32 if(nc<=p2+1){l-=nc-1;}
33 else
34 { l=n-l+1;
35 c-=nc-p2-1;
36 dl=0;dc=-1;
37 }
38 }
39 }
40 else
41 {
42 if(p2%2==0)
43 {
44 dl=-1;dc=0;
45 l=c=n/2+1+p2/2;
46 if(nc<=p2+1){l+=dl*(nc-1);}
47 else{ dl=0;dc=-1;
48 l-=p2;c-=nc-p2-1;}
49 }
50 else
51 {l=c=n/2-p2/2+1;c--;
52 dl=1;dc=0;
53 if(nc<=p2+1){l+=nc-1;}
54 else{ l+=p2;
55 c+=nc-p2-1;
56 dl=0;dc=1;}
57 }
58 }
59
60 if(n%2==0){l1=l;c1=c;}
61 else
62 {
63 l2=l;c2=c;
64 if(l2+dl<=(n-p2)/2 || n-(n-p2)/2+1<l2+dl ||
65 c2+dc<(n-p2)/2 || n-(n-p2)/2+1<c2+dc)
66 {
67 if(dl==-1 && dc==0){dl=0;dc=-1;}
68 else
69 {
70 if(dl==0 && dc==-1){dl=1;dc=0;}
71 else{ if(dl==1 && dc==0){dl=0;dc=1;}
72 else{if(dl==0 && dc==1){dl=-1;dc=0;}}}
73 }
74 }
75 l1=l2+dl;c1=c2+dc;
76 }
77
78 if(l1+dl<=(n-p2)/2 || n-(n-p2)/2+1<l1+dl ||
79 c1+dc<(n-p2)/2 || n-(n-p2)/2+1<c1+dc)
80 {
81 if(dl==-1 && dc==0){dl=0;dc=-1;}
82 else
83 {
84 if(dl==0 && dc==-1){dl=1;dc=0;}
85 else{ if(dl==1 && dc==0){dl=0;dc=1;}
86 else{if(dl==0 && dc==1){dl=-1;dc=0;}}}
87 }
88 }
89
90 l0=l1+dl;c0=c1+dc;
91 out << l0 << ’ ’ << c0 << endl;
92
93 if(n%2==0)out << l1 << ’ ’ << c1 << endl;
94 else out << l2 << ’ ’ << c2 << endl;
95
96 return 0;
97 }
CAPITOLUL 1. OJI 2020 32
75 c2+dc<(n-p2)/2 || n-(n-p2)/2+1<c2+dc)
76 {
77 if(dl==-1 && dc==0){dl=0;dc=-1;}
78 else{if(dl==0 && dc==-1){dl=1;dc=0;}
79 else{ if(dl==1 && dc==0){dl=0;dc=1;}
80 else{if(dl==0 && dc==1){dl=-1;dc=0;}}}}
81 }
82 l1=l2+dl;c1=c2+dc;
83 }
84
85 if(l1+dl<=(n-p2)/2 || n-(n-p2)/2+1<l1+dl ||
86 c1+dc<(n-p2)/2 || n-(n-p2)/2+1<c1+dc)
87 {
88 if(dl==-1 && dc==0){dl=0;dc=-1;}
89 else{if(dl==0 && dc==-1){dl=1;dc=0;}
90 else{ if(dl==1 && dc==0){dl=0;dc=1;}
91 else{if(dl==0 && dc==1){dl=-1;dc=0;}}}}
92 }
93
94 l0=l1+dl;c0=c1+dc;
95 out << l0 << ’ ’ << c0 << endl;
96
97 if(n%2==0)out << l1 << ’ ’ << c1 << endl;
98 else out << l2 << ’ ’ << c2 << endl;
99
100 return 0;}
47 if(nc<3*(n-(2*p2-1)))
48 {
49 dl=0;dc=-1;
50 l=n-p2+1;
51 c=n-p2+1-(nc-2*(n-(2*p2-1)));
52 }
53 else
54 {
55 dl=-1;dc=0;
56 c=p2;
57 l=p2+n-(2*p2-1)-(nc-3*(n-(2*p2-1)));
58 }
59 }
60 }
61
62 l0=l;c0=c;
63 if(nc==4*(n-(2*p2-1))-1){dl=0;dc=1;}
64 else
65 {if(l+dl<p2 || n-p2+1<l+dl || c+dc<p2 || n-p2+1<c+dc)
66 {
67 if(dl==0 && dc==1){dl=1;dc=0;}
68 else{if(dl==1 && dc==0){dl=0;dc=-1;}
69 else{if(dl==0 && dc==-1){dl=-1;dc=0;}
70 else{dl=0;dc=1;}}}
71 }
72 }
73
74 l=l+dl;c=c+dc;
75 l1=l;c1=c;
76 if(l+dl<p2 || n-p2+1<l+dl || c+dc<p2 || n-p2+1<c+dc)
77 {
78 if(dl==0 && dc==1){dl=1;dc=0;}
79 else{if(dl==1 && dc==0){dl=0;dc=-1;}
80 else{if(dl==0 && dc==-1){dl=-1;dc=0;}
81 else{dl=0;dc=1;}}}
82 }
83
84 l=l+dl;c=c+dc;
85 l2=l;c2=c;
86 out << l0 << ’ ’ << c0 << endl;
87
88 if(n%2==0)out << l1 << ’ ’ << c1 << endl;
89 else out << l2 << ’ ’ << c2 << endl;
90
91 return 0;}
28 j=n-d+1;
29 }
30 else
31 if (poz <= k+k-1+k-1)
32 {
33 poz -= (2*k-2);
34 i = n-d+1;
35 j = n-d+1-poz+1;
36 }
37 else
38 {
39 i = d+(4*k-4-poz+1);
40 j = d;
41 }
42
43 }
44
45 int main ()
46 {
47 ifstream fin ("spiralmatrix.in");
48 ofstream fout("spiralmatrix.out");
49
50 fin>>n;
51
52 calcul(n*n/2, i, j);
53 fout<<i<<" "<<j<<"\n";
54 if (n%2 == 0)
55 calcul(n*n/2+1, i, j);
56 else
57 calcul(n*n/2+2, i, j);
58 fout<<i<<" "<<j<<"\n";
59
60 return 0;
61 }
OJI 2019
2.1 abx
Problema 1 - abx 90 de puncte
Un num r natural n se nume³te putere dac exist dou numere naturale a, b, a ' 1, b ' 2
b 5 2 2
astfel încât n a . De exemplu, numerele 32, 169, 1 sunt puteri (32 2 , 169 13 , 1 1 ), iar
72, 2000 ³i 31 nu sunt puteri. Se citesc numerele naturale N , M ³i un ³ir de N numere naturale
x1 , x2 , ..., xN din intervalul 1, M .
Cerinµe
Pentru ecare din cele N numere xi determinaµi câte un num r natural ri din intervalul 1, M ,
cu proprietatea c ri este o putere ³i pentru orice alt putere p din intervalul 1, M este îndeplinit
condiµia ¶xi ri ¶ & ¶xi p¶, unde ¶x¶ reprezint valoarea absolut a lui x (modulul).
Dac exist dou puteri egal dep rtate de xi se va alege puterea cea mai mic . De exemplu
pentru num rul 26, dintre puterile 25 ³i 27 va ales num rul 25.
Date de intrare
Fi³ierul de intrare abx.in conµine pe prima linie dou numere N ³i M , iar pe ecare dintre
urm toarele N linii se g se³te câte un num r natural xi (1 & i & N ), cu semnicaµia de mai sus.
Numerele aate pe aceea³i linie a ³ierului sunt separate prin câte un spaµiu.
Date de ie³ire
Fi³ierul de ie³ire abx.out va conµine N linii, pe ecare linie i (1 & i & N ) aându-se num rul
natural ri cu semnicaµia din enunµ.
Restricµii ³i preciz ri
a 1 & N & 5000
10 & M & 10
18
a
a Pentru teste valorând 40 de puncte M & 5000
a Pentru teste valorând 70 de puncte M & 109
Exemple
abx.in abx.out Explicaµii
3
8 1000 343 343 7
2
345 100 100 10
3
99 1000 1000 10
9
999 512 512 2
2
500 121 121 11
3
123 125 125 5
2
124 100 100 10
8
99 256 256 2
256
Timp maxim de executare/test: 1.0 secunde
Memorie: total 32 MB din care pentru stiv 8 MB
Dimensiune maxim a sursei: 10 KB
Sursa: abx.cpp, abx.c sau abx.pas va salvat în folderul care are drept nume ID-ul t u.
36
CAPITOLUL 2. OJI 2019 37
Soluµie 40p:
Pentru ecare num r x din ³irul dat trebuie s c ut m cea mai apropiat putere, deci vom
avea de efectuat N c ut ri. Pentru a c uta r spunsul pentru un num r dat x, vom avansa în cele
dou direcµii (dreapta, stânga) pân num rul de la pasul curent este putere. Mai apoi, îl vom
a³a pe cel mai apropiat dintre cele dou .
Pentru a verica dac un num r y este putere , o variant este descompunerea lui y în factori
primi. Dac cel mai mare divizor comun al exponenµilor este mai mare decât 1, y este o putere.
Este esenµial observaµia c nu are rost s veric m de mai multe ori dac un num r este
putere sau nu. În acest context, putem precalcula pentru ecare num r din intervalul 1, M dac
acesta este putere ³i stoca acest lucru într-un vector caracteristic.
O soluµie care rezolv problema în complexitate O M N M ar trebui s obµin cel puµin
40 de puncte.
Soluµie 70p:
Vom considera o variant diferit de a genera toate puterile din intervalul 1, M consider m
b b
ecare baz posibil a ³i ad ug m a pornind cu b de la valoarea 2 ³i incrementându-l cât timp a
nu dep ³e³te M . Se observ c ³irul rezultat va avea mai puµin de 50.000 de puteri (eliminând du-
plicatele). Pentru a g si cele dou puteri apropiate de x, vom sorta vectorul, eliminând duplicatele
³i vom efectua o c utare binar pe acest vector sortat.
Se poate demonstra c complexitatea acestei soluµii este O sqrt M N log M . O astfel
de soluµie ar trebui s obµin cel puµin 70 de puncte.
Soluµie 90p:
Pentru subtask-ul M & 10 se poate observa c soluµia de 70 de puncte nu se mai încadreaz în
18
limitele de timp ³i de memorie. Pentru a rezolva problema în acest caz, exist mai multe abord ri;
toate aceste abord ri ar trebui s obµin punctajul maxim, dac sunt implementate cu atenµie:
C utare binar : Pentru un exponent b xat, se poate aa baza maxim a pentru care ab & x.
b b
Mai apoi, singurii candidaµi pentru r spuns sunt a sau a 1 . Complexitatea algoritmului de
c utare binar este O b log M (exponenµiere iterativ ) sau O log b log M (exponenµiere
logaritmic ). O soluµie care caut binar cele dou puteri pentru ecare exponent posibil (2 & b &
60) folosind exponenµierea iterativ are complexitate O N log2 M ³i ar trebui s obµin 90 de
puncte. În continuare vom prezenta optimiz ri extra, care îmbun t µesc ³i mai mult timpul de
execuµie.
Considerarea doar a exponenµilor primi: O optimizare substanµial a soluµiei anterioare
o constituie observaµia c , pentru a considera toate puterile posibile, este sucient s consider m
b b b d
doar exponenµii care sunt primi, deoarece dac n a , cu b d , atunci n a , deci orice
putere de exponent b va considerat în cadrul exponentului d. În intervalul 2, 60 sunt doar 17
numere prime.
Abordare hibrid : O alt soluµie o reprezint precalcularea puterilor pentru b ' 4 într-o
manier similar soluµiei de 70 de puncte ³i folosirea c ut rii binare pentru cazul b 2 sau b 3.
Aceast soluµie are complexitate O sqrt sqrt M N log M . Menµion m c o astfel de
soluµie va obµine un timp de execuµie foarte bun, nedep ³ind 0.1 secunde pe un test maximal.
Posibile gre³eli:
Erori de precizie: Menµion m c folosirea unei abord ri oating-point (folosirea funcµiei
pow) este înceat ³i poate conduce la erori substanµiale de precizie; astfel, nu este recomandat
s e folosit în cadrul soluµiei, dar cu puµin atenµie poate folosit cu succes, mai ales pentru
valori mici de-ale lui M .
Erori de overow: În abordarea de 90 de puncte, ne vom întâmpina de problema overow-
ului, care trebuie tratat cu grij . O variant simpl de a evita astfel de erori este ca, la ecare
înmulµire a b s veric m mai întâi dac a b & M . Cum a b poate da rezultate eronate, vom
verica ca a & M ©b. O soluµie care nu trateaz corect overow-ul va putea obµine între 70 90
de puncte în funcµie de alte detalii de implementare.
2
3 using namespace std;
4
5 int n;
6 long long m, a;
7
8 inline long long lgput(int x, int y)
9 {
10 long long ans = 1, aux = x;
11 for(int p = 1; p <= y ; p = p << 1)
12 {
13 if(y & p) ans = ans * aux;
14 aux = aux * aux;
15 }
16 return ans;
17 }
18
19 inline int cautb(long long x, int put)
20 {
21 long long st = 1, dr = pow(x, 1.0 / put);
22 while(st <= dr)
23 {
24 int mij = (1LL * st + dr) / 2;
25 if(lgput(mij, put) > x) dr = mij - 1;
26 else st = mij + 1;
27 }
28 return dr;
29 }
30
31 int main()
32 {
33 ifstream f("17-abx.in");
34 ofstream g("abx.out");
35
36 f >> n >> m;
37 for(int i=1; i <= n; ++i)
38 {
39 f >> a;
40 long long sol = 0, dif = m + 100;
41 for(int j=2; j <= 60 ; ++j)
42 {
43 long long y = cautb(a, j);
44 long long z = lgput(y, j);
45
46 if(abs(a - z) <= dif && z <= m)
47 sol = z, dif = abs(a - z);
48
49 z = lgput(y + 1, j);
50
51 if(abs(a - z) < dif && z <= m)
52 sol = z, dif = abs(a - z);
53 }
54
55 g << sol << "\n";
56 }
57
58 return 0;
59 }
15 {
16 long long r = 1;
17 for (int i = 0; i < e; ++i)
18 {
19 if (1.0L * r * b > 6e18)
20 return kInf;
21 r *= b;
22 }
23 return r;
24 }
25
26 long long Root(long long x, int ex)
27 {
28 long long b = 1, e = max_base[ex], ans = 1;
29
30 while (b <= e)
31 {
32 long long m = (b + e) / 2;
33 if (Power(m, ex) <= x)
34 {
35 ans = m;
36 b = m + 1;
37 } else e = m - 1;
38 }
39
40 return ans;
41 }
42
43 int main()
44 {
45 ifstream cin("abx.in");
46 ofstream cout("abx.out");
47
48 int n; long long m; cin >> n >> m;
49 assert(1 <= n && n <= 1e5);
50 assert(10 <= m && m <= 1e18);
51
52 for (int ex = 2; ex <= 64; ++ex)
53 {
54 max_base[ex] = kInf;
55 max_base[ex] = Root(m, ex);
56 }
57
58
59 long long max_diff = 0;
60 for (int i = 0; i < n; ++i)
61 {
62 long long x; cin >> x;
63 long long ans = 1;
64 assert(1 <= x && x <= m);
65
66 for (int ex = 2; ex <= 64; ++ex)
67 {
68 long long root = Root(x, ex);
69 long long c1 = Power(root, ex), c2 = Power(root + 1, ex);
70
71 if (c1 <= m && make_pair(abs(c1 - x), c1) <
72 make_pair(abs(ans - x), ans))
73 ans = c1;
74
75 if (c2 <= m && make_pair(abs(c2 - x), c2) <
76 make_pair(abs(ans - x), ans))
77 ans = c2;
78 }
79
80 cout << ans << ’\n’;
81 max_diff = max(max_diff, abs(ans - x));
82 }
83
84 cerr << "MAXIMUM DIFFERENCE: " << max_diff << endl;
85 }
78
79 long long sqrt = Sqrt(x);
80 upd(sqrt * sqrt);
81 upd((sqrt + 1) * (sqrt + 1));
82
83 cout << ans << ’\n’;
84 }
85
86
87 return 0;
88 }
62 else
63 break;
64 }
65 }
66
67 sort(cands.begin(), cands.end());
68
69 cands.erase(unique(cands.begin(), cands.end()), cands.end());
70
71 for (int i = 0; i < n; ++i)
72 {
73 long long x; cin >> x;
74 long long ans = 1;
75
76 auto upd = [&](long long now)
77 {
78 if (now > m) return;
79 if (abs(now - x) < abs(ans - x) ||
80 (abs(now - x) == abs(ans - x) && now < ans))
81 ans = now;
82 };
83
84 auto it = lower_bound(cands.begin(), cands.end(), x);
85
86 upd( *it);
87 if (it != cands.begin())
88 upd( *prev(it));
89
90 long long a2 = Solve2(x);
91
92 upd(a2 * a2);
93 upd((a2 + 1) * (a2 + 1));
94
95 long long a3 = Solve3(x);
96
97 upd(a3 * a3 * a3);
98 upd((a3 + 1) * (a3 + 1) * (a3 + 1));
99
100 cout << ans << ’\n’;
101 }
102
103 return 0;
104 }
30 {
31 long long nxt = now * (base + it);
32 if ((base + it) && nxt / (base + it) != now)
33 nxt = 2e18;
34 now = nxt;
35 }
36
37 if (now > m) continue;
38
39 if (make_pair(abs(x - ans), ans) >
40 make_pair(abs(x - now), now))
41 ans = now;
42 }
43 }
44
45 cout << ans << ’\n’;
46 }
47 return 0;
48 }
54 q=putere(k-1,pr[j]);
55 }
56 else
57 {
58 q1=putere(k+1,pr[j]);
59 if (q1<=v[i])
60 {
61 q=q1;
62 q1=putere(k+2,pr[j]);
63 }
64 }
65
66 if (v[i]-q<=dif)
67 {
68 p=q;
69 dif=v[i]-q;
70 }
71
72 if (q1<=m && q1-v[i]<dif)
73 {
74 p=q1;
75 dif=q1-v[i];
76 }
77 }
78
79 fo<<p<<"\n";
80 }
81
82 return 0;
83 }
2.2 deminare
Problema 2 - deminare 90 de puncte
Pe un teren de form dreptunghiular format din L linii ³i C coloane sunt plantate M mine.
Liniile sunt numerotate de sus în jos cu valori de la 1 la L iar coloanele sunt numerotate de la
stânga la dreapta cu valori de la 1 la C .
Deoarece r zboiul s-a terminat, speciali³tii vor s demineze terenul ³i s -l redea utiliz rii pu-
blice.
Mutarea unei mine reprezint operaµia de transfer a unei mine de la linia x1 ³i coloana y1 la
o poziµie liber , dat de linia x2 ³i coloana y2 , unde 1 & x1 , x2 & L ³i 1 & y1 , y2 & C .
Deoarece mutarea unei mine este periculoas , trebuie determinat num rul minim de mine care
trebuie mutate din poziµia iniµial astfel încât toate minele de pe teren s e a³ezate unele lâng
altele într-o zon compact dreptunghiular , oriunde în cadrul terenului dat, pentru ca apoi s e
detonate împreun .
Spre exemplu: dac L 4, C 5, M 8 ³i minele sunt a³ezate iniµial conform gurii de mai
jos (zonele colorate cu negru arat poziµiile minelor), pentru a se ajunge la o a³ezare a minelor
într-o zon compact de form dreptunghiular num rul minim de mine mutate este 3.
Cerinµe
Cunoscând num rul de linii L ³i de coloane C ale terenului minat, num rul de mine M , precum
³i poziµia ec rei mine, s se scrie un program care determin :
1. linia sau liniile pe care se g sesc cele mai multe mine;
2. num rul minim de mine mutate, pentru ca toate minele de pe teren s e a³ezate într-o
zon compact cu form dreptunghiular .
Date de intrare
Fi³ierul de intrare este deminare.in ³i conµine:
- pe prima linie num rul natural V a c rui valoare poate doar 1 sau 2;
- pe a doua linie dou numere naturale L ³i C , cu semnicaµia din enunµ;
- pe a treia linie num rul natural M , cu semnicaµia din enunµ;
- pe ecare din urm toarele M linii, câte o pereche de valori xi ³i yi , 1 & i & M , reprezentând
linia, respectiv coloana, unde se a o min ;
Numerele aate pe aceea³i linie a ³ierului sunt separate prin câte un spaµiu.
Date de ie³ire
Fi³ierul de ie³ire este deminare.out.
Dac valoarea lui V este 1 atunci prima linie a ³ierului de ie³ire va conµine num rul liniei pe
care se g sesc cele mai multe mine.
Dac exist dou sau mai multe astfel de linii, se vor a³a toate numerele acestora, în ordine
cresc toare, separate prin câte un spaµiu.
Dac valoarea lui V este 2 atunci ³ierul de ie³ire va conµine pe prima linie num rul minim cerut
de mine mutate. Dac minele nu pot a³ezate într-o zon compact de form dreptunghiular ,
în ³ierul de ie³ire se va scrie valoarea 1.
Restricµii ³i preciz ri
a 1 & L, C & 500
a 1&M &L C
a O zon în care se a mine a³ezate pe coloane consecutive, pe aceea³i linie sau a³ezate pe
linii consecutive, pe aceea³i coloan se consider c formeaz o zon compact de form dreptun-
ghiular .
a O zon compact de form dreptunghiular poate avea num rul de linii ocupate egal cu
num rul de coloane ocupate.
a Pentru teste valorând 20 de puncte, avem V 1
a Pentru teste valorând 70 de puncte, avem V 2
a Pentru teste valorând 20 de puncte, avem V 2 ³i L C & 10000
a Pentru teste valorând 32 de puncte, avem V 2 ³i L C & 100000
Exemple
deminare.in deminare.out Explicaµii
1 4 V=1, deci se rezolv doar cerinµa 1
4 5 L=4, C=5, M=8.
8 Minele sunt plasate la poziµiile (1,2), (1,5), (2,1), (3,2), (3,5),
1 2 (4,3), (4,4) ³i (4,5).
1 5 Pe linia 1 sunt amplasate 2 mine;
2 1 Pe linia 2 este amplasat 1 min ;
3 2 Pe linia 3 sunt amplasate 2 mine;
3 5 Pe linia 4 sunt amplasate 3 mine;
4 3 Deci, exist o singur linie pe care sunt amplasate un num r
4 4 maxim de mine ³i anume linia 4.
4 5
CAPITOLUL 2. OJI 2019 46
Consideraµii preliminare
Rezolvarea problemei necesit utilizarea structurilor de date de tip tablou.
Cerinµa 1
Se utilizeaz un tablou bidimensional cu L linii ³i C coloane pentru memorarea poziµiei minelor
din problem .
Se poate calcula num rul de mine de pe ecare linie ³i rezultatul îl putem reµine într-un tablou
unidimensional.
Se determin apoi maximul dintre valorile obµinute anterior ³i se parcurge înc o dat vectorul
num rului de mine ³i dac exist mai multe linii ce reµin un num r egal cu valoarea maxim
anterior determinat se a³eaz indicele liniei respective.
Cerinµa 2
Soluµia I (brute force)
Se descompune num rul de mine M în produs de 2 numere naturale, M a b. Pentru ecare
dintre perechile a ³i b anterior determinate cu proprietatea (1 & a & L ³i 1 & b & C ) se scaneaz
matricea terenului cu zone dreptunghiulare de dimensiuni a b ³i se determin num rul maxim
de valori de 1 dintr-o astfel de zon sau num rul minim de valori de 0.
Este mai ecient s determin m num rul de valori de 1 pentru c acest lucru se poate face
prin însumare, decât num rul de valori de 0, operaµie ce presupune utilizarea repetat a unei
instrucµiuni de decizie.
Nu ne intereseaz unde este a³ezat aceast zon în interiorul terenului. Zona astfel determi-
nat corespunde acelei zone pentru care se vor face cele mai puµine mut ri, având în vedere c
num rul de mine este M (M a b) ³i c aceast zon are cele mai puµine elemente nule.
Este posibil s nu existe o astfel de zon , dac descompunerea lui M nu conµine nici m car o
pereche de numere a ³i b cu 1 & a & L ³i 1 & b & C . În acest caz în ³ierul de ie³ire se a³eaz 1.
Soluµia anterior prezentat obµine aproximativ 50 puncte.
Soluµia II (Sume parµiale pe matrice)
Reducerea ordinului de complexitate al determin rii sumei maxime al numerelor dintr-o zon
dreptunghiular se poate face folosind o matrice auxiliar în care se reµin sume parµiale.
Mai precis se construie³te o matrice M AT cu acelea³i dimensiuni ca matricea din problem , în
care un element M AT ij reµine suma tuturor elementelor matricei iniµiale din zona determinat
de colµul din stânga sus 1, 1 ³i colµul din dreapta jos i, j .
Pe baza acestei matrice num rul de elemente de 1 dintr-o zon dreptunghiular oarecare se
poate calcula mai ecient (O 1) cu formula:
Pentru datele de intrare din exemplul problemei prezent m în gura de mai jos care este
matricea iniµial ³i matricea sumelor parµiale ³i cum se calculeaz ecient num rul de elemente de
1 dintr-o zon dreptunghiular oarecare.
Num rul de 1 din zona galben este egal cu num rul de 1 din toate zonele colorate - num rul
de 1 din zona albastr - num rul de 1 din zona maronie + num rul de 1 din zona colorat
în ambele culori.
O astfel de soluµie obµine 90 puncte.
Observaµii:
a Are mare importanµ cum se construie³te matricea sumelor parµiale. Acest subalgoritm se
2 2
poate realiza în O L C sau O L C L C sau O L C . Prima varianta conduce la punctaje
mai mici chiar ³i decât cele obµinute cu brute force!
a O modalitate ecient de construcµie a acestei matrice folose³te tot algoritmul descris ante-
rior. Fiecare valoare din poziµia i, j se determin pe baza valorilor din poziµiile i 1, j , i, j 1
³i i 1, j 1 cât ³i a valorii din matricea iniµial de pe poziµia i, j .
29 if (v == 1)
30 {
31 for(i=1; i<=L; ++i)
32 if (nL[i] > Max) Max = nL[i];
33 for(i=1; i<=L; ++i)
34 if (nL[i] == Max) printf("%d ", i);
35 return 0;
36 }
37 else
38 {
39 for(i=1; i<=L; ++i)
40 for(j=1; j<=C; ++j)
41 Nr[i][j] = Nr[i-1][j] + Nr[i][j-1] - Nr[i-1][j-1] + a[i][j];
42
43 for(int d=1; d*d<=m; ++d)
44 if (m % d == 0)
45 {
46 int lx = d, ly = m / d;
47
48 ///parcurgem toate submatricile
49 for(i=lx; i<=L; ++i)
50 {
51 int i1 = i - lx;
52 for (j=ly; j<=C; ++j)
53 {
54 int j1 = j - ly;
55 int w = Nr[i][j] - Nr[i][j1] - Nr[i1][j] + Nr[i1][j1];
56 if (w > Max) Max = w;
57 }
58 }
59
60 lx = m/d, ly = d;
61 for(i=lx; i<=L; ++i)
62 {
63 int i1 = i - lx;
64 for (j=ly; j<=C; ++j)
65 {
66 int j1 = j - ly;
67 int w = Nr[i][j] - Nr[i][j1] - Nr[i1][j] + Nr[i1][j1];
68 if (w > Max) Max = w;
69 }
70 }
71 }
72
73 if (Max)
74 printf("%d", m - Max);
75 else
76 printf("-1\n");
77 }
78
79 return 0;
80 }
21 {
22 for(int i=1;i<=lin;++i)
23 {
24 int w=0;
25 for(int k=1;k<=col;++k)
26 w+=ma[i][k];
27 v[i]=w;
28 }
29
30 mx=v[1];
31 for(int i=1;i<=lin;++i)
32 if(v[i]>mx)
33 mx=v[i];
34
35 for(int i=1;i<=lin;++i)
36 if(v[i]==mx)
37 out<<i<<’ ’;
38
39 out<<’\n’;
40 }
41 else
42 {
43 for(int i=1;i<=lin;++i)
44 for(int j=1;j<=col;++j)
45 a[i][j]=ma[i][j]+a[i-1][j]+a[i][j-1]-a[i-1][j-1];
46
47 z=0,mx=0;
48 for(int i=1;i*i<=dim;++i)
49 if(dim%i==0)
50 {
51 int l1=i,c1=dim/i;
52 if(l1<=lin && c1<=col)
53 {
54 z=1;
55 for(int ii=1;ii<=lin-l1+1;++ii)
56 for(int jj=1;jj<=col-c1+1;++jj)
57 {
58 int p=a[ii+l1-1][jj+c1-1]-a[ii+l1-1][jj-1];
59 p=p-a[ii-1][jj+c1-1]+a[ii-1][jj-1];
60 if(p>mx)
61 mx=p;
62 }
63 }
64 //====================================
65
66 l1=dim/i,c1=i;
67 if(l1<=lin && c1<=col)
68 {
69 z=1;
70 for(int ii=1;ii<=lin-l1+1;++ii)
71 for(int jj=1;jj<=col-c1+1;++jj)
72 {
73 int p=a[ii+l1-1][jj+c1-1]-a[ii+l1-1][jj-1];
74 p=p-a[ii-1][jj+c1-1]+a[ii-1][jj-1];
75 if(p>mx)
76 mx=p;
77 }
78 }
79 }
80
81 if(z==0)
82 out<<"-1\n";
83 else
84 out<<dim-mx<<"\n";
85 }
86
87 out.close();
88 return 0;
89 }
80 v.emplace_back(x, y);
81 }
82
83 sort(v.begin(), v.end());
84
85 int best = -1;
86 for (int d = 1; d <= k; ++d)
87 {
88 if (k % d) continue;
89 if (d > m || k / d > n) continue;
90
91 SegmTree st(m + d + 1);
92
93 int j = 0;
94 for (int i = 0; i < k; ++i)
95 {
96 st.Update(v[i].second, v[i].second + d, 1);
97 while (v[j].first == v[i].first - k / d)
98 {
99 st.Update(v[j].second, v[j].second + d, -1);
100 ++j;
101 }
102
103 best = max(best, st.Query());
104 }
105 }
106
107 if (best == -1)
108 cout << -1 << endl;
109 else
110 cout << k - best << endl;
111 }
112 }
40 }
41 return ans;
42 }
43
44 int solve2(std::vector<std::vector<int>>& a, int& l, int& c, int& m) {
45 std::vector<std::vector<int>> sp(l + 1, std::vector<int>(c + 1, 0));
46 for (int i = 0; i < l; ++i) {
47 sp[i][0] = a[i][0];
48 }
49
50 for (int j = 0; j < c; ++j) {
51 sp[0][j] = a[0][j];
52 }
53
54 for (int i = 1; i <= l; ++i) {
55 for (int j = 1; j <= c; ++j) {
56 sp[i][j] = sp[i - 1][j] + sp[i][j - 1] - sp[i - 1][j - 1] + a[i - 1][j - 1];
57 }
58 }
59
60 int lim = sqrt(m);
61 int ans = -1;
62 for (int d = 1; d <= lim; ++d) {
63 if (m % d == 0) {
64 int h = d;
65 int w = m / d;
66
67 ans = std::max(ans, verif(sp, l, c, h, w));
68 ans = std::max(ans, verif(sp, l, c, w, h));
69 }
70 }
71 if (ans == -1) {
72 return -1;
73 }
74 return m - ans;
75 }
76
77 int main() {
78 std::ifstream cin("deminare.in");
79 std::ofstream cout("deminare.out");
80
81 int v, l, c, m;
82 cin >> v >> l >> c >> m;
83 std::vector<std::vector<int>> a(l, std::vector<int>(c, 0));
84 int x, y;
85 for (int i = 0; i < m; ++i) {
86 cin >> x >> y;
87 --x; --y;
88 a[x][y] = 1;
89 }
90
91 if (v == 1) {
92 solve1(a, cout);
93 }
94 else {
95 cout << solve2(a, l, c, m) << "\n";
96 }
97 return 0;
98 }
2.3 mostenire
Problema 3 - mostenire 90 de puncte
Împ ratul cel b trân vrea s împart sacii cu galbeni din vistieria palatului celor K feciori
ai s i, numerotaµi de la 1 la K în ordinea vârstei. Feciorul cu num rul 1 este cel mai mare, iar
mezinul are num rul K .
În vistierie sunt N saci plini cu galbeni, a³ezaµi în linie, atât de grei încât nu li se poate schimba
ordinea, iar pe ecare sac este scris num rul de galbeni pe care îi conµine.
CAPITOLUL 2. OJI 2019 55
Împ ratul îl cheam pe unul dintre feciori ³i îi spune: Fiule, a ta este averea primilor x1
saci! .Feciorul ia sacii ³i pleac fericit. Apoi, împ ratul cheam alt fecior ³i îi spune: Fiule, a ta
este averea primilor x2 saci dintre cei r ma³i! . ³i a³a mai departe, pân ajunge la ultimul fecior
chemat, c ruia îi d toµi sacii r ma³i.
El nu are o ordine anume în care î³i cheam feciorii dar are grij s cheme ecare fecior exact o
dat . Totodat , pentru a evita certurile între ei, este atent ca ecare fecior s primeasc cel puµin
un sac cu galbeni, dar s NU primeasc în total mai mulµi galbeni ca un frate mai mare decât el.
Cel mai mic dintre feciorii împ ratului este ³i cel mai viteaz, a³a c împ ratul ar vrea s îi dea lui
o sum de bani cât mai mare, f r a-i sup ra pe ceilalµi feciori ai s i.
Cerinµe
Cum ar putea împ rµi împ ratul sacii?
Date de intrare
Fi³ierul de intrare mostenire.in conµine pe prima linie numerele naturale N , K , separate de
un spaµiu, cu semnicaµia din enunµ. Pe urm toarele N linii se g se³te câte un num r natural,
reprezentând num rul de galbeni din ecare sac, în ordinea în care ace³tia urmeaz s e distribuiµi
ilor.
Date de ie³ire
Fi³ierul de ie³ire mostenire.out va conµine pe prima linie suma de galbeni pe care o va primi
ul cel mic de la împ rat. Pe urm toarele K linii se vor aa câte dou numere naturale ce
reprezint num rul de ordine al feciorului, respectiv num rul de saci xi pe care îi prime³te acesta,
în ordinea în care au fost chemaµi de împ rat.
Restricµii ³i preciz ri
a2 & K & 100
aK & N & 100000
a 1 & Num rul de galbeni din ecare sac & 100000
a Galbenii din oricare dintre saci nu pot împ rµiµi mai multor fraµi
9
a Num rul total de galbeni aaµi în vistierie este mai mic sau egal cu 10
a Împ ratul cel b trân nu are doi feciori cu aceea³i vârst
a Puteµi a³a orice soluµie în care mezinul prime³te num rul maxim posibil de galbeni
a Pentru ecare test, a³area corect a num rului maxim de galbeni primiµi de mezin este
notat cu 40% din punctajul alocat testului
a Pentru teste valorând 10 puncte N K , N & 100
a Pentru teste valorând 30 de puncte 2 & K $ N & 15
a Pentru teste valorând 50 de puncte 2 & K $ N & 100
Exemple
mostenire.in mostenire.outExplicaµii
83 10 Fiul cel mic este chemat primul ³i ia primii 4 saci, primind
1 34 astfel 1 2 3 4 10 galbeni.
2 22 Fiul cel mijlociu este chemat al doilea ³i ia urm torii 2
3 12 saci, primind astfel 5+6=11 galbeni.
4 Fiul cel mare este chemat ultimul ³i ia restul de 2 saci,
5 primind astfel 7 8 15 galbeni.
6
7
8
CAPITOLUL 2. OJI 2019 56
Soluµia I - N K - 10p
În acest caz, ecare fecior va lua cate un sac din cei N . Vom împ rµii sacii astfel: feciorul 1 va
lua sacul cu cei mai mulµi galbeni, feciorul 2 pe urm torul ³.a.m.d. pân când feciorul cel mai mic
ia sacul cu cei mai puµini galbeni. În caz de egalitate nu trebuie s facem nimic special pentru c
un fecior mai mare poate primi aceea³i sum de galbeni ca un fecior mai mic.
Construim 3 vectori:
ai - num rul de galbeni al ec rui sac i în ordinea din ³ierul de intrare;
indi - indicele sacului (iniµial indi i);
f iui - indicele ului ce va lua sacul respectiv (necompletat iniµial).
Sort m descresc tor vectorul a modicând ³i vectorul ind corespunz tor. Pe prima line putem
a³ valoarea celui mai mic sac, aN .
Apoi, vom completa vectorul u printr-o parcurgere de la stânga la dreapta: f iui i.
În acest moment un grup ai, indi, f iui reprezint nr de galbeni din sac, indicele iniµial
al sacului ³i indicele ului ce va primi acel sac. Pentru a reconstrui împ rµirea, sort m cresc tor
vectorul ind modicând ³i vectorul f iu corespunz tor. Acum în vectorul f iu avem ordinea în care
trebuie chemaµi feciorii de împart.
Pentru c avem de sortat vectorii, complexitatea timp a acestei soluµii este O N log N sau
2
O N , în funcµie de algoritmul de sortare ales.
Reconstrucµia împ rµirii
Se poate adapta soluµia de mai sus pentru a a³a ³i cele K subsecvenµe alese, în cazurile valide.
Pentru a asigna cele K subsecvenµe celor K i, trebuie s ne asigur m c averile vor atribuite
ilor în ordinea vârstei sale. Acest lucru se va realiza prin doi pa³i:
Pasul 1: A m ecare subsecvenµ c rui u îi aparµine. Pentru aceasta, atribuim ec rei
subsecvenµe numere de la 1 la K , în ordinea descresc toare a num rului de galbeni. Acest lucru
se poate realiza printr-o sortare.
Pasul 2: A³ m lungimea subsecvenµei ³i ul corespunz tor, în ordinea de la stânga la dreapta.
O atenµie special trebuie acordat cazului în care soluµia de mai sus va a³a mai mult de
K subsecvenµe, caz în care unele subsecvenµe vecine vor trebui contopite. Din fericire, îns , se
poate observa c putem alege s contopim oricare dou subsecvenµe vecine, soluµia r mânând
valid .
2
Complexitatea reconstrucµiei este O N sau O N log N , în funcµie de algoritmul de sortare
ales.
12 {
13 int n = v.size();
14
15 vector<tuple<int, int, int>> ans;
16
17 int have = 0, start = 0;
18
19 for (int i = 0; i < n; ++i)
20 {
21 have += v[i];
22 if (have < need)
23 continue;
24 if ((int)ans.size() == k - 1 && i != n - 1)
25 continue;
26
27 ans.emplace_back(have, start, i + 1);
28 have = 0;
29 start = i + 1;
30 }
31
32 return ans;
33 }
34
35 int main()
36 {
37 ifstream cin("mostenire.in");
38 ofstream cout("mostenire.out");
39
40 int n, k;
41 cin >> n >> k;
42
43 assert(k <= 100);
44 assert(k <= n);
45 assert(n <= 100 * 1000);
46
47 vector<int> v(n);
48
49 int total = 0;
50 for (int i = 0; i < n; ++i)
51 {
52 cin >> v[i];
53 total += v[i];
54 }
55
56 assert(total <= 1000 * 1000 * 1000);
57
58 int b = 0, e = total, ans = -1;
59 while (b <= e)
60 {
61 int m = (b + e) / 2;
62 if ((int)Solve(v, k, m).size() == k)
63 {
64 ans = m;
65 b = m + 1;
66 }
67 else
68 e = m - 1;
69 }
70
71 assert(ans != -1);
72 cout << ans << endl;
73
74 auto sol = Solve(v, k, ans);
75
76 sort(sol.rbegin(), sol.rend());
77
78 vector<tuple<int, int, int>> new_sol;
79
80 for (int i = 0; i < k; ++i)
81 {
82 int b, e; tie(ignore, b, e) = sol[i];
83 new_sol.emplace_back(b, i, e - b);
84 }
85
86 sort(new_sol.begin(), new_sol.end());
87
CAPITOLUL 2. OJI 2019 59
65 void Print()
66 {
67 int j = 0;
68 fout << Sol << "\n";
69 Sum[1] = Bags[1] = 0;
70 j = 1;
71 for(int i = 1; i<= N; ++i)
72 {
73 Sum[j] += X[i];
74 Bags[j]++;
75 if(Sum[j] >= Sol)
76 {
77 Sum[++j] = 0;
78 Bags[j] = 0;
79 }
80 }
81
82 Sum[K] += Sum[K+1];
83 Bags[K] += Bags[K+1];
84
85 for(int i = 1; i <= K; ++i)
86 Index[i] = i;
87
88 sort(Index + 1, Index + K + 1, Compare);
89
90 for(int i = 1; i <= K; ++i)
91 Sum[Index[i]] = i;
92
93 for(int i = 1; i <= K; ++i)
94 fout << Sum[i] << " " << Bags[i] << "\n";
95 }
96
97 int main()
98 {
99 Read();
100 Solve();
101 Print();
102 return 0;
103 }
34 }
35 }
36 if (cnt == k) {
37 return true;
38 }
39 return false;
40 }
41
42 void imparte(const int& s_mezin, std::vector<int>& a,
43 const int& k, std::vector<Fiu>& sol)
44 {
45 int cnt = -1, last = -1, s = 0;
46
47 for (int i = 0; i < a.size(); ++i) {
48 s += a[i];
49 if (s >= s_mezin) {
50 ++cnt;
51 sol[cnt].st = last + 2;
52 sol[cnt].dr = i + 1;
53 sol[cnt].s = s;
54 if (cnt == k - 1) {
55 sol[cnt].dr = a.size();
56 for (int j = i + 1; j < a.size(); ++j) {
57 s += a[j];
58 }
59 sol[cnt].s = s;
60 break;
61 }
62 last = i;
63 s = 0;
64 }
65 }
66
67 sort(sol.begin(), sol.end(), [](const Fiu& A, const Fiu& B) -> bool {
68 return A.s > B.s;
69 });
70
71 for (int i = 0; i < sol.size(); ++i) {
72 sol[i].ind = i + 1;
73 }
74
75 sort(sol.begin(), sol.end(), [](const Fiu& A, const Fiu& B) -> bool {
76 return A.st < B.st;
77 });
78 }
79
80 int main()
81 {
82 std::ifstream cin("mostenire.in");
83 std::ofstream cout("mostenire.out");
84
85 int n, k;
86 cin >> n >> k;
87 assert(k <= n && n <= N);
88 assert(2 <= k && k <= K);
89
90 std::vector<int> a(n);
91 long long stotal = 0;
92 for (int i = 0; i < n; ++i) {
93 cin >> a[i];
94 assert(1 <= a[i] && a[i] <= VALMAX);
95 stotal += a[i];
96 }
97
98 assert(stotal <= SMAX);
99
100 int mezin = 0;
101 for (int step = (1 << 30); step; step >>= 1) {
102 if (mezin + step <= stotal&& solve(mezin + step, a, k)) {
103 mezin += step;
104 }
105 }
106
107 assert(mezin != 0);
108 std::vector<Fiu> sol(k);
109 imparte(mezin, a, k, sol);
CAPITOLUL 2. OJI 2019 62
OJI 2018
3.1 Cuf r
Problema 1 - Cuf r 100 de puncte
Vr jitoarea cea bun are un cuf r în care este închis piatra magic de c tre piticii l zii cu
ajutorul unui cifru digital. Piticii i-au dat vr jitoarei o cutie în care sunt n cartona³e. Pe ecare
cartona³ este scris un num r natural pe care vr jitoarea îl va folosi s deschid lada. Valorile
scrise pe cartona³e sunt distincte între ele.
Pentru a aa cifrul trebuie s procedeze astfel: extrage ecare cartona³ din cutie ³i apoi
determin valoarea magic asociat num rului natural scris pe cartona³. Pentru ecare cartona³
valoarea magic este dat de al k -lea divizor prim al num rului înscris pe acesta. Vr jitoarea
trebuie s adune valorile magice obµinute pentru cele n cartona³e ³i apoi s introduc în ordine
cifrele valorii obµinute, pentru a descuia lada.
Cerinµe
Deoarece vr jitoarea nu are timp la dispoziµie v roag pe voi s o ajutaµi s rezolve urm toarele
probleme:
1. S ae valoarea magic pentru un cartona³ dat;
2. S ae cifrul cuf rului.
Date de intrare
Fi³ierul de intrare este cufar.in.
Pe prima linie a ³ierului de intrare se g sesc o valoare p care poate doar 1 sau 2 ³i num rul
n de cartona³e desp rµite prin câte un spaµiu.
Dac p este 1 pe linia a doua a ³ierului de intrare se g sesc dou valori reprezentând num rul
de pe cartona³ul dat ³i valoarea k , separate printr-un spaµiu, cu semnicaµia de mai sus.
Dac p este 2 pe urm toarele n linii ale ³ierului de intrare se g sesc câte dou valori, separate
prin câte un spaµiu, reprezentând num rul de pe cartona³ ³i valoarea lui k pentru ecare din cele
n cartona³e.
Date de ie³ire
Fi³ierul de ie³ire este cufar.out.
Dac valoarea lui p este 1, atunci se va rezolva doar cerinµa 1 ³i ³ierul de ie³ire va conµine pe
prima linie valoarea magic asociat cartona³ului dat.
Dac valoarea lui p este 2, atunci se va rezolva doar cerinµa 2 ³i ³ierul de ie³ire va conµine pe
prima linie cifrul necesar deschiderii cuf rului.
Restricµii ³i preciz ri
a 1 & n $ 1000000
a 2 & valoarea înscris pe un cartona³ & 1000000
a Se garanteaz c pentru ecare pereche (num r, k ), num r are cel puµin k divizori primi.
a Pentru rezolvarea corect a cerinµei 1 se acord 18 puncte
a Pentru rezolvarea corect a cerinµei 2 se acord 72 de puncte
a Pentru rezultate corecte la cerinµa a doua respectând restricµiile problemei ³i n & 1000 se
acord 18 puncte
63
CAPITOLUL 3. OJI 2018 64
a Pentru rezultate corecte la cerinµa a doua respectând restricµiile problemei ³i n & 500000 se
acord 43 de puncte
a Din ociu se acord 10 puncte.
Exemple
cufar.in cufar.out Explicaµii
11 5 p = 1, n = 1
30 3 Se rezolv doar prima cerinµ
Al 3-lea divizor prim al num rului 30 este 5
25 48 p = 2, n = 5
30 3 Se rezolv doar a doua cerinµ
64 1 Al 3-lea divizor prim al num rului 30 este 5
105 2 Primul divizor prim al num rului 64 este 2
1001 3 Al 2-lea divizor prim al num rului 105 este 5
5474 4 Al 3-lea divizor prim al num rului 1001 este 13
Al 4-lea divizor prim al num rului 5474 este 23
Suma c utat va S = 5 + 2 + 5 + 13 + 23,
de unde rezult cifrul 48
Se num r cu ajutorul ciurului lui Eratostene câµi divizori primi are ecare din numerele
naturale mai mici sau egale cu 1000000. În momentul când pentru unul din numerele scrise pe
cartona³e se ajunge la numarul de divizori c utat se adaug la sum valoarea num rului prim ce
a condus la atingerea num rului de divizori c utat.
31 for(i=1;i<=n;i++)
32 {
33 scanf("%d%d",&j,&c);
34 k[j]=c;
35 }
36
37 for(i=2;i<=1000000;i++)
38 if(a[i]==0)
39 for(j=1;j<=1000000/i;j++)
40 {
41 a[i*j]++;
42 if(a[i*j]==k[i*j])
43 {
44 s=s+i;
45 }
46 }
47
48 printf("%lld",s);
49 }
50
51 fclose(stdin);
52 fclose(stdout);
53 return 0;
54 }
3.2 fadema
Problema 2 - fadema 100 de puncte
Corina a cump rat de la magazin un material din pânz colorat , de form dreptunghiular
pentru a decupa din el o faµ de mas pentru masa din buc t rie. Fiindc este pasionat de ³ah,
Corina a ales un material format din n m p trate de aceea³i dimensiune colorate cu alb sau
negru. P tratele sunt lipite ³i sunt dispuse pe linii ³i coloane paralele cu laturile dreptunghiului din
pânz care a fost cump rat. Dou p trate se numesc vecine dac au în comun o latur . Materialul
din pânz nu respect neap rat structura unei table de ³ah, adic p tratele vecine pe aceea³i linie
sau pe aceea³i coloan nu sunt în mod necesar colorate în mod alternativ.
Corina î³i propune prin urmare s decupeze un dreptunghi cu un num r maxim de p trate,
paralel cu laturile dreptunghiului din pânz care a fost cump rat, care s respecte alternanµa
culorilor pe o tabl de ³ah.
Cerinµe
Sa se determine num rul maxim de p trate întregi ale unui dreptunghi cu laturile paralele cu
cele ale materialului cump rat, care poate decupat astfel încât s nu existe dou p trate vecine
având aceea³i culoare.
Date de intrare
Fi³ierul fadema.in conµine pe prima linie dou numere naturale n ³i m reprezentând num rul
de linii, respectiv num rul de coloane ale materialului din pânz care a fost cump rat.
Pe ecare dintre urm toarele n linii se a câte m cifre 0 sau 1 desp rµite prin câte un spaµiu,
reprezentând culorile p tratelor materialului. Cifra 0 codic culoarea alb , iar cifra 1 codic
culoarea neagr .
Date de ie³ire
Fi³ierul fadema.out va conµine pe prima linie un singur num r natural A, reprezentând nu-
m rul maxim de p trate ale unui dreptunghi care poate decupat astfel încât s respecte cerinµa
din enunµ. Dac nu exist dreptunghiuri cu cel puµin dou p trate având culori alternante, se va
scrie valoarea 1.
Restricµii ³i preciz ri
2 & N & 1000
a
2 & M & 1000
a
a Pentru rezolvarea corect a cerinµei respectând restricµiile problemei se acord 90 de puncte
a Pentru rezultate corecte respectând restricµiile problemei ³i n, m & 100 se acord 20 de
puncte
a Pentru rezultate corecte respectând restricµiile problemei ³i n, m & 200 se acord 40 de
puncte
a Pentru rezultate corecte respectând restricµiile problemei ³i n, m & 400 se acord 65 de
puncte
a Din ociu se acord 10 puncte
Exemple
fadema.in fadema.out Explicaµii
3 4 6 Dreptunghiul delimitat de liniile 1 ³i 3, respectiv coloanele 2 ³i
0 0 10 3 are 6 p trate (fundal de culoare gri)
1 1 00
1 0 10
4 5 5 Dreptunghiul delimitat de linia 2, respectiv coloanele 1 ³i 5 are
0 1 1 0 1 5 p trate (fundal de culoare gri)
1 0 1 0 1
0 0 1 1 0
1 1 0 1 1
Complexitate O n6 - 20 de puncte
4
Se genereaz în O n toate submatricile cuprinse între liniile i1 ³i i2, respectiv coloanele j1
2
³i j2. Fiecare asemenea submatrice se parcurge în O n ³i se veric validitatea sa.
Complexitate O n4 - 40 de puncte
Se construie³te ³irul r1, r2, ..., rn cu valori 0, 1 sau 2. rk (1 & k & n) va 0 dac
ak i este 0, rk 1 dac ak i 1 ³i rk 2 dac linia k a submatricei nu respect
condiµia de alternanµ . În continuare, se va c uta în ³irul r cea mai lung secvenµ alternant .
Fie L lungimea acesteia. Atunci num rul de elemente a submatricei alternante este L j i 1.
Soluµia va maximul acestor valori:
Complexitate O n3 - 65 de puncte
Se procedeaz ca mai sus, doar c validitatea liniei k se veric pe m sur ce se modic
lungimea liniei, adic odat cu cre³terea valorii j . Aceasta duce la eliminarea unei parcurgeri de
linie, iar complexitatea algoritmului scade cu un ordin de m rime.
Complexitate O n2 - 90 puncte
Calcul m submatricea de dimensiune maxim ce s-ar putea obµine pornind spre dreapta ³i în
jos de la ecare element al matricei ³i respect cerinµa din enunµ. Facem apoi acela³i calcul spre
sânga ³i în jos.
Realiz m suma dimensiunilor celor dou submatrici pentru ecare element al matricei ³i ma-
ximul dintre aceste sume este valoarea c utat .
Pentru a calcula submatricea de dimensiune maxima ce s-ar putea obµine pornind spre dreapta
³i în jos de la ecare element al matricei avem nevoie de:
a) Lungimea maxim lStij a unui ³ir de elemente cu proprietatea din enunµ pornind de la
2
ecare element aij al matricei spre stânga. Aceste lungimi pot calculate în O n parcurgân
matricea de la dreapta spre stânga. Pentru ecare element
aij ! aij 1 avem lStij lStij 1 1 ³i
Stij 1 pentru elementele cu aij aij 1 ³i pentru j m.
b) Lungimea maxim lJosij a unui ³ir de elemente cu proprietatea din enunµ pornind de
2
la ecare element aij al matricei în jos. Aceste lungimi pot calculate în O n parcurgând
matricea de jos în sus analog punctului a).
c) Produsul dintre lungimea maxim lJosij ³i minimul lungimilor maxime lSt al elemen-
telor care aparµin sub³irului lJosij (adic minimul valorilor lStk j al elementrlor ak j
pentru k i, i 1, ..., i lJosij reprezint dimensiunea submatricei. Aceste minime pot
2
calculate în O n pentru toat matricea parcurgând-o de jos în sus ³i p strând minimul dintre
lStij ³i lStij 1 pentru toate elementele aij ! aij 1 iar pentru elementele cu
aij aij 1 ³i pentru j m p stram lStij .
Analog se procedeaz ³i pentru submatricea de dimensiune maxima ce s-ar putea obµine por-
nind spre stânga ³i în jos de la ecare element al matricei.
Observaµie: la punctajele de mai sus se adaug 10 puncte din ociu
41 }
42 }
43 }
44 }
45
46 for(int i=1;i<=n;i++)
47 {
48 for(int j=1;j<=m;j++)
49 {
50 if(j==1)
51 {
52 mr1[i][j]=1;
53 }
54 else
55 {
56 if(a[i][j]+a[i][j-1]==1)
57 {
58 mr1[i][j]=mr1[i][j-1]+1;
59 }
60 else
61 {
62 mr1[i][j]=1;
63 }
64 }
65 }
66 }
67
68 for(int i=1;i<=n;i++)
69 {
70 for(int j=1;j<=m;j++)
71 {
72 if(i==1)
73 {
74 mc1[i][j]=mr1[i][j];
75 mc2[i][j]=mr2[i][j];
76 mc[i][j]=1;
77 }
78 else
79 {
80 if(a[i][j]+a[i-1][j]==1)
81 {
82 mc1[i][j]=min(mc1[i-1][j],mr1[i][j]);
83 mc2[i][j]=min(mc2[i-1][j],mr2[i][j]);
84 mc[i][j]=mc[i-1][j]+1;
85 }
86 else
87 {
88 mc1[i][j]=mr1[i][j];
89 mc2[i][j]=mr2[i][j];
90 mc[i][j]=1;
91 }
92 }
93 }
94 }
95
96 int M=1;
97 for(int i=1;i<=n;i++)
98 {
99 for(int j=1;j<=m;j++)
100 {
101 if(M<mc[i][j]*(mc1[i][j]+mc2[i][j]-1))
102 M=mc[i][j]*(mc1[i][j]+mc2[i][j]-1);
103 }
104 }
105
106 out << M << endl;
107 return 0;
108 }
3.3 tnia
Problema 3 - tnia 100 de puncte
Se d o matrice binar cu n coloane ³i m linii. Coloanele sunt numerotate de la stânga la
dreapta cu valori de la 1 la n, iar liniile sunt numerotate de jos în sus cu valori de la 1 la m.
Matricea dat are o form particular , astfel c pentru ecare coloan i de la 1 la n toate
elementele matricei de pe coloana respectiv au valoarea 1 pentru toate liniile cuprinse în intervalul
1, hi ³i în rest valoarea 0. Valorile hi sunt numere naturale date în ordine cresc toare
(hi 1 & hi, 1 & i & n).
Cerinµe
S se r spund la q întreb ri de forma: dându-se numerele A, B , C , D se cere suma elementelor
din submatricea determinat de zona dreptunghiular având colµul stânga-jos în coloana A ³i linia
B , iar colµul dreapta-sus în coloana C ³i linia D.
Date de intrare
Fi³ierul de intrare este tnia.in.
a pe prima linie se g sesc dou numere naturale n ³i m desp rµite printr-un spaµiu, cu semni-
caµia de mai sus;
a pe a doua linie sunt cele n elemente hi ale vectorului desp rµite prin câte un spaµiu;
a pe a treia linie este un num r natural q ce reprezint num rul de întreb ri;
a pe urm toarele q linii se g sesc câte 4 numere A, B , C , D cu semnicaµia de mai sus,
desp rµite prin câte un spaµiu.
Date de ie³ire
Fi³ierul de ie³ire tnia.out va conµine q linii reprezentând r spunsul pentru ecare întrebare.
Restricµii ³i preciz ri
a 0 & hi & m, 1 & n & 100000
a 1 & q & 100000, 1 & m & 1000000000
a Pentru 15 puncte: n, m, q & 100
a Pentru alte 16 puncte: n, m, q & 3000
a Pentru alte 16 puncte: n & 100000, m & 1000000000, q & 100
a Pentru rezolvarea corect a cerinµei se acord 90 de puncte
a Din ociu se acord 10 puncte.
Exemple
tnia.in tnia.out Explicaµii
5 10 30 Zona dreptunghiular având colµul stânga-jos la coloana 1 ³i
2 3 7 8 10 6 linia 1 ³i colµul dreapta-sus la coloana 5 ³i linia 10 are suma
5 5 elementelor 30.
1 1 5 10 0 Analog, pentru celelalte patru întreb ri, r spunsurile corecte
2 5 4 7 6 sunt: 6, 5, 0 ³i 6
3 2 3 6
3 8 3 10
3 2 3 10
Putem construi iniµial întreaga matrice. Pentru ecare query (întrebare), parcurgem subma-
tricea ³i facem suma elementelor.
2
Complexitate: O N Q
26 }
27
28 scanf("%d",&q);
29 for(int i = 1; i <= q; i++)
30 {
31 scanf("%d%d%d%d",&downL.x,&downL.y,&topR.x,&topR.y);
32
33 long long answer = 0;
34 for(int line = downL.x; line <= topR.x; line++)
35 for(int colum = downL.y; colum <= topR.y; colum++)
36 answer += matrix[line][colum];
37
38 printf("%d\n", answer);
39 }
40
41 return 0;
42 }
31 return answer;
32 }
33
34 int main ()
35 {
36
37 freopen("tnia.in","r",stdin);
38 freopen("tnia.out","w",stdout);
39
40 scanf("%d%d",&n,&m);
41 for(int i = 1; i <= n; i++)
42 scanf("%d",&height[i]);
43
44 for(int i = 1; i <= n; i++)
45 partial_sums[i] = partial_sums[i - 1] + height[i];
46
47 scanf("%d",&q);
48 for(int i = 1; i <= q; i++)
49 {
50 scanf("%d%d%d%d", &downL.x, &downL.y, &topR.x, &topR.y);
51
52 int poz1 = binarySearch(downL.x, topR.x, downL.y);
53 int poz2 = binarySearch(downL.x, topR.x, topR.y);
54
55 // printf("am obtinut %d %d\n", poz1, poz2);
56
57 printf("%lld\n", partial_sums[poz2] -
58 partial_sums[poz1] -
59 ((long long)poz2 - poz1) * (downL.y - 1) +
60 ((long long)topR.x - poz2) * (topR.y - downL.y + 1));
61 }
62
63 return 0;
64 }
OJI 2017
4.1 Ace
Problema 1 - Ace 100 de puncte
Pe o zon în form de dreptunghi cu laturile de lungimi N ³i M se g sesc N M p trate de
latur 1. În centrul ec rui p trat se g se³te înpt câte un ac de grosime neglijabil . Fiecare
ac este descris de în lµimea sa. Aceast zon se poate reprezenta ca un tablou bidimensional de
dimensiuni N ³i M , iar ecare element din matrice reprezint în lµimea (num r natural nenul)
ec rui ac. În centrul p tratului N, M exist o camer de luat vederi de ultim generaµie,
o
mobil , care se poate roti cu 360 în orice plan, situat la nivelul solului. Dimensiunile camerei
sunt neglijabile. De exemplu, dac avem zona sub forma:
Cerinµe
1. Câte ace vede camera de luat vederi dac se poate roti în plan vertical, doar în direcµiile N
³i V ?
2. Câte ace vede camera de luat vederi dac se poate roti în orice plan ³i în orice direcµii?
Date de intrare
Fi³ierul de intrare ace.in conµine pe prima linie num rul P care poate 1 sau 2, pentru prima,
respectiv a doua cerinµ . Pe a doua linie se g sesc numerele N , M reprezentând dimensiunile
tabloului, apoi pe urm toarele N linii câte M numere naturale, desp rµite prin câte un spaµiu,
reprezentând în lµimile acelor.
77
CAPITOLUL 4. OJI 2017 78
Date de ie³ire
Fi³ierul de ie³ire ace.out va conµine pe prima linie num rul de ace v zute pentru cerinµ
indicat de valoarea num rului P .
Restricµii ³i preciz ri
a2 & N & 1000
a2 & M & 1000
a Elementele matricei sunt numere naturale nenule mai mici decât 1000, cu excepµia num rului
de pe linia N ³i coloana M care este 0.
a Pentru rezolvarea corect a cerinµei 1 se acord 20 puncte, pentru rezolvarea corect a cerinµei
2 se acord 70 de puncte, iar din ociu se acord 10 de puncte.
a Pentru cerinµa 2 exist teste în valoare de 20 puncte cu N, M & 50.
a Pentru cerinµa 2 exist teste în valoare de 45 puncte cu N, M & 100.
Exemple
ace.in ace.out Explicaµii
1 3 Pentru cerinµa 1 avem direcµiile N ³i V:
4 4 Pentru direcµia N, camera va vedea acul de coordonatele (3,4) -
8 5 4 7 în totalitate, iar acul (2,4) se va vedea doar parµial. Acul (1,4)
2 7 4 6 nu se va vedea pentru c este acoperit total de (2,4).
5 5 3 2 în direcµia V, camera va vedea doar acul (4,3), deoarece acele
6 6 3 0 (4,2) ³i (4,1) sunt acoperite total de acul (4,3).
2 11 Pentru cerinµa 2 camera va vedea cele 3 ace din direcµiile N
4 4 ³i V(vezi mai sus) ³i 8 pentru celelalte direcµii se vor vedea
8 5 4 7 parµial sau în totalitate acele (3,3), (3,2), (3,1), (2,3), (1,3),
2 7 4 6 (2,2), (2,1),(1,2). Acul (1,1) nu se vede din cauza celui de pe
5 5 3 2 (2,2) care il acoper total. Acul (2,2) se vede doar parµial, pentru
6 6 3 0 c o parte din el este acoperit de acul (3,3).
2 8 Pentru cerinµa 2 camera va vedea în N (3,3), (2,3), în V va
4 3 vedea (4,2). în celelalte direcµii camera va vedea parµial sau în
5 4 7 totalitate acele (3,2), (3,1), (2,2), (1,2), (1,1).
6 4 6
5 3 2
6 3 0
36 mai_mare(j,a[n][i]);
37
38 return k;
39 }
40
41 void rezolva_2()
42 {
43 //parcurg matricea din coltul dreapta_jos spre 1,1
44 // si merg pe "diagonale"
45 int i,j,difx,dify,l,c;
46 for(i=n-1;i>=1;i--)
47 for(j=m-1;j>=1;j--)
48 if(a[i][j]!=-1)
49 {
50 xmax=m-j;
51 ymax=a[i][j];
52 k++;
53 difx=n-i;
54 dify=m-j;
55 a[i][j]=-1;
56 for(l=i-difx,c=j-dify;l>=1&&c>=1;l-=difx,c-=dify)
57 if(a[l][c]!=-1)
58 {
59 mai_mare(m-c,a[l][c]);
60 a[l][c]=-1;
61 }
62 }
63
64 fout<<k<<’\n’;
65 }
66
67 void citire()
68 {
69 int i,j;
70 fscanf(fin,"%d",&ct);
71 fscanf(fin,"%d",&n);
72 fscanf(fin,"%d",&m);
73
74 for(i=1;i<=n;i++)
75 for(j=1;j<=m;j++)
76 fscanf(fin,"%d",&a[i][j]);
77
78 rez_a=rezolva_1();
79 if(ct==1)
80 {
81 fout<<rez_a<<’\n’;
82 return;
83 }
84
85 rezolva_2();
86 }
87
88 int main()
89 {
90 citire();
91 return 0;
92 }
16
17 for(i=N;i>=1;i--)
18 {
19 for(j=M;j>=1;j--)
20 {
21 fin>>a[i][j];
22 }
23 }
24
25 if(P==1)
26 {
27 r=1;
28 i=2;
29 for(j=i+1;j<=M;j++)
30 {
31 if(a[1][j]*(i-1)>a[1][i]*(j-1))
32 {
33 r++;
34 i=j;
35 }
36 }
37
38 r++;
39 j=2;
40 for(i=j+1;i<=N;i++)
41 {
42 if(a[i][1]*(j-1)>a[j][1]*(i-1))
43 {
44 r++;
45 j=i;
46 }
47 }
48
49 fout<<r;
50 }
51
52 if(P==2)
53 {
54 r=0;
55 for(i=1;i<=N;i++)
56 {
57 for(j=1;j<=M;j++)
58 {
59 if(i>1 || j>1)
60 {
61 if(b[i][j]==0)
62 {
63 b[i][j]=1; r++;
64 i1=i;j1=j;
65 ii=i;jj=j;
66 l1=i1-1;k1=j1-1;
67 while(ii+l1<=N && jj+k1<=M)
68 {
69 i2=ii+l1; j2=jj+k1;
70 long long v1=(long long)a[i2][j2]*a[i2][j2]*
71 ((i1-1)*(i1-1)+(j1-1)*(j1-1));
72 long long v2=(long long)a[i1][j1]*a[i1][j1]*
73 ((i2-1)*(i2-1)+(j2-1)*(j2-1));
74 if(v1>v2)
75 {
76 r++;
77 i1=i2;j1=j2;
78 b[i2][j2]=1;
79 }
80 else
81 {
82 b[i2][j2]=2;
83 }
84
85 ii=i2;jj=j2;
86 }
87 }
88 }
89 }
90 }
91
CAPITOLUL 4. OJI 2017 83
92 fout<<r;
93 }
94
95 fout.close();
96 return 0;
97 }
2 #include <bits/stdc++.h>
3
4 using namespace std;
5 int pp, N, M, i, j, x, y, l, c, h, hmax, p, q, nr, vede, pozl, pozc, min1;
6 int a[1005][1005], b[1005][1005];
7
8 int main()
9 {
10 freopen("ace.in", "r", stdin);
11 freopen("ace.out", "w", stdout);
12
13 scanf("%d\n", &pp);
14 scanf("%d%d\n", &N, &M );
15
16 min1=100004;
17 x = N;
18 y = M;
19 for ( i = 1; i<= N; i++)
20 for ( j =1; j<=M; j++)
21 scanf("%d",&a[i][j]);
22
23 vede = 0;
24 nr=0;
25 hmax = 0;
26 for (i = 1;i < x; i++)
27 if (nr == 0)
28 {
29 hmax = a[x-i][M];
30 b[x-i][M] = 2;
31 nr = 1;
32 pozl = i;
33 vede++;
34 }
35 else
36 {
37 if (a[x-i][M] * pozl > i * hmax)
38 {
39 pozl = i;
40 hmax = a[x - i][M];
41 b[x-i][M] = 2;
42 vede++;
43 }
44 }
45
46 nr=0;
47 hmax = 0;
48 for (i = 1;i < y; i++)
49 if (nr == 0)
50 {
51 hmax = a[N][y - i];
52 nr = 1;
53 pozl = i;
54 vede++;
55 }
56 else
57 {
58 if (a[N][y-i] * pozl > i * hmax)
59 {
60 pozl = i;
61 hmax = a[N][y - i];
62 vede++;
63 }
64 }
65
66 if (pp == 1)
67 {
68 printf("%d\n",vede);
69 return 0;
70 }
71
72 for (l=1; l<x; l++)
73 for (c=1; c<y; c++)
74 {
75 h = 0;
76 p = x;
77 q = y;
CAPITOLUL 4. OJI 2017 85
78 nr = 0;
79 for (i = 1; i*l < x&& i*c <y ; i++)
80 {
81 if (b[p-i*l][q-i*c]==0)
82 {
83 b[p-i*l][q-i*c]=1;
84 if (nr==0)
85 {
86 hmax = a[p-i*l][q-i*c];
87 pozl = i;
88 vede++;
89 b[p-i*l][q-i*c]=2;
90 nr++;
91 }
92 else
93 if ((a[p-i*l][q-i*c]-h) * (pozl) > i * (hmax -h))
94 {
95 pozl = i;
96 hmax = a[p - i*l][q - i*c];
97 vede++;
98 b[p-i*l][q-i*c]=2;
99 }
100 }
101 }
102 }
103
104 printf("%d\n",vede);
105 return 0;
106 }
4.2 Admitere
Problema 2 - Admitere 100 de puncte
S ne imagin m faptul c la un anumit liceu exist doar dou clase per generaµie: una de Real
³i una de Uman. În prezent au loc înscrierile pentru clasa a IX-a. Cele dou clase au ecare câte
M locuri disponibile, atât la Real, cât ³i la Uman. Dac lista de elevi înscri³i la o anumit clas
conµine mai mult de M elevi, vor admi³i acei M elevi care au notele cele mai mari. Ambele clase
au deja M elevi înscri³i, iar pentru ecare se ³tie nota cu care a fost înscris la clasa respectiv .
Mai exist îns N elevi, singurii înc neînscri³i, care sunt privilegiaµi în acest proces (indc
au terminat gimnaziul la acest liceu). Privilegiul lor const în urm torul fapt: ei se pot înscrie
acum, dup ce înscrierile publice au fost încheiate, ³i se cunosc notele de înscriere la ambele clase.
Fiecare din cei N elevi are câte dou note: nota cu care ar înscris la Real ³i nota cu care ar
înscris la Uman (acestea pot diferite, deoarece examenele de admitere de la cele dou clase
difer ). Fiecare din cei N elevi va alege s se înscrie în maxim o clas . Ei î³i vor coordona alegerile
astfel încât s maximizeze num rul de elevi admi³i. Deoarece calculele devin destul de complicate,
ace³tia s-ar putea folosi de ajutorul vostru. Ei doresc r spunsul la urm toarele dou întreb ri:
Cerinµe
(1) Care este num rul maxim de elevi privilegiaµi care pot admi³i dac se pune restricµia
suplimentar ca toµi elevii privilegiaµi admi³i s e admi³i la aceea³i clas ?
(2) Care este num rul maxim de elevi privilegiaµi care pot admi³i dac ace³tia se pot înscrie
la clase diferite?
Date de intrare
Fi³ierul de intrare admitere.in conµine pe primul rând o valoare egal cu 1 sau 2, reprezentând
cerinµa ce urmeaz a rezolvat . Urm toarea linie conµine cele dou numere N ³i M . Pe al treilea
rând se a M numere, separate prin câte un spaµiu, reprezentând notele cu care au fost înscri³i
elevii care formeaz momentan clasa de Real. Pe al patrulea rând se a M numere, separate
prin câte un spaµiu, reprezentând notele cu care au fost înscri³i elevii care formeaz momentan
clasa de Uman. Urm toarele N linii vor conµine câte o pereche de numere Ri, U i, separate
CAPITOLUL 4. OJI 2017 86
prin câte un spaµiu, reprezentând nota cu care al i-lea elev privilegiat s-ar înscrie la clasa de Real,
respectiv la clasa de Uman.
Date de ie³ire
Fi³ierul de ie³ire admitere.out va conµine pe prima linie valoarea M AX : num rul maxim de
¬ ¬ ¬ ¬ ¬ ¬
elevi privilegiaµi admi³i. A doua linie va conµine un ³ir de N caractere din mulµimea r R , U , X x,
care va descrie scenariul optim. Dac al i-lea elev va înscris la Real, al i-lea caracter va egal
¬ ¬ ¬ ¬
cu R . Dac al i-lea elev va înscris la Uman, al i-lea caracter va egal cu U . Dac acesta nu
¬ ¬
va înscris nic ieri, al i-lea caracter va egal cu X .
Deoarece elevii nu vor s depun efort inutil, un elev privilegiat care nu va admis în scenariul
optim nu se va înscrie la nicio clas . Cu alte cuvinte, pentru ca scenariul descris s e considerat
¬ ¬
corect este necesar ca exact M AX caractere din ³ir s e diferite de X .
Restricµii ³i preciz ri
a 1 & N, M & 2000
a Teste în valoare total de 25 de puncte vor solicita rezolvarea cerinµei (1), iar restul de 65
de puncte vor solicita rezolvarea cerinµei 2. Din ociu sunt acordate 10 puncte.
a Pentru cerinµa 2, teste în valoare total de 45 de puncte vor avea 1 & N, M & 150
a Toate cele N M note pentru clasa de Real sunt distincte dou câte dou . Acela³i lucru
este valabil ³i în cazul notelor pentru clasa de Uman.
a Toate notele sunt numere naturale din intervalul 1, 4000.
a Notele elevilor deja înscri³i de la clasa de Real, respectiv Uman vor date în ordine cresc -
toare.
a în cazul în care exist mai multe soluµii corecte, este acceptat oricare dintre acestea.
Exemple
admitere.in admitere.out Explicaµii
1 1 Nu este posibil ca ambii elevi s e admi³i la aceea³i clas .
23 XR Exist mai multe soluµii în care un singur elev este admis:
246 XR, XU, RX. Oricare din acestea este corect .
678
35
12 14
2 2 Deoarece acum rezolv m cerinµa (2), ne este permis s
23 RU înscriem elevii la clase diferite. Exist o soluµie în care
246 ambii elevi sunt admi³i, iar aceasta este unic : cea în care
678 elevul 1 este înscris la Real (el nu putea admis la Uman
35 indiferent de decizia celui de-al doilea elev), iar cel de-al
12 14 doilea elev este înscris la Uman.
Vom face acelasi lucru pentru clasa de Uman si vom pastra maximul dintre cele doua valori.
Cerinµa 2
În primul rând, s not m c prima cerinµ trebuie luat în calcul în soluµia celei de a doua.
Astfel, în continuare vom presupune c exist cel puµin un elev privilegiat admis în ambele clase.
La modul informal, dicultatea problemei const în faptul c avem de f cut multe alegeri,
iar acestea se inuenµeaz reciproc. în asemenea situaµii poate util s ne restrângem opµiunile,
încercând s rezolv m o problem mai particular . S analiz m, spre exemplu, cum putem rezolva
urm toarea variant a problemei:
(1) Este posibil s -i admitem pe toµi cei N elevi privilegiaµi?
Este clar c soluµia problemei originale trebuie s trateze implicit sau explicit aceast întrebare
(r psunsul pozitiv ar indica o soluµie clar optim ).
În ce fel este mai u³oar aceast problem ? în problema original exista un factor de nesigu-
ranµ în îns ³i decizia de a încerca s admitem un anumit elev (f r a decide ³i clasa la care am
face acest lucru). Poate c în toate soluµiile optime respectivul elev ar r mas înafara liceului.
în aceast variant trebuie s -i admitem pe toµi, iar acest lucru ne reduce din opµiuni.
Acum putem intui, în termeni informali, c dicultatea în a-i admite pe toµi cei N elevi st în
a-i admite pe cei mai slabi dintre ei. Ce ar însemna totu³i ca un elev s e mai slab decât altul?
Putem argumenta credibil c elevul cu notele (4, 4) este mai slab decât elevul cu notele (10, 10),
dar se pot compara elevii cu notele (4, 10), respectiv (10, 4)? Faptul c elevii sunt bidimensionali
pare s ne pun dicult µi, a³a c poate o idee bun s restrângem din nou problema.
(2) Este posibil s -i admitem pe toµi cei N elevi privilegiaµi ³tiind c ecare dintre ace³tia are
nota de înscriere de la Uman egal cu cea de la Real?
Beneciul acestei constrângeri este c acum avem un cel mai slab elev! Este clar c indiferent
de clasa la care va admis, el va ultimul elev privilegiat admis la clasa respectiv . Vom încerca
pe rând s -l admitem la Real, respectiv Uman.
S presupunem c el va admis la Real. Analizând cele M note care exist deja la Real,
not m c exist P note mai mari decât a sa. Dac P M , el nu poate admis la Real indiferent
de alegerile celorlalµi privilegiaµi. Dac P $ M , el poate admis la Real ³i, mai important, putem
admite înc M P 1 elevi privilegiaµi la Real f r a-l elimina pe elevul cel mai slab. S numim
valoarea M P 1 SPATIU_REAL.
Este optim s aducem cât mai mulµi elevi la Real, respectând acest limit de SPATIU_REAL,
deoarece astfel u³ur m situaµia elevilor r ma³i care vor încerca s e admi³i la Uman. întreba-
rea este acum pe care SPATIU_REAL dintre cei N 1 elevi este optim s -i admitem la Real?
Urm rind din nou s u³ur m situaµia celor care vor r mâne la Uman, îi vom admite la Real pe
cei SPATIU_REAL cu cele mai mici note. Pentru a argumenta c aceast decizie cre³te ³ansele
elevilor care se vor înscrie la Uman ne amintim de la cerinµa 1 c dac exist în general o soluµie
cu K elevi admi³i la o clas , exist ³i una în care ace³ti K sunt cei cu cele mai mari note dintre
cei disponibili. în acela³i timp, nu risc m nimic prin a aduce elevi cu note mici la Real, deoarece
³tim c am avut grij s r mân admis acolo cel mai slab elev, fapt care ne asigur c orice alt
elev înscris la Real va de-asemenea admis.
Dac acest algoritm nu reu³e³te s admit toµi elevii, vom încerca s admitem elevul cel mai
slab la clasa de Uman. Dac nici în acest fel nu se g se³te soluµie, ea nu exist (cel mai slab
elev trebuie s e admis undeva, iar în ambele scenarii am luat decizii optime care s faciliteze
admiterea celorlalµi).
Ce complexitate are acest algoritm? Detaliile variaz , dar exist implement ri simple cu
complexitate O N M N N . Este util (dar nu strict necesar ) o sortare a celor N elevi,
care poate f cut în complexitate O N N . Este de-asemenea util s ³tim pentru ecare elev
³i ecare clas câte dintre cele M note deja înscrise sunt mai mari decât nota elevului respectiv.
Acest lucru se poate calcula u³or în O N M . Simularea algoritmului descris mai sus ³i vericarea
faptului c toµi elevii sunt admi³i poate f cut combinând aceste dou informaµii precalculate.
Astfel, avem o rezolvare satisf c toare ca timp de execuµie pentru subproblema (2). Vom
încerca acum s folosim ideile de la (2) pentru a rezolva subproblema (1). Dicultatea este
bineînµeles c nu mai avem neaparat un cel mai slab elev. Totu³i, vom avea înc un ultim elev
privilegiat admis în clasa de Real. Cine va acesta în soluµia optim ? Nu ³tim, dar putem
presupune, pe rând, despre ecare dintre cei N elevi c va lua aceast poziµie. Având elevul X
xat ca ind ultimul privilegiat admis la Real, suntem prezentati cu un scenariu similar celui din
(2). ³tim c mai putem admite SPATIU_REAL(X ) (aceast valoare variaz în funcµie de X ) elevi
la clasa de Real f r s -l elimin m pe X . Din nou, este de dorit s admitem cât mai mulµi elevi
la Real (luând în calcul aceast limit ). Trebuie îns s m mai atenµi în a analiza pe care din cei
N 1 elevi s -i admitem. în primul rând, ace³tia trebuie s aib nota de la Real strict mai mare
CAPITOLUL 4. OJI 2017 88
decât nota lui X , indc altfel invalid m poziµia sa de ultim admis. Filtrând dup acest criteriu,
are sens în continuare s alegem elevii cu notele cele mai mici la Uman, din acela³i raµionament
de a cre³te ³ansele celor înscri³i la Uman de a admi³i.
Care este complexitatea acestei rezolv ri? Principala schimbare faµ de algoritmul pentru (2)
este c vom varia ultimul elev de la real. Exist N variante pe care le lu m în calcul. Astfel,
pentru a menµine o complexitate p tratic este necesar s calcul m în O N componenµa optim
a claselor, având un ultim elev xat. Acest lucru se poate face folosind acelea³i precalcul ri de la
(2).
Avem astfel o rezolvare pentru subproblema (1). Trecerea c tre soluµia problemei originale se
face acum foarte u³or. R mâne înc adev rat c în orice soluµie optim vom avea un ultim elev
înscris la Real ³i c putem presupune care este acesta. Mai mult, modalitatea de a alege clasa
pentru ceilalµi N 1 elevi având acest ultim elev xat este înc optim . Se poate observa din
argumentele aduse în cadrul discuµiei subproblemei (1) c dac metoda e³ueaz în a-i admite pe
toµi cei N 1 elevi r ma³i, reu³e³te totu³i s admit num rul de elevi maxim posibil.
R mân de soluµionat unele detalii de implementare necesare pentru ca algoritmul s aib
complexitate p tratic . Pentru indicii în acest sens puteµi consulta sursa ocial .
Este util acum s analiz m procesul prin care am ajuns la soluµie. Observ m c ideea critic
a problemei este cea de a varia ultimul elev admis la o anumit clas . Aceast idee ne-a putut
util din dou motive:
- Exist un num r restrâns de opµiuni pe care le putem alege (N ), deci le putem încerca pe
toate, f r a face vreo speculaµie riscant în leg tur cu cea optim .
- Odat aleas o opµiune, multe alte decizii ale algoritmului sunt forµate, iar cele r mase pot
soluµionate u³or.
Pentru a ajunge la aceast idee, am simplicat problema (impunându-ne constrângeri noi) pâna
la punctul în care exista un cel mai slab elev, iar acesta trebuia neaparat s e admis. Acesta este,
bineînµeles, doar un r de gândire din multe posibile, dar autorul îl consider educativ în vederea
abord rii problemelor de acest tip.
111 }
112 }
113
114 config = realityCheck(config);
115 int temp = 0;
116 for(int i = 0; i < n; ++i)
117 if(config[i] != ’X’)
118 temp++;
119
120 if(temp > bestAns)
121 {
122 bestAns = temp;
123 bestConfig = config;
124 }
125 }
126
127 cout << bestAns << "\n";
128 cout << bestConfig << "\n";
129 }
54
55 for(int c = 0; c < 2; ++c)
56 for(int i = 0; i < n; ++i)
57 for(int j = 0; j < m; ++j)
58 if(fixedGrades[c][j] > currGrades[i][c])
59 frontAlready[c][i]++;
60
61 int bestAns = 0;
62 string bestConfig(n, ’X’);
63 string label = "RU";
64
65 // Functia realityCheck preia un string cu optiunile de inscriere
66 // ale celor N elevi
67 // si il "aduce la realitate", punand ’X’ in dreptul elevilor care
68 // nu sunt admisi
69 // la clasa aleasa. Complexitatea functiei este O(N).
70
71 auto realityCheck = [&] (string config) -> string {
72 for(int c = 0; c < 2; ++c)
73 {
74 int greaterFriends = 0;
75 for(int i = n - 1; i >= 0; --i)
76 { // parcurgem elevii privilegiati inscrisi la clasa c
77 // in ordine descrescatoare dupa nota
78 if(config[p[c][i]] != label[c])
79 continue;
80
81 // greaterFriends = cati elevi privilegiati inscrisi
82 // la clasa c au fost admisi deja
83 // frontAlready[..] = cati elevi din cei M initiali
84 // aveau note mai mari decat cel curent
85 // pozitia elevului curent este data de suma acestor
86 // doua valori + 1
87 // daca este >= m, elevul este respins
88
89 if(greaterFriends + frontAlready[c][p[c][i]] >= m)
90 config[p[c][i]] = ’X’;
91 greaterFriends++;
92 }
93 }
94 return config;
95 };
96
97 // Cerinta 1
98
99 for(int c = 0; c < 2; ++c)
100 {
101 string config(n, label[c]); // toti elevii se inscriu la clasa c
102 config = realityCheck(config); // config ne spune acum care elevi
103 // au ramas efectiv admisi la clasa c
104
105 int temp = 0;
106 for(int i = 0; i < n; ++i)
107 if(config[i] != ’X’)
108 ++temp;
109
110 if(temp > bestAns)
111 { // actualizam raspunsul cel mai bun
112 bestAns = temp;
113 bestConfig = config;
114 }
115 }
116
117 if(tip == 1)
118 {
119 cout << bestAns << "\n";
120 cout << bestConfig << "\n";
121 return 0;
122 }
123
124
125 //Cerinta 2
126
127 const int REAL = 0, UMAN = 1;
128
129 for(int minReal = 0; minReal < n; ++minReal)
CAPITOLUL 4. OJI 2017 92
28 {
29 for(int i=1;i<=n;i++)
30 fin>>a[i];
31
32 sort(a+1,a+n+1);
33 }
34
35 int V, M, N, u[4005], r[4005], sr[4005], su[4005],
36 pozu[4005], upoz[4005], pozr[4005], rpoz[4005], vr, vu;
37
38 char x[4005], y[4005];
39
40 int main()
41 {
42 int i,j,k,l,p,rez,aux,c,cr,cu;
43
44 fin>>V>>N>>M;
45
46 citire_sort(r,M);
47 citire_sort(u,M);
48
49 vr=2000000000;
50 vu=2000000000;
51 for(i=1;i<=N;i++)
52 {
53 fin>>sr[i]>>su[i];
54 vr=min(vr,sr[i]);
55 vu=min(vu,su[i]);
56 pozu[i]=i;
57 pozr[i]=i;
58 x[i]=’X’;
59 y[i]=’X’;
60 }
61
62 for(i=1;i<=N-1;i++)
63 for(j=i+1;j<=N;j++)
64 if(sr[pozr[i]]>sr[pozr[j]])
65 {
66 aux=pozr[i];
67 pozr[i]=pozr[j];
68 pozr[j]=aux;
69 }
70 ///for(i=1;i<=N;i++) rpoz[pozr[i]]=i;
71
72 for(i=1;i<=N-1;i++)
73 for(j=i+1;j<=N;j++)
74 if(su[pozu[i]]>su[pozu[j]])
75 {
76 aux=pozu[i];
77 pozu[i]=pozu[j];
78 pozu[j]=aux;
79 }
80
81 for(i=1;i<=N;i++)
82 upoz[pozu[i]]=i;
83
84 for(i=1;i<=N;i++)
85 y[i]=’X’;
86
87 i=N;
88 j=M;
89 k=0;
90 cr=0;
91 pozr[0]=0;
92 sr[0]=0;
93 r[0]=0;
94
95 for(k=M;k>=1;k--)
96 {
97 if(sr[pozr[i]]>r[j])
98 {
99 y[pozr[i]]=’R’;
100 cr++; i--;
101 }
102 else
103 {
CAPITOLUL 4. OJI 2017 94
104 j--;
105 }
106 }
107
108 rez=cr;
109
110 for(i=1;i<=N;i++)
111 x[i]=’X’;
112
113 i=N;
114 j=M;
115 k=0;
116 cu=0;
117 pozu[0]=0;
118 su[0]=0;
119 u[0]=0;
120 for(k=M;k>=1;k--)
121 {
122 if(su[pozu[i]]>u[j])
123 {
124 x[pozu[i]]=’U’;
125 cu++; i--;
126 }
127 else
128 {
129 j--;
130 }
131 }
132
133 if(cu>rez)
134 {
135 rez=cu;
136 for(i=1;i<=N;i++)y[i]=x[i];
137 }
138
139 if(V==1)
140 {
141 fout<<rez<<"\n";
142 fout<<y+1;
143 }
144
145 for(i=1;i<=N;i++)
146 {///O(N)
147 p=pozmin(u,M,su[i]);///log(M)
148 if(p>=1)
149 {
150 for(j=1;j<=N;j++)
151 x[j]=’X’;///O(N)
152
153 c=1;
154 x[i]=’U’;
155 for(j=1;j<=N;j++)///O(N)
156 if(upoz[pozr[j]]>upoz[i] && c<p)
157 {
158 x[pozr[j]]=’U’;
159 c++;
160 }
161
162 l=N;
163 j=M;
164 k=0;
165 pozr[0]=0;
166 sr[0]=0;
167 r[0]=0;
168 for(k=M;k>=1;k--)
169 {///O(M)
170 while(l>0 && x[pozr[l]]!=’X’)
171 l--;
172
173 if(sr[pozr[l]]>r[j])
174 {
175 x[pozr[l]]=’R’;
176 c++; l--;
177 }
178 else
179 {
CAPITOLUL 4. OJI 2017 95
180 j--;
181 }
182 }
183
184 if(c>rez)
185 {
186 rez=c;
187 for(j=1;j<=N;j++)
188 {
189 y[j]=x[j];
190 }
191 }
192 }
193 }
194
195 if(V==2)
196 {
197 fout<<rez<<"\n";
198 fout<<y+1;
199 }
200
201 fin.close();
202 fout.close();
203 return 0;
204 }
4.3 Roboµi
Problema 3 - Roboµi 100 de puncte
tefan a împlinit 15 ani. Fiind un pasionat membru al Clubului de Robotic , familia i-a d ruit
de ziua lui foarte mulµi roboµi, ecare dotat cu o arm de o anumit putere. El a a³ezat toµi roboµii
în jurul s u, pe circumferinµa unui cerc imaginar, în sensul acelor de ceasornic. Aceste dispozitive
inteligente pot comunica între ele, unindu-³i puterile armelor.
Cerinµe
Cunoscând num rul de roboµi, precum ³i puterea ec ruia, s se scrie un program care deter-
min :
1. Dimensiunea celei mai lungi secvenµe de roboµi pentru care puterile armelor lor formeaz
un ³ir strict cresc tor.
2. O aranjare a roboµilor pe cerc, astfel încât suma produselor de câte dou puteri vecine s
e maxim . Dac exist mai multe modalit µi de aranjare astfel încât s se obµin aceea³i sum
maxim , se va determina cea minim din punct de vedere lexicograc.
Date de intrare
Pe prima linie a ³ierului de intrare roboti.in se g se³te un num r natural v a c rui valoare
poate doar 1 sau 2.
Pe a doua linie a ³ierului de intrare se g se³te un singur num r natural n reprezentând
num rul de roboµi.
Pe a treia linie a ³ierului de intrare se g sesc n numere naturale p1 , p2 , ..., pn , separate prin
câte un spaµiu, pi reprezentând puterea armei robotului i.
Date de ie³ire
Dac valoarea lui v este 1, atunci ³ierul de ie³ire roboti.out va conµine pe prima linie un
singur num r natural reprezentând dimensiunea celei mai lungi secvenµe de roboµi pentru care
puterile armelor lor formeaz un ³ir strict cresc tor.
Dac valoarea lui v este 2, atunci ³ierul de ie³ire va conµine pe prima linie n numere naturale
separate prin câte un spaµiu, reprezentând puterile celor n roboµi a³ezaµi pe cerc astfel încât suma
produselor de câte dou puteri vecine s e maxim , iar a³ezarea s e minim din punct de
vedere lexicograc.
CAPITOLUL 4. OJI 2017 96
Restricµii ³i preciz ri
a 2 & n & 100000
a Pentru cerinµa 1, secvenµa de lungime maxim se alege pe cerc în sensul acelor de ceasornic.
a Dac avem dou ³iruri de numere a1 , a2 , ..., an ³i b1 , b2 , ..., bn ³i exist 1 & k & n, cea mai
mic poziµie, pentru care are loc a1 b1 , a2 b2 , ..., ak1 bk1 ³i ak $ bk , atunci spunem c
³irul a este mai mic lexicograc decât ³irul b.
a Pentru rezolvarea corect a cerinµei 1 se acord 30 puncte, pentru rezolvarea corect a cerinµei
2 se acord 60 de puncte, iar din ociu se acord 10 puncte.
a Pentru cerinµa 2, dac soluµia a³at nu este minim lexicograc, dar produce suma maxim
corect se acord 50% din punctajul testului respectiv.
a Pentru cerinµa 2, teste în valoare total de 36 puncte vor avea n & 1000.
a 1 & p1 , p2 , ..., pn & 1000.
Exemple
51 {
52 sort(p, p+n);
53
54 //aranjare
55 a[0]=p[0];
56 s=0; d=n;
57 serie=0;
58 ns=0;nd=0;
59 antdr=0;
60 for(i=1;i<=n-1;i++)
61 {
62 // daca este cap de serie,
63 // adica primuldintr-o serie de nr. care se repeta
64 if(i<n-1 && p[i]==p[i+1] && p[i-1]!=p[i])
65 cs=1;
66 else
67 cs=0;
68
69 //daca am pus mai putini sau egal in st si dr sau
70 // este intr-o serie de egale sau
71 // cel dinaintealui l-am pus in dreapta dar nu a fost cap de serie
72 if(ns<=nd || serie || (antdr && !cs) )//merge stanga
73 {
74 s++;
75 a[s]=p[i];
76 ns++;
77 antdr=0;
78 }
79 else //merge dreapta
80 {
81 d--;
82 a[d]=p[i];
83 nd++;
84 antdr=1;
85 }
86
87 if(p[i]==p[i-1])
88 serie++;
89 else
90 serie=0;
91 }
92
93 for(i=0;i<n;i++)
94 out<<a[i]<<’ ’;
95 }
96
97 in.close();
98 out.close();
99 return 0;
100 }
23 i=1;
24 x=a[0];
25 ok=0;
26 while(i<n && ok<2)
27 {
28 if(a[i]>a[i-1])
29 ls++;
30 else
31 {
32 if(ls>max)
33 max=ls;
34 ls=1;
35 }
36
37 i++;
38 //ciclarea cautarii
39 if(i==n)
40 {
41 if(x>a[i-1])
42 {
43 ls++;
44 i=1;
45 }
46
47 ok++; //numai inca o ciclare
48 }
49 }
50
51 out<<max;
52 }
53 else //cerinta 2
54 {
55 for(i=0;i<n;i++)
56 {
57 in>>d;
58 p[d]++;
59 }
60
61 //aranjare
62 i=1;
63 s=0;
64 d=n;
65 ns=0;
66 nd=0;
67 while(p[i]==0)
68 i++;
69 //cout<<i<<":"<<p[i]<<endl;
70
71 a[0]=i;
72 p[i]--;
73 serie=0;
74 for(j=1;j<=p[i];j++)
75 {
76 s++;
77 a[s]=i;
78 ns++;
79 serie=1;
80 }
81
82 antdr=0;
83 i++;
84 do
85 {
86 while(p[i]==0 && i<=1000)
87 i++;
88
89 // daca este cap de serie,
90 // adica primul dintr-o serie de nr. care se repeta
91 // capul de serie merge dr restul din serie merg st
92 if(p[i]>1)
93 {
94 d--;
95 a[d]=i;
96 p[i]--;
97 nd++;
98 serie=1;
CAPITOLUL 4. OJI 2017 101
99 antdr=0;
100 for(j=1;j<=p[i];j++)
101 {
102 s++;
103 a[s]=i;
104 ns++;
105 }
106 }
107 else
108 {
109 if(ns<=nd || serie || antdr)
110 {
111 s++;
112 a[s]=i;
113 ns++;
114 serie=0;
115 antdr=0;
116 }
117 else
118 {
119 d--;
120 a[d]=i;
121 nd++;
122 antdr=1;
123 }
124 }
125
126 i++;
127 } while(ns+nd<n-1);
128
129 for(i=0;i<n;i++)
130 out<<a[i]<<’ ’;
131 }
132
133 in.close();
134 out.close();
135 return 0;
136 }
35 {
36 for(i=1;i<=1000;i++)
37 q[i]=0;
38
39 for(i=1;i<=n;i++)
40 q[p[i]]++;
41
42 nr=0;
43 for(i=1;i<=1000;i++)
44 {
45 if(q[i]>0)
46 {
47 nr++;
48 f[nr]=q[i];
49 r[nr]=i;
50 q[i]=0;
51 }
52 }
53
54 m=n+1;
55 for(i=1;i<=f[nr];i++)
56 q[--m]=r[nr];
57
58 M=n;
59 for(i=nr-1;i>=2;i--)
60 {
61 if(f[i]>1)
62 {
63 q[++M]=r[i];
64 for(j=1;j<f[i];j++)
65 q[--m]=r[i];
66 }
67 else
68 {
69 j=i;
70 while(j-1>=2 && f[j-1]==1)
71 j--;
72
73 if(q[m]==q[M])
74 {
75 if((i-j+1)%2==1)
76 q[--m]=r[i--];
77
78 for(k=i;k>=j;k=k-2)
79 {
80 q[++M]=r[k];
81 q[--m]=r[k-1];
82 }
83 }
84 else
85 {
86 if(q[m]>q[M])
87 {
88 for(k=0;k<=i-j;k++)
89 {
90 if(k%2==0)
91 q[--m]=r[i+k];
92 else
93 q[++M]=r[i+k];
94 }
95 }
96 else
97 {
98 for(k=0;k<=i-j;k++)
99 {
100 if(k%2==1)
101 q[--m]=r[i+k];
102 else
103 q[++M]=r[i+k];
104 }
105 }
106 }
107
108 i=j;
109 }
110 }
CAPITOLUL 4. OJI 2017 103
111
112 for(i=1;i<=f[1];i++)
113 q[--m]=r[1];
114
115 for(i=m;i<=M;i++)
116 fout<<q[i]<<" ";
117 }
118
119 fout.close();
120 return 0;
121 }
62 else
63 B[p++] = A[i];
64
65 for (int i = 0; i < N; i++)
66 g << B[i] << " ";
67 }
68
69 g.close();
70 return 0;
71 }
OJI 2016
5.1 Cifre
Problema 1 - Cifre 100 de puncte
Cerinµe
Cunoscând un num r natural N a³at cu ajutorul mai multor indicatoare numerice, s se scrie
un program care determin :
1. Num rul de segmente aprinse pentru a³area num rului N .
2. Num rul de numere distincte mai mari decât N ,ce se pot forma prin aprinderea a cel
puµin unui segment în plus, faµ de cele utilizate pentru a³area num rului N ,f r a folosi alte
indicatoare numerice, ³i f r a stinge nici un segment dintre cele deja aprinse.
Date de intrare
Fi³ierul de intrare este cifre.in
Pe prima linie a ³ierului de intrare se g se³te num rul natural V a c rui valoare poate doar
1 sau 2.
Pe a doua linie a ³ierului de intrare se g se³te num rul natural N .
Date de ie³ire
Fi³ierul de ie³ire este cifre.out
Dac valoarea lui V este 1 atunci ³ierul de ie³ire va conµine pe prima linie un singur num r
natural ce reprezint num rul de segmente aprinse pentru a³area num rului N .
Dac valoarea lui V este 2 atunci ³ierul de ie³ire va conµine pe prima linie un singur num r
natural reprezentând num rul de numere distincte mai mari decât N , ce se pot forma prin aprin-
derea a cel puµin unui segment în plus, faµ de cele utilizate pentru a³area num rului N , f r a
folosi alte indicatoare numerice.
Restricµii ³i preciz ri
a 10 & N & 1019
a 20% din teste vor avea valoarea V 1, iar 80% din teste vor avea valoarea V 2.
105
CAPITOLUL 5. OJI 2016 106
Exemple
cifre.in cifre.out Explicaµii
1 17 V = 1, deci se rezolv NUMAI prima cerinµ .
823 N = 823;
Pentru a³area cifrei 8 s-au aprins 7 segmente, pentru cifra 2 s-au
aprins 5 segmente ³i pentru cifra 3 tot 5 segmente. în total s-au
aprins 17 segmente.
2 5 V = 2, deci se rezolv NUMAI a doua cerinµ .
823 N = 823;
Din cifra 8 nu se mai pot obµine alte cifre prin aprinderea de noi
segmente.
Din cifra 2 se poate obµine cifra 8 iar din cifra 3 se pot obµine cifrele 8
³i 9 prin aprinderea de noi segmente. A³adar, se pot obµine 5 numere
mai mari ca 823: 828, 829, 883, 888, 889.
Varianta 1
Pentru prima cerinµ trebuie determinate câte segmente sunt aprinse pentru a³area num rului
N.
Se prelucreaz num rul N cifr cu cifr ³i se calculeaz num rul segmentelor aprinse.
Num rul de segmente aprinse pentru a³area cifrelor este dat în tabelul de mai jos :
Cifr 0 1 2 3 4 5 6 7 8 9
Num r segmente aprinse 6 2 5 5 4 5 6 3 7 6
Pentru a doua cerinµ o variant mai puµin ecient este urm toarea :
a Se parcurg toate numerele de la N 1 pân la cel mai mare num r cu acela³i num r de cifre
ca N .
a Pentru ecare dintre numerele de mai sus, se determin pentru ecare cifr dac aceasta
poate construit din cifra lui N de pe aceea³i poziµie prin aprinderea suplimentar a unui sau
mai multor segmente.
a Dac pentru ecare cifr condiµia de mai sus este adevarat se contorizeaz înc o soluµie.
Aceast soluµie obµine aproximativ jum tate din punctaj ³i ordinul s u de complexitate este
nrcif re N
O 10 1 N .
Varianta 2 (optimizare matematic )
Pentru a determina un algoritm mai ecient folosim una din metodele de num rare prezentate
în manualul de clasa a IX-a de matematic ³i anume regula produsului. Aceast regul arm
c dac avem A1 , A2 , ...., Ak operaµii succesive, prima putând efectuat în n1 moduri, a doua
în n2 moduri, ..., ultima în nk moduri, atunci succesiunea celor k operaµii poate efectuat în
n1 n2 ... nk moduri.
În acest scop construim urm toarele structuri de date:
a) Num rul de cifre ce se pot forma dintr-o cifr dat prin ad ugarea de noi segmente (inclusiv
cifra curent ):
Cifr 0 1 2 3 4 5 6 7 8 9
Num rul cifrelor ce se pot realiza din cifra curent 2 7 2 3 3 4 2 5 1 2
prin ad ugare de noi segmente (inclusiv cifra curent )
b) Num rul de cifre, strict mai mari decât o cifr dat , ce se pot forma prin ad ugarea de noi
segmente:
Cifr 0 1 2 3 4 5 6 7 8 9
Num rul cifrelor strict mai mari decât cifra curent 1 5 1 2 2 3 1 2 0 0
ce se pot forma dintr-o cifr dat prin ad ugarea de
noi segmente:
Având în vedere aceste date vom parcurge cifrele lui N de la cifra cea mai semnicativ la cea
mai puµin semnicativ ³i la ecare cifr proced m astfel:
Calcul m produsul dintre numerele:
a câte cifre strict mai mari exist decât cifra curent ³i
CAPITOLUL 5. OJI 2016 107
a câte cifre se pot forma prin ad ugarea de noi segmente pentru ecare din cifrele urm toare,
nu neap rat mai mari, decât cifrele de pe poziµii similare ale lui N .
Num rul de numere distincte mai mari decât N reprezint suma produselor de mai sus.
Aceast soluµie obµine maximum de punctaj iar ordinul s u de complexitate este
2
O nrcif re N .
63 {
64 if (a[w[i]])
65 {
66 P=a[w[i]];
67 for(j=i+1;j<=k;j++)
68 P=P*b[w[j]];
69 S=S+P;
70 }
71 }
72
73 g<<S<<"\n";
74 }
75
76
77 f.close();
78 g.close();
79
80 return 0;
81 }
54 s=s+p;
55 }
56
57 g<<s<<"\n";
58 }
59
60 return 0;
61 }
5.2 pic
Problema 2 - pic 100 de puncte
Exemple
pic.in pic.out Explicaµii
1 2 V = 1, deci se rezolv NUMAI prima cerinµ .
3 Pe nivelul 1 se g se³te un pahar de capacitate 2.
242123 Pe nivelul 2 se g sesc dou pahare de capacit µi 4 ³i 2.
Pe nivelul 3 se g sesc trei pahare de capacit µi 1, 2 ³i 3 .
Suma capacit µilor paharelor este: 2 pe nivelul 1, 6 pe nivelul 2
³i 6 pe nivelul 3, deci cel mai de sus nivel cu suma maxim - 6,
este nivelul 2.
2 18 4 V = 2, deci se rezolv NUMAI a doua cerinµ .
3 Dup 10 secunde conguraµia paharelor este urm toarea:
242123 Pahar Numar picaturi Observatii
1 2 Plin
2 4 Plin
3 2 Plin
4 0
5 1
6 1
Cea de a unsprezecea pic tur se scurge din paharul 1 în paharul
2 ³i mai departe în paharul 4.
Pentru rezolvarea primei cerinµe se calculeaz , simultan cu citirea datelor, suma capacit µilor
de pe ecare nivel ³i se determin maximul acestor sume, reµinându-se ³i primul nivel pentru care
se atinge acest maxim.
Rezolvarea celei de-a doua cerinµe se bazeaz pe o simulare a curgerii picurilor.
4 #include <fstream>
5 #define NMAX 55
6
7 using namespace std;
8
9 ifstream f("pic.in");
10 ofstream g("pic.out");
11
12 long long ctot,p[NMAX][NMAX];
13 long long c[NMAX][NMAX],d[NMAX][NMAX];
14 long long x,m,k,s,mx=0,ss;
15 int i,j,umpl,v,lin,n;
16
17 int main()
18 {
19 f>>v>>n;
20 ctot=0;
21
22 for (i=1; i<=n; i++)
23 {
24 m=0;
25 ss=0;
26 for (j=1; j<=i; j++)
27 {
28 f>>x;
29
30 ss+=x;
31 c[i][j]=x;
32 if (x>m) m=x;
33 }
34
35 ctot += ss;
36 if (ss>mx)
37 {
38 mx=ss;
39 lin=i;
40 }
41
42 }
43
44 if (v==1)
45 g<<lin<<"\n";
46 else
47 {
48 s=(1<<n); // 2^n, cantitate inca insuficienta pt a umple n nivele
49 // daca paharele ar avea toate capacitate 1
50
51 do
52 {
53 // turnam dintr-o data s picaturi in paharul 1
54
55 for (i=1; i<=n; i++) // initializam nr de picaturi turnate
56 // in fiecare pahar
57 for (j=1; j<=n; j++)
58 p[i][j]=0;
59 i=1;
60 j=1;
61 p[1][1]=s;
62 for (i=1; i<n; i++)
63 for (j=1; j<=i; j++)
64 {
65 x = p[i][j]-c[i][j];
66 p[i][j] = x;
67 p[i+1][j] += (x+1)/2;
68 p[i+1][j+1] += x/2;
69 }
70
71 // aflam cate pahare neumplute avem
72 k=0;
73 for (j=1; j<=n; j++)
74 {
75 p[n][j] -= c[n][j];
76 if (p[n][j]<0) k++;
77 }
78
79 if (k>0) // mai sunt pahare neumplute
CAPITOLUL 5. OJI 2016 113
80 s *= 2;
81 } while (k>0);
82
83 // s umple toate paharele,
84 // s/2 nu umple toate paharele
85
86 // numarul de picaturi necesare este in intervalul [s/2, s] facem
87 // o cautare binara a cantitatii necesare
88 // pt a ramane un singur pahar gol
89
90 long long l=s/2;
91 s=s-l/2; // s e jumatatea intervalului [s/2,s]
92
93 while (l>0)
94 {
95 for (i=1; i<=n; i++) // initializam nr de picaturi turnate
96 // in fiecare pahar
97 for (j=1; j<=n; j++)
98 p[i][j]=0;
99
100 i=1;
101 j=1;
102 p[1][1]=s;
103 for (i=1; i<n; i++)
104 for (j=1; j<=i; j++)
105 {
106 x = p[i][j]-c[i][j];
107 p[i][j] = x;
108 p[i+1][j] += (x+1)/2;
109 p[i+1][j+1] += x/2;
110 }
111
112 k=0;
113 for (j=1; j<=n; j++)
114 {
115 p[n][j] -= c[n][j];
116 if (p[n][j]<0) k++; // pahar neumplut
117 }
118
119 l=l/2;
120 if (k>0) // cel putin un pahar neumplut
121 s=s+l/2;
122 else
123 s=s-l/2;
124 }
125
126 if (k>0)
127 s++;
128
129 g<<s<<" "<<s-ctot<<"\n";
130 }
131
132 return 0;
133 }
19 fi>>v>>n;
20 for(int i=1;i<=n;i++)
21 {
22 pl=0;
23 for(int j=1;j<=i;j++)
24 {
25 fi>>p[i][j];
26 pl+=p[i][j];
27 }
28
29 pt+=pl;
30 if (pl>mx)
31 {
32 mx=pl;
33 l=i;
34 }
35 }
36
37 if(v==1)
38 {
39 fo<<l<<"\n";
40 }
41 else
42 {
43 // copie stiva pahare
44 for(int i=1;i<=n+1;i++)
45 {
46 for(int j=1;j<=n+1;j++)
47 {
48 pTemp[i][j]=p[i][j];
49 }
50 }
51
52 // cautare binara intre 0 si ULLONG_MAX
53 unsigned long long p2=ULLONG_MAX/2+1,d;
54 d=p2;
55 int c=1;
56 while(d>0)
57 {
58 // simularea trecerii a p2 picaturi
59 p[1][1]-=p2;
60 for(int i=1;i<=n-1;i++)
61 {
62 for(int j=1;j<=i;j++)
63 {
64 if(p[i][j]<0)
65 {
66 p[i+1][j]+=p[i][j]/2;
67 p[i+1][j+1]+=p[i][j]/2;
68 if(p[i][j]%2==-1)
69 p[i+1][j]--;
70 p[i][j]=0;
71 }
72 }
73 }
74
75 // verificarea paharelor de pe ultimul rand
76 c=0;
77 for(int j=1;j<=n;j++)
78 if(p[n][j]>0)
79 c=1;
80 d=d/2;
81 if(c==1)
82 p2=p2+d;
83 else
84 p2=p2-d;
85
86 // refacere stiva pahare
87 for(int i=1;i<=n+1;i++)
88 {
89 for(int j=1;j<=n+1;j++)
90 {
91 p[i][j]=pTemp[i][j];
92 }
93 }
94 }
CAPITOLUL 5. OJI 2016 115
95
96 if(c==1)
97 p2++;
98
99 fo<<p2<<" "<<p2-pt<<"\n";
100 }
101
102 return 0;
103 }
64 }
65
66 long long Solve2()
67 {
68 long long Sol = -1;
69 long long Left = Sum, Right = oo;
70 while(Left <= Right)
71 {
72 long long Mid = (Left + Right) / 2;
73 if(Check(Mid))
74 {
75 Sol = Mid;
76 Right = Mid - 1;
77 }
78 else
79 Left = Mid + 1;
80 }
81
82 return Sol;
83 }
84
85 int main()
86 {
87 Read();
88
89 if(V == 1)
90 fout<<Solve1()<<"\n";
91
92 if(V == 2)
93 {
94 long long T = Solve2();
95 fout<<T<<" "<<T - Sum<<"\n";
96 }
97
98 return 0;
99 }
OJI 2015
6.1 arc
Problema 1 - arc 100 de puncte
Irinuca a descoperit un nou joc pe calculator. Pe ecran sunt plasate pe o linie n bile colorate.
Culorile bilelor sunt codicate cu numere naturale. Un sub³ir de bile al turate având toate aceea³i
culoare se nume³te secvenµ . O secvenµ va conµine num rul maxim de bile al turate având aceea³i
culoare. Lungimea unei secvenµe este egal cu num rul de bile din care este compus .
Irinuca are la dispoziµie un arc special. Tr gând cu arcul asupra unei bile, dac aceasta face
parte dintr-o secvenµ de lungime cel puµin egal cu 3, întreaga secvenµ va eliminat , iar bilele
din dreapta secvenµei se vor deplasa spre stânga pentru a umple golul l sat de bilele eliminate.
Dac imediat în stânga ³i în dreapta secvenµei eliminate se g seau dou secvenµe având aceea³i
culoare ³i dac secvenµa obµinut din unirea acestora dup eliminare are o lungime cel puµin egal
cu 3, atunci va ³i ea eliminat la rândul ei. Procesul continu pân când secvenµele din stânga
³i dreapta unei secvenµe tocmai eliminate au culori diferite sau pân când lungimea secvenµei
obµinute prin al turare este mai mic decât 3 sau pân când în stânga ori în dreapta unei secvenµe
eliminate nu se mai g sesc bile sau pân sunt eliminate toate bilele de pe ecran.
Scopul jocului este de a elimina cât mai multe bile de pe ecran. Cum Irinuca înc nu se pricepe
prea bine la acest joc ³i-a stabilit o strategie. Va trage cu arcul întotdeauna asupra unei bile ce
face parte din secvenµa de lungime maxim de pe ecran. Dac sunt mai multe astfel de secvenµe,
ea va alege cea mai din stânga secvenµ de lungime maxim . Dac toate secvenµele de pe ecran
au lungimi mai mici decât 3, Irinuca nu va mai putea elimina nici una din ele ³i jocul se încheie.
De exemplu, dac ³irul iniµial de bile este
513322223115644447
Irinuca va acµiona asupra unei bile de culoare 2. Prin eliminare se obµine ³irul de bile
51333115644447
din care se elimin ³i secvenµa de bile de culoare 3 obµinându-se ³irul de bile
51115644447
din care se elimin ³i secvenµa de culoare 1.
55644447
Cum secvenµa de bile de culoare 5 nu este sucient de lung , aceasta nu se mai elimin . Acum
Irinuca trage asupra unei bile de culoare 4 ³i obµine
5567
dar cum în stânga ³i în dreapta secvenµei eliminate sunt secvenµe de culori diferite, nu se va
mai elimina nici o secvenµ . Jocul se încheie deoarece nu mai exist nici o secvenµ de lungime cel
puµin 3 asupra c reia s se poat trage.
Cerinµe
Cunoscând num rul de bile ³i culorile ec rei bile de pe ecran se cere s se determine:
1. num rul de secvenµe de bile care se aau iniµial pe ecran;
2. num rul de bile care r mân neeliminate de pe ecran ³i culorile bilelor r mase în ordine pe
ecran la nalul jocului.
Date de intrare
117
CAPITOLUL 6. OJI 2015 118
Fi³ierul de intrare arc.in conµine pe prima linie un num r natural V . Pentru toate testele de
intrare, num rul V poate avea doar valoarea 1 sau 2.
A doua linie conµine un num r natural n reprezentând num rul de bile, iar a treia linie conµine
n numere naturale c1 , c2 , ..., cn separate prin câte un spaµiu, reprezentând culorile celor n bile de
pe ecran.
Date de ie³ire
Dac valoarea lui V este 1, se va rezolva numai punctul 1 din cerinµ .
În acest caz, în ³ierul de ie³ire arc.out se va scrie un singur num r natural n1 , reprezentând
num rul de secvenµe de bile aate iniµial pe ecran.
Dac valoarea lui V este 2, se va rezolva numai punctul 2 din cerinµ .
În acest caz, în ³ierul de ie³ire arc.out se va scrie pe prima linie un singur num r natural
n2 , reprezentând num rul de bile care r mân neeliminate de pe ecran la nalul jocului, iar pe
urm toarele n2 linii se va scrie câte un num r natural reprezentând în ordine culorile bilelor
r mase neeliminate la nalul jocului.
Dac la nalul jocului nu mai r mâne nici o bil neeliminat , ³ierul de ie³ire va conµine pe
prima sa linie valoarea 0.
Restricµii ³i preciz ri
a 1 & n & 10000
a 1 & c1 , c2 , ..., cn & 100000
a Pentru rezolvarea corect a primei cerinµe se acord 20 de puncte, iar pentru cerinµa a doua
se acord 80 de puncte.
Exemple
arc.in arc.out Explicaµii
1 10 V=1
18 Atenµie!
513322223115644 Pentru acest test se rezolv doar cerinµa 1.
447 Secvenµele sunt (5), (1), (3, 3), (2,2,2,2), (3), (1,1),
(5), (6), (4,4,4,4), (7)
2 4 V=2
18 5 Atenµie!
513322223115644 5 Pentru acest test se rezolv doar cerinµa 2.
447 6
7
2 0 V=2
15 Atenµie!
122221133344443 Pentru acest test se rezolv doar cerinµa 2.
Cerinµa 1.
Practic la citirea unei noi valori din ³ier, dac aceasta este egal cu ultima valoare memorat
în x vom incrementa contorul c corespunz tor, altfel o vom memora în urm toarea component
din vectorul x iar contorul corespunzator îl iniµializ m cu 1.
Num rul efectiv de valori din cei doi vectori, m, este r spunsul la primul punct.
Cerinta 2.
Vom simula elimin rile. Determin m maximul din vectorul c, e acesta max cp.
CAPITOLUL 6. OJI 2015 119
57 {
58 n=n-x[i]-x[j];
59 i--; j++;
60 }
61
62 if (j>m)
63 m=i;
64 else
65 {
66 if (i>=1 && j<=m && c[i]==c[j])
67 {
68 x[i]=x[i]+x[j];
69 j++;
70 }
71
72 m1=m-j+i+1;
73 i=i+1;
74 while (j<=m)
75 {
76 x[i]=x[j]; c[i]=c[j];
77 i++; j++;
78 }
79
80 m=m1;
81 }
82 }
83 }
84
85 int main()
86 {
87 int k;
88
89 citire();
90
91 if (p==1)
92 g<<m<<"\n";
93 else
94 {
95 k=maxim();
96 while (n>0 && x[k]>2)
97 {
98 elim(k);
99 if (k>0)
100 k=maxim();
101 }
102
103 if (n>0)
104 {
105 g<<n<<"\n";
106 for (int i=1;i<=m;i++)
107 for (int j=1;j<=x[i];j++)
108 g<<c[i]<<"\n";
109 }
110 else
111 g<<"0\n";
112 }
113
114 g.close();
115 return 0;
116 }
13
14 struct Secv
15 {
16 int v, cnt;
17 short pos, prev, next;
18 };
19
20 const int MaxN = 10001;
21 Secv s[MaxN];
22 int first, last;
23
24 void Add(int val);
25 void Print();
26 int GetMax();
27 void DelSecv(int p);
28
29 int main()
30 {
31 int x;
32 fin >> p >> n;
33
34 for (int i = 1; i <= n; ++i)
35 {
36 fin >> x;
37 Add(x);
38 }
39
40 if (p == 1)
41 fout << n1 << ’\n’;
42 else
43 {
44 n2 = n;
45 while (true)
46 {
47 int p = GetMax(), p1, p2;
48
49 if ( !p || s[p].cnt <= 2 )
50 break;
51
52 n2 -= s[p].cnt;
53 p1 = s[p].prev;
54 p2 = s[p].next;
55
56 DelSecv(p);
57
58 while ( (p1 && p2) && (s[p1].v == s[p2].v) )
59 {
60 s[p1].cnt += s[p2].cnt;
61 DelSecv(p2);
62
63 if ( s[p1].cnt > 2 )
64 {
65 n2 -= s[p1].cnt;
66 int q = p1;
67 p1 = s[p1].prev;
68 DelSecv(q);
69 }
70
71 if ( p1 )
72 p2 = s[p1].next;
73 }
74 }
75
76 Print();
77 }
78
79 fin.close();
80 fout.close();
81 }
82
83 void Add(int val)
84 {
85 if ( last && s[last].v == val )
86 {
87 s[last].cnt++;
88 return;
CAPITOLUL 6. OJI 2015 122
89 }
90
91 Secv s1 {0, 0, 0, 0, 0 };
92
93 s1.v = val;
94 s1.cnt++; n1++;
95
96 if ( !first )
97 {
98 s1.prev = s1.next = 0;
99 first = last = 1;
100 s[first] = s1;
101 }
102 else
103 {
104 s[last].next = last + 1;
105 s1.prev = last;
106 s1.next = 0;
107 last++;
108 s[last] = s1;
109 }
110 }
111
112 void DelSecv(int p)
113 {
114 if ( p == first )
115 {
116 if ( p == last )
117 {
118 first = last = 0;
119 return;
120 }
121
122 first = s[p].next;
123 s[first].prev = 0;
124
125 return;
126 }
127
128 if ( p == last )
129 {
130 last = s[p].prev;
131 s[last].next = 0;
132 return;
133 }
134
135 int p1 = s[p].prev, p2 = s[p].next;
136 s[p1].next = p2;
137 s[p2].prev = p1;
138 }
139
140 int GetMax()
141 {
142 int pMax(0);
143 int cntMax = 0;
144
145 for (int p = first; p; p = s[p].next)
146 if ( s[p].cnt > cntMax )
147 cntMax = s[p].cnt, pMax = p;
148
149 return pMax;
150 }
151
152 void Print()
153 {
154 if ( !first )
155 fout << "0\n";
156 else
157 {
158 fout << n2 << ’\n’;
159
160 for (int p = first; p; p = s[p].next)
161 while ( s[p].cnt--)
162 fout << s[p].v << ’\n’;
163 }
164 }
CAPITOLUL 6. OJI 2015 123
75 }
76
77 if(poz>1&& poz<nr && v[poz-1].c==v[poz+1].c)
78 {
79 v[poz-1].nr+=v[poz+1].nr;
80
81 for(j=poz+2;j<=nr;j++)
82 v[j-2]=v[j];
83
84 nr-=2;
85 }
86 else
87 {
88 for(j=poz+1;j<=nr;j++)
89 v[j-1]=v[j];
90
91 nr--;
92 }
93
94 Max=0;
95 poz=0;
96 t=0;
97 for(i=1;i<=nr;i++)
98 {
99 if(v[i].nr>=3&&v[i].nr>Max)
100 {
101 Max=v[i].nr;
102 poz=i;
103 }
104
105 t=t+v[i].nr;
106 }
107
108 }
109
110 g<<t<<’\n’;
111
112 for(i=1;i<=nr;i++)
113 for(j=1;j<=v[i].nr;j++)
114 g<<v[i].c<<"\n";
115
116 return 0;
117 }
30 u=x;
31 }
32
33 if (caz==1)
34 fout<<secv<<endl;
35
36 if (caz==2)
37 {
38 l=0;u=0;
39 for(i=1;i<=secv;i++)
40 {
41 //fout<<v[i]<<" "<<f[i]<<endl;
42 if(f[i]>l) l=f[i],u=i;
43 }
44
45 i=u; /// plec de la cea mai lunga secventa...
46 while(l>=3)
47 {
48 if(f[i]>=3)
49 {
50 ///o pot elimina
51 v[i]=0;
52 n=n-f[i]; ///cate se sterg
53 f[i]=0;
54
55 st=i-1;
56 dr=i+1;
57 while(v[st]==0 && st>1)
58 st--;
59 while(v[dr]==0 && dr<secv)
60 dr++;
61
62 if (v[st]==v[dr]) ///verific lipirea
63 {
64 f[dr]=f[dr]+f[st];
65 f[st]=0;
66 v[st]=0;
67 i=dr;///ce incerc sa scot
68 cauta=0;
69 }
70 else
71 cauta=1;
72 }
73 else
74 cauta=1;
75
76 if (cauta)
77 {
78 ///caut noua secv maxima
79 l=0;
80 u=0;
81 for(i=1;i<=secv;i++)
82 {
83 //fout<<v[i]<<" "<<f[i]<<endl;
84 if(f[i]>l) l=f[i],u=i;
85 }
86
87 i=u; /// plec de la cea mai lunga secventa...
88 }
89 }
90
91 fout<<n<<endl;
92
93 for(i=1;i<=secv;i++)
94 for(x=1;x<=f[i];x++)
95 fout<<v[i]<<endl;
96 }
97
98 return 0;
99 }
6.2 defrag
Problema 2 - defrag 90 de puncte
Discul dur (hard disk) este un dispozitiv utilizat pentru stocarea datelor. Stocarea se face pe
o suprafaµ magnetic dispus pe platane rotunde metalice. Pe un platan, datele sunt organizate
în piste ³i sectoare, iar zona aat la intersecµia dintre o pist ³i un sector poart denumirea de
cluster.
Un cluster poate avea dou st ri: liber, dac nu conµine date, sau ocupat, atunci când conµine
date.
Un platan se nume³te defragmentat dac toµi clusterii ocupaµi de pe ecare pist sunt a³ezaµi
în ordine consecutiv . Defragmentarea se realizeaz prin mutarea unor clusteri ocupaµi ³i are rolul
de a mic³ora timpul de acces la date. Mutarea unui cluster reprezint transferul datelor de la un
cluster ocupat c tre un cluster liber de pe aceea³i pist .
Cerinµe
Cunoscând num rul de piste P ³i de sectoare S al unui platan, num rul ³i poziµia clusterilor
ocupaµi, s se scrie un program care determin :
1. num rul de piste care au toµi clusterii liberi;
2. num rul minim de mut ri de clusteri, pentru ecare pist în parte, astfel încât platanul s
devin defragmentat.
Date de intrare
Pe prima linie a ³ierului de intrare defrag.in se g se³te num rul natural V a c rui valoare
poate doar 1 sau 2.
Pe a doua linie a ³ierului de intrare se g sesc dou numere naturale P ³i S , separate printr-un
spaµiu, cu semnicaµia din enunµ.
A treia linie conµine un num r natural C reprezentând num rul total de clusteri ocupaµi de pe
platan, iar pe ecare din urm toarele C linii se g se³te câte o pereche de valori pi ³i si , 1 & i & C ,
separate printr-un spaµiu, reprezentând pista, respectiv sectorul unde se a ecare cluster ocupat.
Date de ie³ire
Fi³ierul de ie³ire este defrag.out.
Dac valoarea lui V este 1 atunci ³ierul de ie³ire va conµine pe prima linie un num r natural
ce reprezint num rul de piste care au toµi clusterii liberi.
Dac valoarea lui V este 2 atunci ³ierul de ie³ire va conµine pe prima linie P numere naturale
notate Mi , 1 & i & P , separate prin câte un singur spaµiu, unde Mi reprezint num rul minim de
mut ri de clusteri, dintre cei aaµi pe pista i, astfel încât pe pista i clusterii ocupaµi s se g seasc
într-o ordine consecutiv .
Restricµii ³i preciz ri
a 1 & P & 100
a 1 & S & 360
a 1&C &P S
a pistele sunt numerotate de la 1 la P începând cu pista exterioar ;
a sectoarele sunt numerotate de la 1 la S în sensul acelor de ceasornic începând cu sectorul 1;
a dac o pist are toµi clusterii liberi, atunci valoarea cerut la a doua cerinµ este 0;
a 20% din teste vor avea valoarea V 1, iar 80% din teste vor avea valoarea V 2.
CAPITOLUL 6. OJI 2015 127
Exemple
defrag.in defrag.out Explicaµii
1 1 Datele corespund gurilor anterioare:
48 V = 1, deci se rezolv NUMAI prima cerinµ .
10 a Num rul de piste P = 4 , num rul de sectoare S = 8
11 a Num rul total de clusteri ocupaµi este C = 10 (cei marcaµi cu
13 negru)
15 a Pe prima pist sunt 4 clusteri ocupaµi, în sectoarele 1, 3, 5 si
17 7.
45 a Pe a doua pist sunt 2 clusteri ocupaµi, în sectoarele 2 ³i 4.
41 a Pe a treia pist nu sunt clusteri ocupaµi.
46 a Pe a patra pist sunt 4 clusteri ocupaµi, în sectoarele 1, 5, 6
48 ³i 8.
22 O singur pist are toµi clusterii liberi, pista num rul 3, deci
24 valoarea cerut este 1;
2 2101 Datele corespund gurilor anterioare:
48 V = 2, deci se rezolv NUMAI a doua cerinµ .
10 a Pe prima pist sunt necesare minim dou mut ri de clusteri
11 pentru ca toµi clusterii ocupaµi s se g seasc într-o ordine con-
13 secutiv , deci valoarea cerut este 2.
15 a Pe a doua pist este sucient o singur mutare de cluster,
17 pentru ca toµi clusterii ocupaµi s se g seasc într-o ordine con-
45 secutiv , deci valoarea cerut este 1.
41 a Pe a treia pist nu sunt clusteri ocupaµi, deci valoarea cerut
46 este 0.
48 a Pe a patra pist este sucient o singur mutare de cluster,
22 pentru ca toµi clusterii ocupaµi s se g seasc într-o ordine con-
24 secutiv , deci valoarea cerut este 1.
Pentru rezolvarea primei cerinµe se determin câµi clusteri sunt ocupaµi pe ecare pist . Se
poate utiliza în acest scop o matrice având num rul de linii egal cu num rul de piste ³i num rul
de coloane egal cu num rul de sectoare al platanului. La ecare citire de cluster ocupat se seteaz
în matrice poziµia dat de pista ³i sectorul clusterului pe 1 (iniµial ind pe 0). în acela³i timp se
contorizeaz în primul element de pe ecare linie num rul de clusteri ocupaµi. Prin parcurgerea
elementelor de pe prima coloan a matricei se determin valoarea cerut la prima cerinµ , prin
sc dere faµ de num rul total de sectoare.
Pentru a doua cerinµ se procedeaz astfel:
Imaginându-ne c s-a realizat mutarea unor clusteri ³i s-a obµinut o zon contigu , aceast
zon va avea lungimea egal cu num rul de clusteri ocupaµi pe ecare pist . Aceast zon poate
începe în orice poziµie a pistei (de la 1 la ns), îns numai unele dintre aceste secvenµe au un num r
minim de clusteri liberi.
A³adar se preia num rul de clusteri ocupaµi pe ecare linie, calculat anterior, pe care s -l
not m cu ncoi (num r clusteri ocupaµi pe pista i) ³i se analizeaz toate secvenµele de câte ncoi
elemente, începând cu poziµia 1 pân la o poziµie în care zona se termin pe ultimul sector, ³i se
determin num rul minim de clusteri de 0 pentru toate secvenµele. Aceast valoare este valoarea
cerut la cerinµa 2.
O soluµie care implementeaz algoritmul descris mai sus obµine aproximativ jumatate din
punctaj, deoarece nu µine cont de circularitatea a³ez rii clusterilor.
Pentru a rezolva ³i circularitatea a³ez rii clusterilor se realizeaz o copie a matricii clusterilor pe
âorizontal prin dublarea num rului de sectoare. în acest mod se poate testa ³i dac secvenµele
cu clusteri consecutivi pot începe chiar de pe ultimul sector, formând astfel o zon contigu cu
clusteri aaµi în primele sectoare.
CAPITOLUL 6. OJI 2015 128
Pentru optimizarea algoritmului descris anterior, se poate proceda astfel: se determin num rul
de clusteri liberi din secvenµa care începe pe primul sector ³i are lungimea ncoi, apoi la ecare
nou secvenµa de aceea³i lungime mutat cu o poziµie c tre dreapta (sau stânga),se adun sau
se scade câte un element în funcµie de ce se întâmpl la capete, deoarece celelalte elemente din
secvenµ nu se modic .
³i
Se observ c
bj bj 1 aij 1 aij k 1 pentru j 1, 2, ...., s k 1
³i
c1 bs k 1 ais k 1 ai1
cj cj 1 ais k j aij
pentru j 2, 3, ..., k 1
Se poate observa u³or c nu avem nevoie de vectorii b ³i c, ci doar de o variabila simpl în care
memor m suma curent ³i pe care o actualiz m la ecare pas.
R spunsul la a doua cerinµ este k - maximul dintre rb1, b2, ..., bs k 1, c1, c2, ..., ck 1x
5 #include <fstream>
6
7 #define pmax 101
8 #define smax 361
9
10 using namespace std;
11
12 short hdd[pmax][2*smax];
13
14 // ns = numar sectoare
15 // np = numar piste
16 // nso = numar sectoare ocupate
17 // xs = sector curent citit
18 // xp = pista curenta citita
19 // po = piste ocupate
20
21 int main()
22 {
23 int v,c,np,ns,xp,xs,i,j,po,min,s,nso;
24
25 ifstream f("defrag.in");
26 ofstream g("defrag.out");
27
28 // citesc configuratia HDD
29 f>>v>>np>>ns;
30
31 // citesc cate clustere sunt ocupate
32 f>>c;
33
34 // citesc clusterele ocupate
35 for(i=1;i<=c;i++)
36 {
37 f>>xp>>xs;
38 hdd[xp][xs]=1;
39
40 // extindere matrice
41 hdd[xp][xs+ns]=1;
42
43 hdd[xp][0]++;
44 }
45
46 if (v==1)
47 {
48 // cate piste nu au clustere ocupate
49 po=0;
50 for(i=1;i<=np;i++)
51 if (hdd[i][0])
52 po++;
53
54 g<<np-po;
55 }
56
57 if (v==2)
58 {
59 // determin numarul minim de mutari de clusteri, pe fiecare pista,
60 // pentru a obtine zone contigue
61 for(i=1;i<=np;i++)
62 {
63 min=ns;
64 nso=hdd[i][0];
65
66 // j = pozitie inceput de secventa
67 s=0;
68 for(j=1;j<=nso;j++)
69 if (hdd[i][j]==0)
70 s++;
71
72 if (s<min) min=s;
73
74 for(j=2;j<=ns;j++)
75 {
76 if (hdd[i][j-1]==0) s--;
77 if (hdd[i][j+nso-1]==0) s++;
78 if (s<min) min=s;
79 }
80
CAPITOLUL 6. OJI 2015 131
81 g<<min<<" ";
82 }
83 }
84
85 g<<"\n";
86 f.close();
87 g.close();
88
89 return 0;
90 }
63
64 sum = 0;
65 for (int i = 0; i < k; ++i)
66 sum += d[p][i];
67
68 sp[k - 1] = sum;
69 for (int i = k; i < S + k; ++i )
70 sp[i % S] = sp[(i - 1)% S] + d[p][i % S] - d[p][i - k];
71
72 int maxim = 0;
73 for (int i = 0; i < S; ++i)
74 maxim = max(maxim, sp[i]);
75
76 fout << k - maxim << ’ ’;
77 }
78 }
79
80 fin.close();
81 fout.close();
82 }
53 }
54 }
55
56 return 0;
57 }
68
69 }
70
71 g<<"\n";
72 g.close();
73 return 0;
74 }
OJI 2014
7.1 cool
Problema 1 - cool 100 de puncte
Se consider un ³ir A format din N elemente naturale nenule. Numim secvenµ de lungime K
a ³irului A orice succesiune de elemente consecutive din ³ir de forma Ai , Ai1 , ..., AiK 1 .
O secvenµ o numim secvenµ cool dac elementele care o compun sunt distincte ³i pot
rearanjate astfel încât s alc tuiasc o secvenµ continu de numere consecutive.
De exemplu, considerând ³irul A 3, 1, 6, 8, 4, 5, 6, 7, 4, 3, 4, atunci secvenµa 8, 4, 5, 6, 7 este
o secvenµ cool deoarece conµine elemente distincte ce pot rearanjate astfel încât s alc tuiasc
³irul de numere consecutive 4, 5, 6, 7, 8, pe când secvenµele 4, 3, 4, 6, 7, 4, 3 nu sunt considerate
secvenµe cool.
Cerinµe
Fiind dat un ³ir de N numere naturale nenule se cer urm toarele:
1. Pentru o valoare dat K s se verice dac secvenµa A1 , A2 , ..., AK este secvenµ cool.
Dac secvenµa este cool, atunci se va a³a cea mai mare valoare ce aparµine secvenµei. Dac
secvenµa nu este cool, atunci se va a³a num rul elementelor distincte din secvenµa A1 , A2 , ...,
AK , adic num rul elementelor care apar o singur dat .
2. Lungimea maxim a unei secvenµe cool ³i num rul secvenµelor cool de lungime maxim .
Date de intrare
Fi³ierul de intrare cool.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 linia a doua se g sesc, desp rµite
printr-un spaµiu, dou numere naturale N K . Pe urm toarea linie se g sesc N numere întregi,
separate prin câte un spaµiu, ce reprezint elementele ³irului.
Date de ie³ire
Dac valoarea lui p este 1, atunci se va rezolva numai punctul 1 din cerinµ . În acest caz, ³ierul
de ie³ire cool.out va conµine pe prima linie un num r natural, num r ce reprezint conform cerinµei
1, maximul secvenµei A1,A2, ...,AK , dac secvenµa este secvenµ cool, sau num rul elementelor
distincte din secvenµ , dac aceasta nu este secvenµ cool.
Dac valoarea lui p este 2, se va rezolva numai punctul 2 din cerinµ . În acest caz, ³ierul de
ie³ire cool.out va avea dou linii. Prima linie va conµine un num r natural nenul ce reprezint
lungimea maxim a unei secvenµe cool, iar urm toarea linie un num r natural nenul ce reprezint
num rul de secvenµe cool care au lungimea maxim .
Restricµii ³i preciz ri
a 1 & N & 5000
a 2 & K & 1000
a 1 & Ai & 1000, 1 & i & N
a Pentru 30% dintre teste N & 1000
a Pentru rezolvarea primei cerinµe se acord 20% din punctaj, iar pentru cerinµa a doua se
acord 80% din punctaj.
135
CAPITOLUL 7. OJI 2014 136
Exemple
col.in col.out Explicaµii
1 7 Atenµie! Pentru acest test se rezolv doar cerinµa 1.
7 4 Secvenµa 6 4 5 7 este cool.
6 457835 Valoarea maxim din secvenµ este 7
1 2 Atenµie! Pentru acest test se rezolv doar cerinµa 1.
7 6 Secvenµa 6 4 5 7 5 4 nu este secvenµ cool. Num rul
6 457543 valorilor distincte din secvenµ este 2. Valorile distincte
sunt: 6,7
2 5 Atenµie! Pentru acest test se rezolv doar cerinµa 2.
11 4 2 Cele dou secvenµe cool de lungime maxim 5 sunt:
74568457432 74568
68457
Cerinµa 1. ( 20 puncte)
Printr-o simpl vericare a frecvenµei de apariµie a primelor k numere se obµine r spunsul
a³teptat.
Cerinµa 2.
O soluµie brute-force obµine 25 p.
O soluµie bazat pe set(stl) obµine 40 50 p.
Soluµia 1. ( 80 puncte) (Eugen Nodea)
Rezolvarea cerinµei necesit câteva observaµii.
Fie secvenµa ce conµine k numere consecutive distincte:
x 1, x 2, ..., x k
Observ m c :
1) min x 1, max x k => max min k1
2) elementele sunt distincte
3) relaµia 1) este adev rat indiferent de ordinea elementelor
A³adar,
- pentru orice secvenµa care începe pe poziµia i si se termina pe poziµia j se va determina
minimul si maximul
- secvenµa este cool daca respecta relaµiile 1) si 2)
Astfel, complexitatea rezolv rii subpunctului b) poate redus la O N k amortizat.
Soluµia 2. ( 80 puncte) (Constantin Galatan)
Pentru secvenµa curent cuprins între poziµiile i ³i j , se menµine un ³ir de contoare pentru
valorile din secvenµ . La ad ugarea unui nou element aj în secvenµ se incrementeaz valoarea
contorului corespunz tor: cntaj , iar la eliminarea unui element ai din secvenµ , contorul
se decrementeaz : cntai . Se reµin de asemenea maximul ³i minimul valorilor din secvenµ
în amax ³i amin. La ecare pas se veric dac amax - amin == j - i ³i c nicio valoare din
2
secvenµ nu are contorul mai mare decât 1. Complexitatea soluµiei este O n
9
10 using namespace std;
11
12 int w[nmax],v[lmax];
13
14 int main()
15 {
16 int n,a[nmax],ok,nrsec=0,lsec=1,min,max,i,j,s,k,test,p,d;
17
18 ifstream f("cool.in");
19 ofstream g("cool.out");
20
21 f>>test;
22 f>>n>>p;
23 for(i=1;i<=n;i++)
24 f>>a[i];
25
26 // subpunctul a
27 if (test==1)
28 {
29 max=a[1];min=a[1];
30 for(i=1;i<=p;i++)
31 {
32 if (a[i]>max) max=a[i];
33 if (a[i]>max) max=a[i];
34 v[a[i]]=0;
35 }
36
37 for(i=1;i<=p;i++)
38 v[a[i]]++;
39 d=0;
40 for(i=1;i<=p;i++)
41 if (v[a[i]]==1)
42 d++;
43
44 if (d==p&&max-min==p-1)
45 g<<max<<"\n";
46 else
47 g<<d<<"\n";
48 }
49
50 // subpunctul 2
51 if (test==2)
52 {
53 w[1]=a[1];
54 for(i=2;i<=n;i++)
55 w[i]=w[i-1]+a[i];
56
57 for(i=1;i<=n-1;i++)
58 {
59 min=a[i];
60 max=a[i];
61 for(j=i+1;j<=n;j++)
62 {
63 if (a[j]<min) min=a[j];
64 if (a[j]>max) max=a[j];
65 if (a[j]==a[i]) break;
66 if (j-i==max-min)
67 {
68 s=w[j]-w[i-1];
69 if (s==max*(max+1)/2-min*(min-1)/2)
70 ok=1;
71 else
72 ok=0;
73
74 if (ok)
75 {
76 for(k=i;k<=j;k++)
77 v[a[k]]=0;
78
79 for(k=i;k<=j;k++)
80 {
81 v[a[k]]++;
82 if (v[a[k]]>1)
83 {
84 ok=0;
CAPITOLUL 7. OJI 2014 138
85 break;
86 }
87 }
88
89 // daca este secventa cool verific lungimea ei
90 if (ok)
91 {
92 if (max-min+1>lsec)
93 {
94 lsec=max-min+1;
95 nrsec=1;
96 }
97 else
98 if (max-min+1==lsec)
99 nrsec++;
100 }
101 }
102 }
103 }
104 }
105
106 g<<lsec<<"\n"<<nrsec<<"\n";
107 }
108
109 f.close();
110 g.close();
111
112 return 0;
113 }
42
43 freopen ("cool.in", "r", stdin);
44 freopen ("cool.out","w", stdout);
45
46 scanf("%d", &p);
47 scanf("%d %d", &n, &k);
48 for (i=1; i<=n; ++i)
49 scanf("%d", &a[i]);
50
51 if (p == 1)
52 { //a
53 for (i=1; i<=k; ++i)
54 {
55 ap[a[i]]++;
56 if (a[i] < Min) Min = a[i];
57 if (a[i] > Max) Max = a[i];
58 }
59
60 for (i=Min; i<=Max; ++i)
61 if (ap[i] == 1) ++nr_dist;
62
63 if (nr_dist == k)
64 printf("%d\n", Max);
65 else
66 printf("%d\n", nr_dist);
67 }
68 else
69 { //b
70 cool();
71 printf("%d\n%d\n", Max, nr);
72 }
73
74 return 0;
75 }
7.2 pseudobil
Problema 2 - pseudobil 100 de
puncte
Suprafaµa plan a unei mese de pseudo-biliard este format din n n celule p tratice cu
lungimea laturii egal cu 1 (o unitate), lipite, dispuse pe n linii numerotate de la 1 la n ³i n
coloane, numerotate de la 1 la n. Pe mas se a³eaz K bile, ecare bil g sindu-se în centrul unei
anumite celule a mesei. Un juc tor dore³te s plaseze pe suprafaµa mesei un cadru p tratic având
lungimea diagonalei egal cu D unit µi.
El trebuie s r spund la m întreb ri de forma: x y . Fiecare întrebare are semnicaµia: câte
bile se g sesc în interiorul sau pe laturile cadrului ?
Cadrul se plaseaz astfel încât ecare colµ s e poziµionat în centrul unei celule, colµurile
opuse s se g seasc pe aceea³i coloan , respectiv pe aceea³i linie, iar colµul de sus s e plasat
în centrul celulei aat pe linia x ³i coloana y .
Cerinµe
Cunoscând lungimea n a laturilor mesei, num rul m de întreb ri, num rul K de bile a³ezate
pe mas , poziµiile lor ³i lungimea D a diagonalei cadrului p tratic, se cere:
1. Num rul de celule care se vor g si în întregime în interiorul cadrului, dac acesta se a³eaz
pe suprafaµa mesei, conform descrierii de mai sus.
CAPITOLUL 7. OJI 2014 142
Date de intrare
Fi³ierul de intrare pseudobil.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 linia a doua se g sesc numerele naturale n, K ³i D separate prin câte un spaµiu.
Pe ecare dintre urm toarele K linii, se g sesc câte dou numere a ³i b (a, b & n) reprezentând
linia ³i coloana celulei în centrul c reia va a³ezat o bil .
Pe linia K 3 se g se³te un num r natural m.
Urm toarele m linii conµin câte dou numere naturale x ³i y , reprezentând linia ³i coloana
celulei în centrul c reia se va plasa colµul de sus al cadrului.
Date de ie³ire
Dac valoarea lui p este 1, se va rezolva numai punctul 1 din cerinµ . În acest caz, în ³ierul
de ie³ire pseudobil.out se va scrie un singur num r natural n1 , reprezentând num rul de celule
care se vor g si în întregime în interiorul cadrului.
Dac valoarea lui p este 2, se va rezolva numai punctul 2 din cerinµ . În acest caz, ³ierul de
ie³ire pseudobil.out va conµine m linii. Pe ecare linie i se va scrie câte un num r natural n2 ,
reprezentând r spunsul pentru întrebarea i.
Restricµii ³i preciz ri
a 3 & n & 1500
a 1 & K & 55000
a 2 & D & n 1, D - num r par
a 1 & m & 100000
a Poziµiile cadrului sunt distince.
a Se garanteaz pentru x ³i y valori pentru care cadrul este plasat în interiorul suprafeµei mesei
de pseudo-biliard.
a Pentru rezolvarea corect a primei cerinµe se acord 20 de puncte, iar pentru cerinµa a doua
se acord 80 de puncte.
a Pentru primele 35% dintre testele care veric cerinµa 2, m & 1000 ³i n & 500
a Pentru primele 75% din testele care veric cerinµa 2, m & 10000 ³i n & 1000
Exemple
Cerinµa 1 ( 20 puncte)
Se parcurg segmentele orizontale care conµin numai celule în interiorul p tratului.
Se observ c segmentul de lungime maxim are nr D 1 celule. Segmentul aat imediat
de deasupra ³i cel de dedesupt au ecare câte nr 2 celule. Soluµia va
nr1 nr 2 nr 2 2 nr 4 ... 2 1
Cerinµa 2 ( 80 de puncte)
Soluµie O m n2
Pentru ecare interogare, se parcurg orizontal toate segmentele formate din celule interioare
sau traversate pe diagonal de c tre laturile p tratului.
Acest soluµie obµine 30 de puncte din punctajul cerinµei 2.
Soluµie O m K (Ciprian Che³c )
Se ³tie c o dreapt de ecuaµie ax by c 0 împarte planul în dou semiplane cu proprietatea
c toate punctele dintr-un semiplan veric relaµia ax by c % 0 sau ax by c $ 0.
Notând vârfurile cadrului cu ABCD laturile acestuia formeaz 4 drepte : AB , CD respectiv
AD, BC . Putem considera c o bila se g se³te în interiorul cadrului dac bila se g se³te în
regiunea pozitiv a semiplanului AB ³i regiunea negativ a semiplanului CD ³i analog dac bila
se g se³te în regiunea pozitiv a semiplanului AD ³i regiunea negativ a semiplanului BC .
Calculând în ce semiplan se g se³te ecare bil în funcµie de poziµia cadrului se poate deduce
dac bila este în interiorul cadrului sau pe una din laturi.
Acest soluµie obµine 30 de puncte din punctajul cerinµei 2.
Soluµie O n2 m n
Pentru reducerea complexit µii la O n per interogare, se reµin sumele parµiale pentru ecare
coloan a matricei.
Fie deci matricea a, cu aij - num rul de bile aate pe coloana j , pân la linia i.
Se parcurge ecare segment vertical aat în interiorul cadrului ³i se calculeaz num rul de bile
ca ind ai2 j ai1 j unde i2 este linia pe care se g se³te ultima celul (cea mai de jos), iar
i1 este linia anterioar primei celule a segmentului.
Acest soluµie obµine 60 de puncte din punctajul cerinµei 2.
CAPITOLUL 7. OJI 2014 144
Pentru a aa num rul de bile din interiorul cadrului plasat cu colµul superior în centrul celulei
CAPITOLUL 7. OJI 2014 145
x, y , se fac sume ³i diferenµe de sume parµiale. V puteµi gândi la arii ³i la principiul includerii
³i excluderii.
Prin urmare, aria poligonului acoperit de cadru (num rul de bile acoperite) va egal cu aria
întregii suprafeµe, din care se scad ariile poligoanelor marcate cu ro³u, verde ³i albastru:
7 #include <vector>
8
9 using namespace std;
10
11 const int DIM = 1501;
12
13 ifstream fin("pseudobil.in");
14 ofstream fout("pseudobil.out");
15
16 typedef unsigned short M[2 * DIM][DIM];
17
18 M su, sd, pu, pd; // sec up, sec down, princ up, princ down
19 M a, b; // a[d][j] = 1 daca pe diagonala secundara d si coloana j
20 // este 1, b - acelasi lucru pentru diagonala principala d
21
22 int m, n, K, L, D, T, n1, n2;
23 unsigned short sc[DIM], ss[DIM], s[DIM]; // sume partiale pe coloane,
24 // suma dreptunghiului pana la col j
25 unsigned short sp1[DIM * 2], sp2[DIM * 2]; // suma pe diagonala curenta
26 // pana la coloana j
27
28 int main()
29 {
30 fin >> T >> n >> K >> D;
31 if ( T == 1 ) // rezolv numai cerinta 1)
32 {
33 int nr = D - 1;
34 n1 = nr;
35 while ( true )
36 {
37 nr -=2;
38 if ( nr < 0 ) break;
39 n1 += 2 * nr;
40 }
41
42 fout << n1 << ’\n’;
43 }
44 else // rezolv numai cerinta 2)
45 {
46 L = D / 2 + 1;
47 int d;
48 int x, y;
49
50 for ( int i = 0; i < K; ++i )
51 {
52 fin >> x >> y;
53 b[n + y - x][y] = 1;
54 a[x + y - 1][y] = 1;
55 s[y]++;
56 }
57
58 for ( int j = 1; j <= n; ++j )
59 ss[j] = ss[j - 1] + s[j];
60
61 for ( int d = 1; d < 2 * n; ++d )
62 {
63 for (int j = 0; j <= n; ++j )
64 sp1[j] = 0, sp2[j] = 0;
65
66 for ( int j = max(d - n + 1, 1); j <= min(d, n) ; ++j )
67 {
68 sp1[j] = sp1[j - 1] + a[d][j];
69 su[d][j] = su[d - 1][j] + sp1[j];
70
71 if ( j >= d ) su[d][j] += su[d - 1][j - 1];
72
73 sd[d][j] = ss[j] - su[d][j] + sp1[j];
74
75 sp2[j] = sp2[j - 1] + b[d][j];
76 pd[d][j] = pd[d - 1][j] + sp2[j];
77
78 if ( j >= d )
79 pd[d][j] += pd[d - 1][j - 1];
80
81 pu[d][j] = ss[j] - pd[d][j] + sp2[j];
82 }
CAPITOLUL 7. OJI 2014 147
83 }
84
85 int A, B, C, D, E, F;
86 fin >> m;
87
88 for ( int i = 0; i < m; ++i )
89 {
90 fin >> x >> y;
91
92 A = ss[y - L];
93 B = K - ss[y + L - 1];
94 if ( y > x + y - 2 )
95 C = su[x + y - 2][y - 1];
96 else
97 C = su[x + y - 2][y];
98
99 C -= su[x + y - 2][y - L];
100 D = pu[n - x + y + 1][y + L - 1] - pu[n - x + y + 1][y];
101
102 int X = x + 2 * (L - 1);
103 if ( y > n - X + y - 1)
104 E = pd[n - X + y - 1][y - 1];
105 else
106 E = pd[n - X + y - 1][y];
107
108 E -= pd[n - X + y -1][y - L];
109 F = sd[X + y ][y + L - 1] - sd[X + y ][y];
110 n2 = K - (A + B + C + D + E + F);
111
112 fout << n2 << ’\n’;
113 }
114 }
115
116 fin.close();
117 fout.close();
118 return 0;
119 }
36 else
37 { //2.
38 f >> m;
39 while (m--)
40 {
41 f >> x >> y;
42 x1 = x+y-1; y1 = n-x+y;
43 sol = nr[x1+D][y1] - nr[x1+D][y1-D-1] -
44 nr[x1-1][y1] + nr[x1-1][y1-D-1];
45
46 g << sol <<"\n";
47 }
48 }
49
50 return 0;
51 }
57 x2=n-(y+d/2)+x+d/2;
58 y2=x+d/2+y+d/2-1;
59 x3=n-y+x+d;
60 y3=x+d+y-1;
61 x4=n-(y-d/2)+x+d/2;
62 y4=x+d/2+(y-d/2)-1;
63 n2=a[x3][y3]-a[x2-1][y2]-(a[x4][y4-1]-a[x1-1][y1-1]);
64 fprintf(g,"%d\n",n2);
65 }
66 }
67
68 fclose(f);
69 fclose(g);
70 return 0;
71 }
OJI 2013
8.1 betasah
Problema 1 - betasah 100 de puncte
Jocul beta³ah se joac folosindu-se doar piese asem n toare damelor clasicului ³ah, numite
N N 1
tot dame. Suprafaµa de joc are o form triunghiular ³i este format din 2
p trate identice
dispuse pe N rânduri ³i N coloane. Rândurile se numeroteaz de sus în jos, de la 1 la N . Coloanele
se numeroteaz de la stânga la dreapta, de la 1 la N . Primul rând conµine un singur p trat, al
doilea rând conµine dou p trate al turate, ..., al N -lea rând conµine N p trate al turate, ca în
N N 1
suprafeµele de joc cu N 6 din gurile de mai jos. Din cele 2
p trate, K sunt gri, iar restul
sunt albe. Poziµia ec rui p trat de pe suprafaµa de joc este dat de rândul ³i coloana în care
acesta este situat.
Pe suprafaµa de joc sunt a³ezate D dame în D p trate albe distincte, ocupându-le. Într-un
p trat alb poate a³ezat o singur dam , iar într-un p trat gri nu poate a³ezat nicio dam .
Poziµia unei dame pe suprafaµa de joc este dat de poziµia p tratului alb în care este a³ezat
dama.
Damele pot accesa orice p trat alb neocupat situat pe direcµiile: vertical , orizontal sau
diagonal , numerotate de la 1 la 8 în gura b). Accesul pe o direcµie se face trecând din p trat alb
în p trat alb (doar p trate albe neocupate) pân la întâlnirea unui p trat gri sau a unui p trat
alb ocupat de o alt dam sau pân la terminarea suprafeµei de joc.
Numim p trat accesibil orice p trat alb neocupat (de pe suprafaµa de joc) care ar putea
accesat de cel puµin una din cele D dame.
De exemplu, pentru suprafaµa de joc din gura c) num rul de p trate accesibile (marcate cu
X ) de pe suprafaµ este 11; pentru suprafaµa de joc cu N 6, D 3 ³i K 4 din gura d)
num rul de p trate accesibile de pe suprafaµ este 13. În gura e) sunt marcate cu X p tratele
accesibile ec rei dame de pe suprafaµa de joc din gura d).
151
CAPITOLUL 8. OJI 2013 152
Cerinµe
Scrieµi un program care s citeasc numerele naturale N , D, K , poziµiile damelor ³i ale p tra-
telor gri pe suprafaµa de joc ³i care s determine:
a) num rul maxim M de p trate albe conµinute de un rând al suprafeµei de joc;
b) num rul P de p trate accesibile de pe suprafaµa de joc.
Date de intrare
Fi³ierul de intrare betasah.in conµine:
- pe prima linie cele trei numere naturale N , D ³i K , separate prin câte un spaµiu, cu semni-
caµia din enunµ;
- pe linia i 1 dou numere naturale nenule xi ³i yi , separate printr-un singur spaµiu, repre-
zentând poziµia damei i pe suprafaµa de joc (rândul xi ³i coloana yi ), pentru i 1, 2, 3, ..., D;
- pe linia D 1 j dou numere naturale nenule zj ³i tj , separate printr-un singur spaµiu,
reprezentând poziµia p tratului gri j pe suprafaµa de joc (rândul zj ³i coloana tj ), pentru j
1, 2, 3, ..., K .
Date de ie³ire
Fi³ierul de ie³ire betasah.out va conµine pe prima linie num rul natural M ³i pe a doua linie
num rul natural P , cu semnicaµia din enunµ.
Restricµii ³i preciz ri
a 2 & N & 1000;
a 1 & D & 100;
a 1 & K & 50;
a DK &
N n1
2
;
a 1 & yi & xi & N pentru i 1, 2, 3, ..., D;
a 1 & tj & zj N pentru j 1, 2, 3, ..., K ;
a num rul M se va scrie obligatoriu pe prima linie a ³ierului de ie³ire betasah.out;
a num rul P se va scrie obligatoriu pe a doua linie a ³ierului de ie³ire betasah.out;
a pentru rezolvarea corect a cerinµei a) se acord 20% din punctaj, iar pentru rezolvarea
corect a cerinµei b) se acord 80% din punctaj.
Exemple
Pentru punctul a), se poate utiliza un vector v cu N componente care, iniµial, memoreaz în
ecare v i num rul maxim de p trate albe de pe rândul i: v i i pentru i 1, 2, 3, ..., N .
La citirea rândului i ³i a coloanei j pentru ecare p trat gri se decrementeaz valoarea com-
ponentei v i.
Num rul maxim M de p trate albe care pot conµinute de un rând al suprafeµei de joc este
egal cu maximul valorilor componentelor vectorului v , M max v 1, v 2, ..., v N
Pentru punctul b), o soluµie se poate obµine utilizând o matrice A cu N linii si N coloane.
Partea inferioar a matricei, format din elementele situate sub diagonala principal inclusiv
diagonala principal , vor reprezenta p tratele din suprafaµa de joc.
Iniµial, matricea va avea toate elementele cu valoarea 0, adic toate p tratele sunt albe.
Elementele matricei care corespund poziµiilor damelor vor avea valoarea 1, iar cele corespun-
z toare p tratelor gri vor avea valoarea 2. Pentru ecare dam se va simula deplasarea pe cele
8 direcµii. Dac dama se a în p tratul din poziµia l, c atunci aceasta se poate deplasa în
p tratele accesibile ale c ror poziµii corespund elementelor cu valoarea 0 din partea inferioar a
matricei ³i sunt situate în direcµia:
- 1, prin mic³orarea indicelui de linie: l 1, c, l 2, c, l 3, c etc.
- 5, prin m rirea indicelui de linie: l 1, c, l 2, c, l 3, c etc.
- 7, pe aceea³i linie, la stânga, prin mic³orarea indicelui de coloan :
l, c 1, l, c 2, l, c 3 etc.
- 3, pe aceea³i linie, la dreapta, prin m rirea indicelui de coloan : l, c
1, l, c 2, l, c 3 etc.
- 8, diagonal , prin mic³orarea indicilor de linie ³i coloan : l 1, c
1, l 2, c 2, l 3, c 3 etc. Figura 8.4: betasah
- 4, diagonal , prin m rirea indicilor de linie ³i coloan : l 1, c 1, l 2, c 2, l 3, c 3
etc.
- 2, diagonal , prin mic³orarea indicelui de linie ³i m rirea celui de coloan : l 1, c 1, l
2, c 2, l 3, c 3 etc.
- 6, diagonal , prin m rirea indicelui de linie ³i mic³orarea celui de coloan : l 1, c 1, l
2, c 2, l 3, c 3 etc.
Elementele matricei ce corespund p tratelor accesibile vor memora valoarea 3.
Pentru a se evita ie³irea din suprafaµa de joc în timpul c ut rii poziµiilor accesibile, se poate
borda partea inferioar a matricei cu valori de 2 sau se vor verica indicii ec rei poziµii accesibile
x, y : 1 $ x $ N ³i 1 $ y $ x.
Dup stabilirea p tratelor accesibile pentru ecare dam , partea inferioar a matricei va avea
elemente cu valoarea 3 ce corespund acestor p trate. Parcurgând partea inferioar a matricei, se
vor num ra aceste valori de 3. Num rul lor va reprezenta num rul P de p trate accesibile de pe
suprafaµa de joc.
Observaµie: o soluµie care const în parcurgerea integral a suprafeµei de joc ³i vericarea
pentru ecare p trat alb dac pe una din cele 8 direcµii exist vreo dam care s -l acceseze va
obµine un punctaj de aprox. 55p din cauza dep ³irii timpului de executare.
9
10 ifstream f("betasah.in");
11 ofstream g("betasah.out");
12
13 int main()
14 {
15 //citire date
16 int i,l,c,j,i1;
17 f>>n>>d>>k;
18 for(i=1;i<=d;i++)
19 {
20 f>>l>>c;
21 a[l][c]=1;//codific cu 1 pozitia damei din joc
22 pozdama[i][1]=l;pozdama[i][2]=c;
23 }
24
25 for(i=1;i<=n;i++) albe[i]=i;
26 for(i=1;i<=k;i++)
27 {
28 f>>l>>c;
29 a[l][c]=2;//codific cu 2 patratele gri din joc
30 albe[l]--;//scad patratele gri din nr total de patrate de pe linia l
31 }
32
33 int M=albe[1]; //a)
34 for(i=2;i<=n;i++)M=max(albe[i],M);
35
36 //bordare matrice. Incadrez suprafata de joc cu patrate gri
37 //pentru a nu iesi din suprafata de joc
38 for(i=0;i<=n+1;i++)
39 a[i][0]=a[i][i+1]=a[i][i+2]=2;
40 for(j=0;j<=n+2;j++)
41 a[n+1][j]=2;
42
43 //determin pentru fiecare dama patratele accesibile
44 for(i=1;i<=d;i++)
45 {
46 l=pozdama[i][1];
47 c=pozdama[i][2];
48
49 //pe aceeasi linie
50 j=c-1;
51 while(a[l][j]!=2)//directia 7
52 {
53 if(a[l][j]==0)a[l][j]=3;
54 j--;
55 }
56 j=c+1;
57 while(a[l][j]!=2)//directia 3
58 {
59 if(a[l][j]==0)a[l][j]=3;
60 j++;
61 }
62
63 //pe aceeasi coloana
64 i1=l-1;
65 while(a[i1][c]!=2)//directia 1
66 {
67 if(a[i1][c]==0)a[i1][c]=3;
68 i1--;
69 }
70 i1=l+1;
71 while(a[i1][c]!=2)//directia 5
72 {
73 if(a[i1][c]==0)a[i1][c]=3;
74 i1++;
75 }
76
77 //pe diagonala 8-4
78 i1=l-1;
79 j=c-1;
80 while (a[i1][j]!=2)//directia 8
81 {
82 if(a[i1][j]!=1)
83 a[i1][j]=3;//marchez cu 3 patratele accesibile
84 i1--;
CAPITOLUL 8. OJI 2013 155
85 j--;
86 }
87
88 i1=l+1;
89 j=c+1;
90 while (a[i1][j]!=2)//directia 4
91 {
92 if(a[i1][j]!=1)
93 a[i1][j]=3;
94 i1++; j++;
95 }
96
97 //pe diagonala 2-6
98 i1=l-1;
99 j=c+1;
100 while (a[i1][j]!=2)//spre 2
101 {
102 if(a[i1][j]!=1) a[i1][j]=3;
103 i1--;
104 j++;
105 }
106
107 i1=l+1;
108 j=c-1;
109 while (a[i1][j]!=2)//spre 6
110 {
111 if(a[i1][j]!=1)
112 a[i1][j]=3;
113 i1++;
114 j--;
115 }
116 }
117
118 //numarul patratelor accesibile = nr valori de 3 din matrice
119 int P=0;
120 for(i=1;i<=n;i++)
121 for(j=1;j<=i;j++)
122 if(a[i][j]==3)
123 P++;
124
125 g<<M<<endl<<P<<endl;
126
127 return 0;
128 }
29 }
30 }
31
32 void bordare()//incadrez suprafata de joc cu patrate gri
33 //pentru a nu iesi din suprafata de joc
34 {
35 int i,j;
36 for(i=0;i<=n+1;i++)
37 a[i][0]=a[i][i+1]=a[i][i+2]=2;
38 for(j=0;j<=n+2;j++)
39 a[n+1][j]=2;
40 }
41
42 void linie(int l,int c) //deplasare dama pe aceeasi linie
43 {
44 int j=c-1;
45 while(a[l][j]!=2)//directia 7
46 {
47 if(a[l][j]==0)a[l][j]=3;
48 j--;
49 }
50
51 j=c+1;
52 while(a[l][j]!=2)//directia 3
53 {
54 if(a[l][j]==0)a[l][j]=3;
55 j++;
56 }
57 }
58
59 void coloana(int l,int c)//deplasare dama pe aceeasi coloana
60 {
61 int i=l-1;
62 while(a[i][c]!=2)//directia 1
63 {
64 if(a[i][c]==0)a[i][c]=3;
65 i--;
66 }
67
68 i=l+1;
69 while(a[i][c]!=2)//directia 5
70 {
71 if(a[i][c]==0)a[i][c]=3;
72 i++;
73 }
74 }
75
76 void diag1(int l,int c)//deplasare dama pe directia 8-4
77 {
78 int i,j;
79 i=l-1;
80 j=c-1;
81 while (a[i][j]!=2)//directia 8
82 {
83 if(a[i][j]!=1) a[i][j]=3;//marchez cu 3 patratele accesibile
84 i--;
85 j--;
86 }
87
88 i=l+1;
89 j=c+1;
90 while (a[i][j]!=2)//directia 4
91 {
92 if(a[i][j]!=1)
93 a[i][j]=3;
94 i++;
95 j++;
96 }
97 }
98
99 void diag2(int l,int c)//deplasare dama pe directia 2-6
100 {
101 int i,j;
102 i=l-1;
103 j=c+1;
104 while (a[i][j]!=2)//directia 2
CAPITOLUL 8. OJI 2013 157
105 {
106 if(a[i][j]!=1) a[i][j]=3;
107 i--;
108 j++;
109 }
110
111 i=l+1;
112 j=c-1;
113 while (a[i][j]!=2)//directia 6
114 {
115 if(a[i][j]!=1)
116 a[i][j]=3;
117 i++;
118 j--;
119 }
120 }
121
122 int numara()
123 {
124 //numarul patratelor accesibile = nr valori de 3 din matrice
125 int i,j,P=0;
126 for(i=1;i<=n;i++)
127 for(j=1;j<=i;j++)
128 if(a[i][j]==3)
129 P++;
130 return P;
131 }
132
133 int main()
134 {
135 int i,l,c,M;
136
137 citeste();
138 bordare();
139
140 M=v[1];
141 for(i=2;i<=n;i++) M=max(M,v[i]);
142 for(i=1;i<=d;i++)
143 {
144 l=pozdama[i][1];
145 c=pozdama[i][2];
146 linie(l,c);
147 coloana(l,c);
148 diag1(l,c);
149 diag2(l,c);
150 }
151
152 g<<M<<endl<<numara()<<endl;
153
154 return 0;
155 }
22 for(i=1;i<=d;i++)
23 {
24 f>>l>>c;
25 a[l][c]=1;//codific cu 1 pozitia damei din joc
26 pozdama[i][1]=l;pozdama[i][2]=c;
27 }
28
29 for(i=1;i<=n;i++)albe[i]=i;
30 for(i=1;i<=k;i++)
31 {
32 f>>l>>c;
33 a[l][c]=2;//codific cu 2 patratele gri din joc
34 albe[l]--;//scad patratele gri din nr total de patrate de pe linia l
35 }
36
37 M=albe[1]; //a)
38 for(i=2;i<=n;i++) M=max(albe[i],M);
39 g<<M<<endl;
40
41 //bordare matrice. Incadrez suprafata de joc cu patrate gri
42 //pentru a nu iesi din suprafata de joc
43 for(i=0;i<=n+1;i++)
44 a[i][0]=a[i][i+1]=a[i][i+2]=2;
45 for(j=0;j<=n+2;j++)
46 a[n+1][j]=2;
47
48 //determin pentru fiecare dama patratele accesibile
49 for(i=1;i<=d;i++)
50 {
51 l=pozdama[i][1];
52 c=pozdama[i][2];
53 //pe aceeasi linie
54 j=c-1;
55
56 while(a[l][j]!=2)//directia 7
57 {
58 if(a[l][j]==0) a[l][j]=3;
59 j--;
60 }
61
62 j=c+1;
63 while(a[l][j]!=2)//directia 3
64 {
65 if(a[l][j]==0) a[l][j]=3;
66 j++;
67 }
68
69 //pe aceeasi coloana
70 i1=l-1;
71 while(a[i1][c]!=2)//directia 1
72 {
73 if(a[i1][c]==0) a[i1][c]=3;
74 i1--;
75 }
76
77 i1=l+1;
78 while(a[i1][c]!=2)//directia 5
79 {
80 if(a[i1][c]==0) a[i1][c]=3;
81 i1++;
82 }
83
84 //pe diagonala 8-4
85 i1=l-1;
86 j=c-1;
87 while (a[i1][j]!=2)//directia 8
88 {
89 if(a[i1][j]!=1) a[i1][j]=3;//marchez cu 3 patratele accesibile
90 i1--;
91 j--;
92 }
93
94 i1=l+1;
95 j=c+1;
96 while (a[i1][j]!=2)//directia 4
97 {
CAPITOLUL 8. OJI 2013 159
98 if(a[i1][j]!=1) a[i1][j]=3;
99 i1++;
100 j++;
101 }
102
103 //pe diagonala 2-6
104 i1=l-1;
105 j=c+1;
106 while (a[i1][j]!=2)//directia 2
107 {
108 if(a[i1][j]!=1) a[i1][j]=3;
109 i1--;
110 j++;
111 }
112
113 i1=l+1;
114 j=c-1;
115 while (a[i1][j]!=2)//directia 6
116 {
117 if(a[i1][j]!=1) a[i1][j]=3;
118 i1++;
119 j--;
120 }
121 }
122
123 //numarul patratelor accesibile = nr valori de 3 din matrice
124 for(i=1;i<=n;i++)
125 for(j=1;j<=i;j++)
126 if(a[i][j]==3) P++;
127 g<<P<<endl;
128 return 0;
129 }
41 {
42 T[i][0]=-1;
43 T[N+1][i]=-1;
44 T[0][i]=-1;
45 }
46
47 for (i=1;i<=D;i++)
48 {
49 l=Dame[0][i];
50 c=Dame[1][i];
51 T[l][c]=0;
52
53 // directia NORD
54 while (l>=c && (abs)((float)T[l][c])!=1)
55 {
56 T[l][c]=3;
57 --l;
58 }
59
60 l=Dame[0][i];
61 c=Dame[1][i];
62
63 // directia Nord Est
64 while (l>=c &&(abs)((float)T[l][c])!=1)
65 {
66 T[l][c]=3;
67 --l;
68 ++c;
69 }
70
71 l=Dame[0][i];
72 c=Dame[1][i];
73
74 // directia Est
75 while (l>=c && (abs)((float)T[l][c])!=1)
76 {
77 T[l][c]=3;c++;
78 }
79
80 l=Dame[0][i];
81 c=Dame[1][i];
82
83 // directia Sud Est
84 while ((abs)((float)T[l][c])!=1)
85 {
86
87 T[l][c]=3;
88 l++;
89 c++;
90 }
91
92 l=Dame[0][i];
93 c=Dame[1][i];
94
95 // directia Sud
96 while ((abs)((float)T[l][c])!=1)
97 {
98 T[l][c]=3;
99 l++;
100 }
101
102 l=Dame[0][i];
103 c=Dame[1][i];
104
105 // directia Sud Vest
106 while ( (abs)((float)T[l][c])!=1)
107 {
108 T[l][c]=3;
109 ++l;
110 --c;
111 }
112
113 l=Dame[0][i];
114 c=Dame[1][i];
115
116 // directia Vest
CAPITOLUL 8. OJI 2013 161
115 }
116 ++l;
117 }
118
119 l=d[0][i];
120 c=d[1][i];
121
122 // directia oblic stanga-jos
123 while (l<=N && c>0 && a[l][c]!=-1)
124 {
125 if (a[l][c]==0)
126 {
127 ++atacate; // se numara orice camp nenumarat
128 a[l][c]=1; //
129 }
130 ++l;
131 --c;
132 }
133
134 l=d[0][i];
135 c=d[1][i];
136
137 // directia orizontala-dreapta
138 while (c>0 && a[l][c]!=-1)
139 {
140 if (a[l][c]==0)
141 {
142 ++atacate; // se numara orice camp nenumarat
143 a[l][c]=1; //
144 }
145 --c;
146 }
147
148 l=d[0][i];
149 c=d[1][i];
150
151 // directia oblic-stanga-sus
152 while (c>0 && a[l][c]!=-1)
153 {
154 if (a[l][c]==0)
155 {
156 ++atacate; // se numara orice camp nenumarat
157 a[l][c]=1; //
158 }
159 --c;
160 --l;
161 }
162 }
163
164 fout <<maxalbe<<endl<<atacate<< endl;
165
166 fin.close();
167 fout.close();
168 return 0;
169 }
8.2 clepsidru
Problema 2 - clepsidru 100 de
puncte
O clepsidr este un dispozitiv folosit pentru a m sura timpul. Clepsidra este
alc tuit din dou incinte de sticl , conectate printr-un tub n. Una dintre incinte este
umplut cu nisip, acesta scurgându-se în cea de-a doua incint , cu o vitez constant .
Clepsidra poate întoars , pentru a m sura o alt perioad de timp.
Arheologii au descoperit un dispozitiv, pe care l-au denumit clepsidru, format
din n clepsidre identice, suprapuse, numerotate de la 1 la n, prin care nisipul poate Figura 8.5:
circula de la o clepsidr la alta datorit forµei gravitaµionale. clepsidru
CAPITOLUL 8. OJI 2013 164
Date de intrare
Prima linie a ³ierului de intrare clepsidru.in conµine dou numere naturale nenule n ³i b,
separate printr-un singur spaµiu, cu semnicaµia din enunµ; a doua linie conµine num rul natural
nenul k având semnicaµia din enunµ, iar urm toarele k linii conµin ecare câte o pereche de valori
si ³i pi , 1 & i & k , separate printr-un singur spaµiu, cu semnicaµia din enunµ.
Date de ie³ire
Fi³ierul de ie³ire clepsidru.out va conµine pe prima linie un num r natural ce reprezint
valoarea obµinut la primul experiment, iar pe urm toarele n linii va conµine câte o pereche de
numere naturale, separate printr-un singur spaµiu, ce reprezint cantit µile de boabe de nisip din
incintele de sus ³i de jos ale celor n clepsidre, scrise în ordinea de la 1 la n a clepsidrelor, dup
realizarea celui de-al doilea experiment.
Restricµii ³i preciz ri
a 1 & n & 1000;
a 1 & b & 1000000000;
a 1 & k & 1000;
a 1 & si & 1000, 1 & i & k ;
a pi " 1, 2, 1 & i & k ;
a pentru rezolvarea corect a primei cerinµe se acord 25% din punctaj, iar pentru rezolvarea
corect a celei de-a doua cerinµe se acord 75% din punctaj.
a acordarea punctajului pentru a doua cerinµ se face numai dac în ³ierul de ie³ire exist un
r spuns pentru prima cerinµ , indiferent de corectitudinea acestuia.
CAPITOLUL 8. OJI 2013 165
Exemple
CAPITOLUL 8. OJI 2013 166
Varianta nr. 1
autor prof. Che³c Ciprian - Liceul Tehnologic Costin Neniµescu Buz u
<
Soluµie în O n si - C++
Valoarea cerut de primul experiment, adic dup câte secunde ajung toate boabele de nisip
în incinta de jos a ultimei clepsidre, se determin cu formula n b 1. Justicarea este urm toarea:
la ecare secund câte un bob de nisip cade în clepsidra urm toare, a³adar ultimul bob de nisip
din incinta de sus a primei clepsidre întârzie b 1 secunde pân începe s cad , iar pentru a c dea
are nevoie de n secunde, câte clepsidre sunt.
Pentru a r spunde cerinµei celui de-al doilea experiment, adic pentru a preciza num rul de
boabe de nisip din incintele clepsidrelor, dup cele k a³ez ri consecutive, am f cut o simulare
la nivel de secund . La ecare secund am simulat curgerea boabelor de nisip într-unul sau în
cel lalt sens de curgere, în funcµie de poziµie. La citirea unei noi poziµii am simulat, dac era
cazul, r sturnarea clepsidrului ³i rea³ezarea boabelor de nisip.
Varianta nr. 2
prof. Szabo Zoltan - Inspectoratul ³colar Judeµean Mure³
Dac clepsidra este în starea 2, procedeul este identic, dar cu direcµie invers .
La tip rire vom avea grij s vedem ultima stare a clepsidrului, indc în incintele intermediare
vom avea 0 1 sau 1 0 boabe de nisip.
Varianta nr.3
prof. Rodica Moldovan - C.N. Gheorghe ³incai Baia Mare
2
Soluµie în O k n - C++
Vom lucra într-un vector stare1001, în care vom p stra num rul de boabe din ecare clepsidr
la un moment dat. Iniµializ m staren b;
Vom folosi urm toarele notaµii:
l - nivelul de pe care pornesc boabele,
k - nivelul pe care ajung boabele
s - num r de secunde într-o anumit stare
Pentru ecare pereche citit (secunde poziµie) vom actualiza (vectorul stare) num rul de boabe
din clepsidre (nu la nivel de secund ci funcµie de l, k , s)
La ecare actualizare, num rul de boabe b se iniµializeaz cu num rul de boabe aate în
recipientul de pornire b starel
Se disting urm toarele situaµii:
transformareJos(int l, int k, int s)
a Dac (l 0) && (k 0)
atunci suntem pe nivelul inferior ³i boabele nu coboar , deci poziµia din vectorul stare se va
actualiza cu b
a Dac (l k)
atunci num rul de boabe r mase în recipientul iniµial va max 0, b s;
a Dac (k 0)
atunci num rul de boabe adunate în recipientul inferior va max 0, min b, s l k 1;
a Dac (s $ l k )
atunci timpul este mai mic decât timpul necesar s ajung o boab în recipient ³i vom actualiza
cu 0
a Dac (s ' b l k )
atunci boabele au trecut deja prin recipient ³i vom actualiza cu 0
a Altfel boaba se aa în tranziµie prin recipient ³i vom actualiza cu 1
Varianta nr. 4
prof. Popa Daniel - C.N. Aurel Vlaicu Or ³tie
71 u[j]--;
72 u[j+1]++;
73 }
74 }
75
76 // clepsidru in pozitia 2
77 if (sens==-1)
78 {
79 if (d[1]>0)
80 {
81 d[1]--;
82 u[1]++;
83 }
84
85 for(j=2;j<=n;j++)
86 if (d[j]>0)
87 {
88 d[j]--;
89 d[j-1]++;
90 }
91 }
92
93 }
94
95 sensv=sens;
96 }
97
98 // afisez a doua cerinta
99 for(i=1;i<=n;i++)
100 g<<u[i]<<" "<<d[i]<<"\n";
101
102 f.close();
103 g.close();
104
105 return 0;
106 }
65 return 0;
66 }
147 }
148
149 if (sus>0 && jos==n && stare==2)
150 {
151 c[n][2]=bjos;
152 for(i=sus;i<jos;++i)
153 c[i][2]=1;
154 }
155
156 if (sus>0 && jos<n && stare==1)
157 {
158 for(i=sus+1;i<=jos+1;++i)
159 c[i][1]=1;
160 }
161
162 if (sus>0 && jos<n && stare==2)
163 {
164 for(i=sus;i<=jos;++i)
165 c[i][2]=1;
166 }
167
168 for (i=1;i<=n;++i)
169 fout<<c[i][1]<<" "<<c[i][2]<<"\n";
170
171 fin.close();
172 fout.close();
173
174 return 0;
175 }
OJI 2012
9.1 elicop
Problema 1 - elicop 100 de puncte
Un teren de fotbal este folosit pentru aterizarea elicopterelor. Gazonul de pe stadion este
parcelat în p tr µele de aceea³i dimensiune, cu laturile paralele cu marginile terenului. Liniile cu
p tr µele de gazon sunt numerotate de sus în jos cu numerele 1, 2, ..., m, iar coloanele cu p tr µele
de gazon sunt numerotate de la stânga la dreapta cu numerele 1, 2, ..., n.
Din cauza tipului diferit de iarb se ³tie care dintre p tr µele de gazon sunt afectate sau nu
de umbr . Acest lucru este precizat printr-un tablou bidimensional a cu m linii ³i n coloane, cu
elemente 0 ³i 1 (aij 0 înseamn c p tr µelul aat pe linia i ³i coloana j este afectat de umbr ,
iar aij 1 înseamn c p tr µelul aat pe linia i ³i coloana j nu este afectat de umbr ).
Fiecare elicopter are 3 roµi pe care se sprijin . Roµile ec rui elicopter determin un triunghi
dreptunghic isoscel. Elicopterele aterizeaz , astfel încât triunghiurile formate s e cu catetele
paralele cu marginile terenului. în exemplul urm tor avem patru elicoptere.
Pentru a preciza poziµia unui elicopter pe teren este sucient s cunoa³tem linia ³i coloana
v rfurilor ipotenuzei ³i poziµia vârfului deasupra (codicat prin 1) sau dedesubtul ipotenuzei
(codicat prin 1). Pentru exemplu, elicopterul din stânga sus este dat prin 1, 1, 3, 3 ³i 1,
cel din dreapta sus prin 1, 9, 5, 5 ³i 1, cel din stânga jos prin 5, 1, 6, 2 ³i 1, iar cel din
dreapta jos prin 5, 9, 6, 8 ³i 1.
Un elicopter se consider c a aterizat gre³it, dac triunghiul format sub el (denit mai sus)
are mai mult de jum tate din p tr µele afectate de umbr .
Administratorul terenului de fotbal dore³te s determine num rul N 1 de elicoptere, care nu
afecteaz nici un p tr µel din teren ³i numerele de ordine al elicopterelor, care au aterizat gre³it în
ordine cresc toare: e1 , e2 , ..., eN 2 , ³tiind c exist k elicoptere codicate prin numerele 1, 2, ..., k .
Cerinµe
Scrieµi un program care s determine, pentru ³ierul cu datele din enunµ: num rul de elicoptere
N 1, care nu afecteaz nici un p tr µel din teren ³i numerele de ordine al elicopterelor, care au
aterizat gre³it în ordine cresc toare, precedate de num rul lor N 2.
Date de intrare
Prima linie a ³ierului de intrare elicop.in conµine dou numere naturale m ³i n, separate
printr-un spaµiu, cu semnicaµia din enunµ.
175
CAPITOLUL 9. OJI 2012 176
Urm toarele m linii conµin câte n numere 0 sau 1, separate prin câte un spaµiu cu semnicaµia
0 - p tr µel de gazon care este afectat de umbr , respectiv 1 - p tr µel care nu este afectat de
umbr .
Pe linia m 2 se a num rul de elicoptere k , iar pe urm toarele k linii (în ordinea codic rii
lor 1, 2, ..., k ) câte cinci numere separate prin cate un spaµiu, pentru liniile ³i coloanele ipotenuzelor
³i poziµia vârfului (1 sau 1), triunghiurilor dreptunghice asociate elicopterelor:
L1 C1 L2 C2 p
Date de ie³ire
Fi³ierul de ie³ire elicop.out va conµine dou linii: prima linie num rul N 1 de elicoptere, care
nu afecteaz nici un p tr µel din teren, a doua linie cu numerele naturale N 2, e1 , e2 , ..., e N 2
separate prin câte un spaµiu, în ordine cresc toare.
Restricµii ³i preciz ri
a2 & m, n & 100; 1 & k & 40
aNu exist suprapuneri de triunghiuri asociate la dou elicoptere. Triunghiurile asociate
elicopterelor conµin cel puµin trei p tr µele.
a Pentru determinarea corect a valorilor N 1 se obµine 40% din punctajul unui test, iar pentru
determinarea corect a valorilor N 2, e1 , e2 , ..., eN 2 se obµine 60% din punctajul unui test.
Exemple
elicop.in elicop.out Explicaµii
7 9 2 Elicopterele 2 ³i 4 nu afecteaz niciun p tr µel de gazon.
1 1 1 1 1 1 1 1 1 213
0 0 0 0 1 1 1 1 0 Elicopterele 1 ³i 3 afecteaz ecare mai mult de jum tate din
0 0 1 0 1 1 1 0 0 num rul p tr µelelor asociate triunghiurilor dreptunghice ³i
1 1 1 0 1 1 0 1 1 deci aterizeaz gre³it. Elicopterul 1 face umbr la 6 p tr µele,
0 0 1 1 1 1 0 1 1 din care afectate sunt 4.
1 1 1 1 1 1 0 1 1
1 1 1 1 1 1 0 0 1 Elicopterul 3 face umbr la 3 p tr µele, din care afectate sunt
4 dou .
1 1 3 3 -1
1 9 5 5 1
5 1 6 2 1
5 9 6 8 1
Pentru tabloul a cu elementele ai, j , 1 & i & m, 1 & j & n, un elicopter dat prin L1, C1, L2, C2
³i p poate avea în una din poziµiile:
47 f>>x1>>y1>>x2>>y2>>v;
48
49 d=(x2-x1)*(y2-y1);
50
51 if (d>0&&v==-1) tip=1;
52 if (d>0&&v==1) tip=2;
53 if (d<0&&v==1) tip=3;
54 if (d<0&&v==-1) tip=4;
55
56 pg=0;
57 switch (tip)
58 {
59 case 1 :{
60 for(l=1;l<=max(x1,x2)-min(x1,x2)+1;l++)
61 for(c=1;c<=l;c++)
62 if (t[l+min(x1,x2)-1][c+min(y1,y2)-1]==0)
63 pg++;
64 break;
65 }
66 case 2 :{
67 for(l=1;l<=max(x1,x2)-min(x1,x2)+1;l++)
68 for(c=l;c<=max(y1,y2)-min(y1,y2)+1;c++)
69 if (t[l+min(x1,x2)-1][c+min(y1,y2)-1]==0)
70 pg++;
71 break;
72 }
73 case 3 :{
74 for(l=1;l<=max(x1,x2)-min(x1,x2)+1;l++)
75 for(c=1;c<=modul(x2-x1)+2-l;c++)
76 if (t[l+min(x1,x2)-1][c+min(y1,y2)-1]==0)
77 pg++;
78 break;
79 }
80 case 4 :{
81 for(l=1;l<=max(x1,x2)-min(x1,x2)+1;l++)
82 for(c=modul(x2-x1)+2-l;
83 c<=max(y1,y2)-min(y1,y2)+1;
84 c++)
85 if (t[l+min(x1,x2)-1][c+min(y1,y2)-1]==0)
86 pg++;
87 break;
88 }
89 }
90
91 if (pg==0)
92 ne++;
93 else
94 if (pg>(modul(x2-x1)+1)*(modul(x2-x1)+2)/4)
95 sol[++sol[0]]=i;
96 }
97
98 g<<ne<<"\n";
99 g<<sol[0]<<" ";
100 for(i=1;i<=sol[0];i++)
101 g<<sol[i]<<" ";
102
103 f.close();
104 g.close();
105 return 0;
106 }
89
90 return no;
91 }
92
93 //---------------------
94
95 void afis()
96 {
97 int i;
98 fout<<N1<<"\n"<<np<<" ";
99 for(i=1;i<=np;i++)
100 fout<<p[i]<<" ";
101 fout.close();
102 }
103
104 int main()
105 {
106 fin>>m>>n;
107
108 for(i=1;i<=m;i++)
109 for(j=1;j<=n;j++)
110 fin>>a[i][j];
111 fin>>k;
112
113 for(i=1;i<=k;i++)
114 fin>>L1[i]>>C1[i]>>L2[i]>>C2[i]>>tip[i];
115
116 fin.close();
117
118 np=0;
119 for(i=1;i<=k;i++)
120 {
121 t=triunghicu1(i);
122 //cout<<"Q "<<t<<"\n";
123
124 temp=abs(L1[i]-L2[i]);
125 temp=(temp+1)*(temp+2)/2;
126 //cout<<"*"<<L1[i]<<" "<<L2[i]<<" "<<temp<<"\n";
127
128 if(t==temp)
129 N1++;
130 if(t<temp/2.0)
131 {
132 np++;
133 p[np]=i;
134 }
135 }
136
137 afis();
138 return 0;
139 }
22 fscanf(f,"%d%d%d%d%d",&Elicop[i][1],&Elicop[i][2],
23 &Elicop[i][3],&Elicop[i][4],&Elicop[i][0]);
24 fclose(f);
25 }
26
27 int main()
28 {
29 f=fopen("elicop.in","r");
30 g=fopen("elicop.out","w");
31
32 nre=0;
33 citire();
34 int nr1;
35
36 for(int i=1;i<=k;i++)
37 {
38 if((Elicop[i][3]-Elicop[i][1])*(Elicop[i][4]-Elicop[i][2])>0 &&
39 Elicop[i][0]==-1)
40 Caz=1;
41 else
42 if((Elicop[i][3]-Elicop[i][1])*(Elicop[i][4]-Elicop[i][2])>0 &&
43 Elicop[i][0]==1)
44 Caz=2;
45 else
46 if((Elicop[i][3]-Elicop[i][1])*(Elicop[i][4]-Elicop[i][2])<0&&
47 Elicop[i][0]==-1)
48 Caz=3;
49 else
50 Caz=4;
51 nr1=0;
52
53 int J=max(Elicop[i][1],Elicop[i][3])-min(Elicop[i][1],Elicop[i][3])+1;
54 int Lx1=min(Elicop[i][1],Elicop[i][3]);
55 int Ly1=min(Elicop[i][2],Elicop[i][4]);
56 int Ly2=max(Elicop[i][2],Elicop[i][4]);
57
58 switch(Caz)
59 {
60 case 1: {
61 for(int j=1;j<=J;j++)
62 for(int l=1;l<=j;l++)
63 nr1+=!(Teren[j+Lx1-1][l+Ly1-1]);
64 break;
65 }
66 case 2: {
67 for(int j=1;j<=J;j++)
68 for(int l=j;l<=Ly2-Ly1+1;l++)
69 nr1+=!(Teren[j+Lx1-1][l+Ly1-1]);
70 break;
71 }
72 case 3: {
73 for(int j=1;j<=J;j++)
74 for(int l=(int)abs(Elicop[i][1]-Elicop[i][3])+2-j;
75 l<=Ly2-Ly1+1;
76 l++)
77 nr1+=!(Teren[j+Lx1-1][l+Ly1-1]);
78 break;
79 }
80 case 4: {
81 for(int j=1;j<=J;j++)
82 for(int l=1;
83 l<=(int)abs(Elicop[i][1]-Elicop[i][3])+2-j;
84 l++)
85 nr1+=!(Teren[j+Lx1-1][l+Ly1-1]);
86 break;
87 }
88 }
89
90 nre+=!nr1;
91 if(nr1 > (abs(Elicop[i][1]-Elicop[i][3])+1)*
92 (abs(Elicop[i][1]-Elicop[i][3])+2)/4)
93 E_Sol[++nr_umbra]=i;
94 }
95
96 fprintf(g,"%d\n%d ",nre,nr_umbra);
97
CAPITOLUL 9. OJI 2012 182
98 for(int i=1;i<=nr_umbra;i++)
99 fprintf(g,"%d ",E_Sol[i]);
100
101 fclose(g);
102 return 0;
103 }
9.2 roata
Problema 2 - roata 90 de puncte
Una dintre atracµiile celebrului parc de distracµii Prater din Viena este
Marea Roat Vienez . Din ea se poate admira priveli³tea întregii Viene.
Roata are n cabine, numerotate de la 1 la n în sens orar ³i dispuse simetric
pe circumferinµa roµii. îmbarcarea clienµilor se face în cabina în care roata
este tangent cu solul, iar rotirea începe cu cabina 1 aat în poziµia de
îmbarcare ³i se face în sens antiorar. Un client pl te³te pentru o rotire 1
EUR ³i poate cump ra un num r oarecare de rotiri. Figura 9.2: roata
Cei p clienµi care doresc utilizarea roµii trebuie s respecte urm toarea procedur : clientul cu
num rul de ordine i î³i cump r un bilet pe care sunt înscrise num rul s u de ordine ³i num rul
de rotiri ci, 1 & i & p, apoi se a³eaz la rând. Când în poziµia de îmbarcare este o cabin liber
sau se elibereaz o cabin , roata se opre³te ³i urc urm torul clientul. Un client coboar dup ce
se efectueaz num rul de rotiri înscris pe bilet.
Cerinµe
S se scrie un program care, cunoscând num rul n de cabine al roµii, num rul p de clienµi,
precum ³i num rul de rotiri cump rate de ecare client, ci , 1 & i & p, s calculeze:
a suma total încasat de administratorul roµii de la clienµi;
a ordinea în care coboar clienµii din roat ;
a num rul cabinei din care coboar ultimul client.
Date de intrare
Fi³ierul de intrare roata.in conµine pe primul rând num rul natural n, pe al doilea rând
num rul natural p iar pe al treilea rând numerele naturale ci , 1 & i & p, separate printr-un spaµiu,
cu semnicaµiile de mai sus.
Date de ie³ire
Fi³ierul de ie³ire roata.out va conµine pe prima linie suma total încasat , pe a doua linie
numerele de ordine ale clienµilor, în ordinea coborârii, separate printr-un spaµiu, iar pe a treia linie
num rul cabinei din care va coborî ultimul client.
Restricµii ³i preciz ri
a2 & n & 360
a1 & p & 100000
a 1 & ci & 100000
a pentru rezolvarea primei cerinµe se acord 20% din punctaj, iar pentru celelalte dou cerinµe
se acord câte 40% din punctaj ecare.
Exemple
roata.in roata.out Explicaµii
CAPITOLUL 9. OJI 2012 183
În cazul în care n ' p se încarc num rul de rotiri într-un vector ³i se determin suma total
încasat ca ind suma valorilor din vector, apoi se determin poziµia maximului dintre elementele
vectorului, care reprezint cabina din care va coborî ultimul client.
Pentru a determina ordinea în care coboar clienµii, se determin poziµia minimul dintre valorile
vectorului ³i se a³eaz , apoi se elimin acest minim ³i se reia operaµia anterioar .
În cazul în care n $ p se încarc într-un vector c i 1 & i & p num rul de rotiri ³i se iniµializeaz
un vector cu num rul de ordine al clienµilor o i 1 & i & n.
Se calculeaz ³i se a³eaz suma total încasat ca ind suma valorilor din vector.
Considerând c primii n clienµi sunt urcaµi în roat , pentru restul clienµilor cu numere de
ordine de la n 1 la p se procedeaz astfel :
- se determin poziµia minimului dintre primele n valori ale vectorului c i ³i se a³eaz num rul
de ordine al acestuia;
- se încarc un nou client în roat ad ugând pe poziµia minimului calculat precedent datele
noului client (num rul de rotiri ³i num rul s u de ordine);
De remarcat c dup ce a fost calculat poziµia unui minim, pentru a-l elimina, e sucient s
adun m pe poziµia acestuia num rul de rotiri ale urm torului client ³i s atribuim vectorului de
ordine num rul de ordine al clientului; aceast metod evit înc o parcurgerea a vectorului c i
în vederea prelucr rii informaµiilor clienµilor la o coborare, îns are dezavantajul c prin adun ri
repetate se poate ajunge la valori mari care trebuie gestionate cu tipuri de date corect alese.
- dup prelucrarea tuturor clienµilor cu numerele de ordine de la n 1 la p se intr pe secvenµa
descris în cazul n ' p.
Varianta 2
prof. Florentina Ungureanu - Colegiul Naµional de Informatic Piatra Neamµ
Vectorul roata reµine în poziµia i num rul de ordine al clientului din cabina i, respectiv p+1
dac aceast cabin este liber . (Iniµializat cu 1, 2, ..., n pentru n & p, respectiv 1, 2, ..., p, p 1, p
1, ...).
Vectorul ture conµine pentru început num rul de ture pl tite de ecare client, dar va actuali-
zat indicând la nal, pentru ecare client, num rul total de ture f cute de roat pân la momentul
coborârii acestuia.
Rezolvare:
1. Suma valorilor de pe a treia linie a ³ierului furnizeaz prima valoare cerut .
2. Determinarea ordinii coborârii:
Etapa I coboar -urc (n $ p):
a. Pentru ecare client i (i % n) r mas în a³teptare se determin num rul de ordine k al cabinei
care se elibereaz - cea al c rei client are num r minim de ture pân la coborâre ³i se a³eaz
num rul de ordine al clientului.
CAPITOLUL 9. OJI 2012 184
b. Clientul i urc în cabina k , iar num rul de ture pl tit de acesta se actualizeaz devenind
egal cu num rul total de ture f cute de roat pân când acest client va coborî.
Etapa II coboar :
a. Se determin num rul de ordine k al cabinei care se elibereaz - cea al c rei client are num r
minim de ture pân la coborâre.
b. Dac num rul de ture corespunz tor este mai mic decât inf (mai exist clienµi în roat ):
a se a³eaz num rul de ordine al clientului;
a se completeaz cabina k cu valoarea p 1 - (cabin goal );
a se reia pasul a.
c. Când nu mai sunt clienµi în roat se a³eaz num rul cabinei din care a coborât ultimul
client.
56 o[pozmin]=k;
57 }
58 else
59 n=p;
60
61 // determin numarul cabinei din care va cobora ultimul client
62 pozmax=1;
63 for(i=2;i<=n;i++)
64 if (c[i]>=c[pozmax])
65 pozmax=i;
66
67 for(k=1;k<=n;k++)
68 {
69 // determin clientul care urmeaza sa coboare
70 pozmin=1;
71 for(i=2;i<=n;i++)
72 if (c[i]<c[pozmin]) pozmin=i;
73
74 // afisez ordinea la coborare
75 g<<o[pozmin]<<" ";
76
77 c[pozmin]+=100001;
78 }
79
80 // afisez numarul cabinei din care va cobora ultimul client
81 g<<"\n"<<pozmax<<"\n";
82
83 f.close();
84 g.close();
85 return 0;
86 }
42 {
43 f>>a[i]; s+=a[i];
44 }
45
46 g<<s<<"\n";
47 if (p<=n)
48 {
49 for (i=0;i<p;i++)
50 {
51 c.cab=i+1;
52 c.cl=i+1;
53 c.rot=a[i];
54 m.insert(c);
55 }
56
57 it=m.begin();
58 c=*it;
59 g<<c.cl;
60 it++;
61 while (it!=m.end())
62 {
63 c=*it;
64 g<<" "<<c.cl;
65 it++;
66 }
67
68 g<<"\n";
69 g<<c.cab<<"\n";
70 }
71 else
72 {
73 for (i=0;i<n;i++)
74 {
75 c.cab=i+1;
76 c.cl=i+1;
77 c.rot=a[i];
78 m.insert(c);
79 }
80
81 int pr=0;
82 for (i=n;i<p;i++)
83 {
84 c=*m.begin();
85
86 if (pr!=0)
87 g<<" ";
88 else
89 pr=1;
90
91 g<<c.cl;
92
93 c.rot+=a[i];
94 c.cl=i+1;
95
96 m.erase(m.begin());
97 m.insert(c);
98 }
99
100 for (it=m.begin();it!=m.end();it++)
101 {
102 c=*it;
103 if (pr!=0)
104 g<<" ";
105 else
106 pr=1;
107 g<<" "<<c.cl;
108 }
109
110 g<<"\n"<<c.cab<<"\n";
111 }
112
113 g.close();
114 }
CAPITOLUL 9. OJI 2012 187
OJI 2011
10.1 vase
Problema 1 - vase 100 de puncte
Speciali³tii chimi³ti au reu³it crearea în laborator a unei game diversicate
de substanµe lichide nemiscibile (care nu se amestec între ele), de aceea³i
densitate ³i de culori diferite.
Acest rezultat a fost utilizat de c tre speciali³tii zicieni pentru studiul
principiului vaselor comunicante. Conform acestui principiu într-un sistem de
vase comunicante nivelul lichidului este acela³i, indiferent de forma vaselor.
Experimentele zicienilor se desf ³oar astfel: Figura 10.1:
Într-un sistem cu dou vase comunicante, gradat identic pe ecare ramur vase
cu 0, 1, 2, 3, ..., zicienii introduc un num r de n lichide, pe ramura din stânga sau pe ramura din
dreapta. Volumele introduse din ecare lichid, notate cu Vi (1 & i & n), sunt numere naturale
nenule pare astfel încât, la echilibru, orice lichid se va a³eza între dou gradaµii de aceea³i parte a
unei ramuri sau pe cele dou ramuri ale sistemului de vase comunicante. Lichidele sunt identicate
prin intermediul culorii acestora, culori numerotate cu 1, 2, 3, ..., n.
Introducerea lichidelor în sistemul cu dou vase comunicante se face în ordinea cresc toare a
numerelor culorilor, începând cu lichidul de culoare 1.
Scopul experimentului este de a determina gradaµia maxim
la care se ridic lichidele în sistemul cu dou vase comunicante,
precum ³i între ce gradaµii se g se³te un lichid de culoare x, dintre
cele introduse.
De exemplu, dac în sistemul cu dou vase comunicante se
introduc n 3 lichide în ordinea: V1 4 lichid de culoare 1
introdus prin ramura din dreapta (operaµie codicat 4D), V2
4 lichid de culoare 2 introdus prin ramura din stânga (operaµie
codicat 4S ) ³i V3 2 lichid de culoare 3 introdus prin ramura
din stânga (operaµie codicat 2S ) atunci gradaµia maxim la care
se ridic nivelul lichidelor în sistemul cu dou vase comunicante
este 5, iar lichidul de culoare x 2 se g se³te între gradaµiile: 3 pe
ramura din stânga 3S ³i 1 pe ramura din dreapta 1D, conform
gurii al turate.
Date de intrare
Prima linie a ³ierului de intrare vase.in conµine un singur num r natural nenul n, cu sem-
nicaµia de mai sus. Fiecare linie, din urm toarele n, conµine câte dou valori separate printr-un
spaµiu: un num r natural nenul par ³i o liter mare, S sau D, reprezentând volumul introdus
188
CAPITOLUL 10. OJI 2011 189
din lichidul de culoare i, respectiv ramura (S pentru ramura din stânga ³i D pentru ramura din
dreapta) prin care se face introducerea acestuia. Linia n 2 a ³ierului de intrare conµine un
singur num r nenul x ce reprezint culoarea lichidului c utat.
Date de ie³ire
Fi³ierul de ie³ire vase.out va conµine pe prima linie un num r natural nenul ce reprezint gra-
daµia maxim la care se ridic lichidele în sistemul de vase comunicante la echilibru. Urm toarele
dou linii vor conµine ecare câte dou valori separate printr-un spaµiu: un num r natural ³i o
liter mare (S sau D), reprezentând gradaµia ³i ramura între care se a³eaz lichidul c utat.
Restricµii ³i preciz ri
a 1 & x & n & 100000
a 2 & V i & 100000 pentru 1 & i & n
a sistemul de vase este gradat în acelea³i unit µi de m sur în care sunt exprimate volumele
de lichid;
a dac lichidul c utat, de culoare x, se a³eaz pe aceea³i ramur se va a³a întâi gradaµia
superioar ³i apoi cea inferioar ;
a dac lichidul c utat, de culoare x, se a³eaz pe ramuri diferite se va a³a întâi gradaµia de
pe ramura din stânga ³i apoi cea de pe ramura din dreapta;
a dac una dintre gradaµiile între care se situeaz lichidul c utat, de culoare x, este 0 atunci
se consider c aceast gradaµie se g se³te pe aceea³i ramur cu cealalt gradaµie;
a pentru rezolvarea primei cerinµe se acord 20% din punctaj, iar pentru a doua cerinµ 80%
din punctaj.
Exemple
vase.in vase.out Explicaµii
3 5 Se introduc 3 lichide în sistemul de dou vase comunicante:
4D 3S - primul cu volumul 4, se introduce prin dreapta ³i are culoarea 1;
4S 1D - al doilea cu volumul 4, se introduce prin stânga ³i are culoarea 2;
2S - al treilea cu volumul 2, se introduce prin stânga ³i are culoarea 3;
2 Se caut gradaµiile ce corespund lichidului de culoare 2.
Gradaµia maxim la care ajunge nivelul lichidului este 5.
Lichidul de culoare 2 se a³eaz între gradaµiile 3 pe ramura din stânga
³i 1 pe ramura din dreapta.
O prim abordare a problemei pleac de la ideea c înc de la citirea datelor despre lichidele
introduse în sistemul de vase comunicante se face separarea acelora introduse pe ramura stâng faµ
de cele introduse pe ramura dreapt în dou structuri de date identice (tablouri unidimensionale),
câte un tablou pentru volume ³i respectiv culoare. În acela³i timp se calculeaz suma tuturor
volumelor în vederea determin rii echilibrului ³i deci a gradaµiei maxime la care se ridic lichidele.
Pentru rezolvarea celei de-a doua cerinµe se face o c utare secvenµial în funcµie de culoare pe
cele dou ramuri, actualizând în permanenµ gradaµiile între care se g se³te lichidul curent. Se
analizeaz cu atenµie a³area în ³ierul de ie³ire a rezultatelor, în funcµie de preciz rile problemei
referitoare la modul de a³are (întâi gradaµia superioar ³i apoi cea inferioar , înt i ramura stâng
³i apoi cea dreapt , s.a.m.d.)
Aceast abordare necesit îns mai mult memorie deoarece se reµine ³i culoarea lichidului
introdus, întrucât s-a facut separarea pe ramuri a lichidelor.
O a doua abordare a problemei se poate face prin preluarea datelelor despre lichidele introduse
în ordinea culorilor (a citirii datelor), adic în dou tablouri unidimensionale (unul pentru volume
³i altul pentru ramur ) de la 1 la n.
CAPITOLUL 10. OJI 2011 190
Apoi se calculeaz nivelul la care se ajunge pân la lichidul c utat, se determin intervalul
iniµial al lichidului c utat ³i se actualizeaz intervalul ocupat de lichidul c utat, în funcµie de
direcµia curent pentru lichidele care au mai r mas de ad ugat.
Aceast soluµie necesit mai puµin memorie deoarece memorarea culorilor s-a f cut natural
prin indicele vectorilor utilizaµi.
76 fin=ss+s[es][1];
77 g<<fin<<" S"<<endl<<ss<<" S";
78 }
79 else
80 {
81 dif=-echi+ns;
82 ss-=dif;
83 fin=ss+s[es][1];
84 if (ss<0)
85 if(fin==0)
86 g<<-ss<<" D"<<endl<<0<<" D";
87 else
88 if(fin<0)
89 {
90 fin=-fin;
91 ss=-ss;
92 if(fin>ss)
93 g<<fin<<" D"<<endl<<ss<<" D";
94 else
95 g<<ss<<" D"<<endl<<fin<<" D";
96 }
97 else
98 g<<fin<<" S"<<endl<<-ss<<" D";
99 else
100 g<<fin<<" S"<<endl<<ss<<" S";
101 }
102 else
103 if(nd<echi)
104 {
105 dif=echi-nd;
106 sd+=dif;
107 fin=sd+d[ed][1];
108 g<<fin<<" D"<<endl<<sd<<" D";
109 }
110 else
111 {
112 dif=-echi+nd;
113 sd-=dif;
114 fin=sd+d[ed][1];
115 if (sd<0)
116 if(fin<=0)
117 g<<-sd<<" S"<<endl<<-fin<<" S";
118 else
119 g<<-sd<<" S"<<endl<<fin<<" D";
120 else
121 g<<fin<<" D"<<endl<<sd<<" D";
122 }
123
124 return 0;
125 }
99 l1=h2;
100 l1r=’D’;
101 }
102
103 if (h2-dr[vdr].cant<0)
104 {
105 l2=-(h2-dr[vdr].cant);
106 l2r=’S’;
107 }
108 else
109 {
110 l2=h2-dr[vdr].cant;
111 l2r=’D’;
112 }
113
114 gasit=1;
115 }
116
117 h2-=dr[vdr--].cant;
118 }
119
120 if (l1==0) l1r=l2r;
121 if (l2==0) l2r=l1r;
122
123 // scriu rezultatele in fisier
124 g<<mij<<"\n";
125 if (l1r==’D’&&l2r==’S’)
126 {
127 g<<l2<<" "<<l2r<<"\n";
128 g<<l1<<" "<<l1r<<"\n";
129 }
130 else
131 if (l1r==’S’&&l2r==’D’)
132 {
133 g<<l1<<" "<<l1r<<"\n";
134 g<<l2<<" "<<l2r<<"\n";
135 }
136 else
137 if (l1>l2)
138 {
139 g<<l1<<" "<<l1r<<"\n";
140 g<<l2<<" "<<l2r<<"\n";
141 }
142 else
143 {
144 g<<l2<<" "<<l2r<<"\n";
145 g<<l1<<" "<<l1r<<"\n";
146 }
147
148 f.close();
149 g.close();
150 return 0;
151 }
10.2 cri
Problema 2 - cri 100 de puncte
Furnicuµa ³i-a construit un depozit pentru gr unµe pe o suprafaµ de teren dreptunghiular
³i l-a compartimentat în N M camere identice, de form p tratic , dispuse câte M pe direcµia
Ox ³i câte N pe direcµia Oy . Din ecare camer se poate intra în orice camer învecinat cu ea
(camer care are un perete comun cu aceasta).
În ecare camer , identicat prin coordonatele sale, ca în
desenul al turat în care N 5 ³i M 4, furnica a depozitat
o cantitate de gr unµe. De exemplu, în camera de coordonate
I, J este depozitat cantitatea CIJ de gr unµe.
CAPITOLUL 10. OJI 2011 195
Exemple
CAPITOLUL 10. OJI 2011 196
Cazul I
Dac X ³i Y sunt ambele numere pare, atunci num rul de camere prin care va trece Cri este
egal cu X Y 1. Dac ar trece prin toate camerele, el nu ar mai putea s ias din zon f r s
treac de dou ori printr-o camer , lucru nepermis.
Fie Ai0j0 cea mai mic valoare din matricea A cu proprietatea c suma indicilor i0 j0 este
un num r impar. Atunci, Cri nu va trece prin camera de coordonate X i0 1, Y j0 1 iar
cantitatea total maxim de gr unµe pe care Cri poate s-o fure în acest caz este egal cu S Ai0j0 .
Cazul al II-lea
Dac X este impar sau Y este impar, sau ambele sunt impare, atunci num rul de camere prin
care va trece Cri este egal cu X Y . Astfel, cantitatea total maxim de gr unµe pe care Cri
poate s-o fure în acest caz este egal cu S .
Se procedeaz analog pentru celelalte trei zone, ³i apoi se alege zona pentru care se obµine
cantitatea total maxim de gr unµe prin traversarea unui num r minim de camere.
Implementarea soluµiei se poate realiza prin utilizarea unui tablou bidimensional ce memoreaz
cantit µile de gr unµe (sursele: cripas1.pas, cricpp1.cpp) sau se poate realiza f r tablouri (sursele:
cripas2.pas, cricpp2.cpp, cricpp3.cpp).
Complexitatea soluµiei propuse este O N M
Pentru exemplul dat în enunµul problemei, traseul pe care l-ar putea str bate Cri în ecare
zon este:
CAPITOLUL 10. OJI 2011 197
50 s4+=a;
51 if((i-i0+j-j0)%2!=0)
52 if(min4>a)
53 min4=a;
54 }
55 }
56
57 k1=i0*j0;
58 k2=i0*(m-j0+1);
59 k3=(n-i0+1)*j0;
60 k4=(n-i0+1)*(m-j0+1);
61
62 if((i0%2==0)&&(j0%2==0))
63 {
64 k1--;
65 s1=s1-min1;
66 }
67
68 if((i0%2==0)&&((m-j0+1)%2==0))
69 {
70 k2--;
71 s2=s2-min2;
72 }
73
74 if(((n-i0+1)%2==0)&&(j0%2==0))
75 {
76 k3--;
77 s3=s3-min3;
78 }
79
80 if(((n-i0+1)%2==0)&&((m-j0+1)%2==0))
81 {
82 k4--;
83 s4=s4-min4;
84 }
85
86 if(s2>s1)
87 {
88 ies=2;
89 k1=k2;s1=s2;
90 }
91 else
92 if((s2==s1)&&(k1>k2))
93 {
94 ies=2;
95 k1=k2;
96 }
97
98 if(s3>s1)
99 {
100 ies=3;
101 k1=k3;
102 s1=s3;
103 }
104 else
105 if((s3==s1)&&(k1>k3))
106 {
107 ies=3;
108 k1=k3;
109 }
110
111 if(s4>s1)
112 {
113 ies=4;
114 k1=k4;
115 s1=s4;
116 }
117 else
118 if((s4==s1)&&(k1>k4))
119 {
120 ies=4;
121 k1=k4;
122 }
123
124 g<<ies<<’ ’<<s1<<’ ’<<k1;
125
CAPITOLUL 10. OJI 2011 199
126 g.close();
127 return 0;
128 }
70 }
71
72 return s;
73 }
74
75 int zona3( int &nr)
76 {
77 int i,j,s=0,min=2000000000;
78
79 nb=0;
80 for(i=x; i<=n;i++)
81 {
82 nb++;
83 mb=0;
84 for(j=y;j>=1;j--)
85 {
86 mb++;
87 s=s+a[i][j];
88 if(((nb+mb)%2!=0)&&(a[i][j]<min))
89 min=a[i][j];
90 }
91 }
92
93 nr=nb*mb;
94 if(mb%2==0 && nb%2==0)
95 {
96 nr=nr-1;
97 s=s-min;
98 }
99
100 return s;
101 }
102
103 int zona4( int &nr)
104 {
105 int i,j,s=0,min=2000000000;nb=0;
106
107 for(i=x; i<=n;i++)
108 {
109 nb++;
110 mb=0;
111 for(j=y;j<=m;j++)
112 {
113 mb++;
114 s=s+a[i][j];
115 if(((nb+mb)%2!=0)&&(a[i][j]<min))
116 min=a[i][j];
117 }
118 }
119
120 nr=nb*mb;
121 if((mb%2==0) && (nb%2==0))
122 {
123 nr--;
124 s=s-min;
125 }
126
127 return s;
128 }
129
130 int main()
131 {
132 int nr,s,k=0,smax=0,ies;
133
134 citire();
135
136 smax=zona1(k);
137 ies=1;
138 s=zona2(nr);
139 if(s>smax)
140 {
141 smax=s;
142 k=nr;ies=2;
143 }
144 else
145 if(s==smax)
CAPITOLUL 10. OJI 2011 201
146 if(nr<k)
147 {
148 k=nr;
149 ies=2;
150 }
151
152 s=zona3(nr);
153 if(s>smax)
154 {
155 smax=s;
156 k=nr;ies=3;
157 }
158 else
159 if(s==smax)
160 if(nr<k)
161 {
162 k=nr;
163 ies=3;
164 }
165
166 s=zona4(nr);
167 if(s>smax)
168 {
169 smax=s;
170 k=nr;ies=4;
171 }
172 else
173 if(s==smax)
174 if(nr<k)
175 {
176 k=nr;
177 ies=4;
178 }
179
180 freopen("cri.out","w",stdout);
181 printf("%d %d %d",ies,smax,k);
182 return 0;
183 }
35 {
36 s3+=a;
37 if((i-i0+j0-j)%2!=0)
38 if(min3>a)
39 min3=a;
40 }
41
42 if((i>=i0)&&(j>=j0))
43 {
44 s4+=a;
45 if((i-i0+j-j0)%2!=0)
46 if(min4>a)
47 min4=a;
48 }
49 }
50
51 k1=i0*j0;
52 k2=i0*(m-j0+1);
53 k3=(n-i0+1)*j0;
54 k4=(n-i0+1)*(m-j0+1);
55
56 if((i0%2==0)&&(j0%2==0))
57 {
58 k1--;
59 s1=s1-min1;
60 }
61
62 if((i0%2==0)&&((m-j0+1)%2==0))
63 {
64 k2--;
65 s2=s2-min2;
66 }
67
68 if(((n-i0+1)%2==0)&&(j0%2==0))
69 {
70 k3--;
71 s3=s3-min3;
72 }
73
74 if(((n-i0+1)%2==0)&&((m-j0+1)%2==0))
75 {
76 k4--;
77 s4=s4-min4;
78 }
79
80 if(s2>s1)
81 {
82 ies=2;
83 k1=k2;
84 s1=s2;
85 }
86 else
87 if((s2==s1)&&(k1>k2))
88 {
89 ies=2;
90 k1=k2;
91 }
92
93 if(s3>s1)
94 {
95 ies=3;
96 k1=k3;
97 s1=s3;
98 }
99 else
100 if((s3==s1)&&(k1>k3))
101 {
102 ies=3;
103 k1=k3;
104 }
105
106 if(s4>s1)
107 {
108 ies=4;
109 k1=k4;
110 s1=s4;
CAPITOLUL 10. OJI 2011 203
111 }
112 else
113 if((s4==s1)&&(k1>k4))
114 {
115 ies=4;
116 k1=k4;
117 }
118
119 printf("%d %d %d",ies,s1,k1);
120
121 return 0;
122 }
61
62 if(i>=x && j<=y)
63 {
64 s3 += q;kk3++;
65 if( (i!=x || j!=y) && (i!=n || j!=1) &&
66 (i+j)%2 != (n+1)%2 && q<m3 )
67 m3 = q;
68 }
69
70 if(i>=x && j>= y)
71 {
72 s4 += q;kk4++;
73 if((i!=x || j!=y) && (i!=n || j!=m) &&
74 (i+j)%2 != (n+m)%2 && q<m4 )
75 m4 = q;
76 }
77 }
78
79 int k1=x*y, k2=x*(m-y+1), k3=(n-x+1)*y, k4=(n-x+1)*(m-y+1);
80
81 if(x%2==0 && y%2==0)
82 s1-=m1, k1--;
83
84 if(x%2==0 && (m-y+1)%2==0)
85 s2-=m2, k2--;
86
87 if((n-x+1)%2==0 && y%2==0)
88 s3-=m3, k3--;
89
90 if((n-x+1)%2==0 && (m-y+1)%2==0)
91 s4-=m4, k4--;
92
93 #ifdef DEBUG
94 printf("%d %d %d %d\n",kk1,kk2,kk3,kk4);
95 printf(" zona suma min k\n");
96 printf("%d %d %d %d\n",1,s1,m1,k1);
97 printf("%d %d %d %d\n",2,s2,m2,k2);
98 printf("%d %d %d %d\n",3,s3,m3,k3);
99 printf("%d %d %d %d\n",4,s4,m4,k4);
100 #endif
101
102 int z=1,k=k1;
103 int s=s1;
104
105 if(s2>s)
106 z=2,s=s2,k=k2;
107 else
108 if (s2==s && k2<k)
109 z=2,s=s2,k=k2;
110
111 if(s3>s)
112 z=3,s=s3,k=k3;
113 else
114 if (s3==s && k3<k)
115 z=3,s=s3,k=k3;
116
117 if(s4>s)
118 z=4,s=s4,k=k4;
119 else
120 if (s4==s && k4<k)
121 z=4,s=s4,k=k4;
122
123 #ifndef STDIO
124 ofstream fout("cri.out");
125 fout<<z<<" "<<s<<" "<<k<<endl;
126 #else
127 freopen("cri.out","w",stdout);
128 printf("%d %d %d\n",z,s,k);
129 #endif
130
131 return 0;
132 }
CAPITOLUL 10. OJI 2011 205
OJI 2010
11.1 livada
Problema 1 - livada 100 de puncte
Norocosul Gigel tocmai a primit în dar de la bunicul s u, Nelu, o imens plantaµie de pomi
fructiferi. Fost profesor de geometrie, Nelu a plantat în mod riguros pomii fructiferi pe m rânduri
paralele, iar pe ecare rând a plantat exact câte n pomi fructiferi. Îns , din motive mai mult sau
mai puµin obiective, domnul Nelu nu a plantat pe ecare rând toµi pomii de acela³i soi, ci din
mai multe soiuri diferite. Soiurile de pomi plantaµi în livad sunt codicate cu numere naturale
cuprinse între 1 ³i p.
Cuprins de febra rigurozit µii matematice ³i de cea a statisticii, Gigel a denit noµiunea de soi
majoritar astfel: dac pe un rând k format din n pomi fructiferi avem cel puµin n©2 1 pomi de
acela³i soi x, atunci spunem c soiul x este soi majoritar pe rândul k (prin y se înµelege partea
întreag a num rului real y ).
Cerinµe
Cunoscând numerele m, n ³i p, precum ³i soiul ec rui pom de pe ecare rând al plantaµiei,
ajutaµi-l pe Gigel s determine:
1. pe câte rânduri din livad exist un soi majoritar;
2. care este cel mai mare num r de pomi de acela³i soi plantaµi în poziµii consecutive pe un
rând.
Date de intrare
Fi³ierul de intrare livada.in conµine pe prima linie trei numere naturale m, n ³i p cu semni-
caµia din enunµ, iar pe ecare dintre urm toarele m linii se g sesc câte n numere, desp rµite prin
câte un spaµiu, reprezentând soiurile pomilor de pe rândul respectiv.
Date de ie³ire
Fi³ierul de ie³ire livada.out va conµine dou linii:
1. pe prima linie se va scrie un num r natural reprezentând num rul de rânduri din livad pe
care exist un soi majoritar;
2. pe a doua linie se va scrie un num r natural reprezentând cel mai mare numar de pomi de
acelasi soi plantaµi în poziµii consecutive pe un rând.
Restricµii ³i preciz ri
a 1 & m & 100
a 1 & n & 700.000
a 1 & m n & 700.000
a 1 & p & 998.560.000
a Pe ecare rând diferenµa dintre valoarea maxim ³i cea minim este cel mult 250.000.
a Dac doar valoarea de pe prima linie este corect , se acord 40% din punctaj. Dac doar
valoarea de pe a doua linie este corect , se acord 60% din punctaj. Dac ambele valori sunt
corecte, se acord 100% din punctajul testului respectiv.
206
CAPITOLUL 11. OJI 2010 207
Exemple
livada.in livada.out Explicaµii
4 7 9 2 Plantaµia este format din m=4 rânduri, iar pe ecare rând
2 1 23 8 2 2 3 avem câte n=7 pomi.
4 7 24 9 7 4 Pentru ca un soi sa e majoritar pe un rând trebuie ca pe acel
5 5 25 5 5 7 rând s existe cel puµin [7/2]+1 = 4 pomi din soiul respectiv.
2 3 23 2 3 1 Exist soiuri majoritare pe dou rânduri: primul ³i al treilea.
Pe randul al treilea exista 3 poziµii consecutive în care se a
pomi din acela³i soi (soiul 5).
71
72 return 0;
73 }
70 }
71
72 fprintf(fout,"%d\n%d",rsm,max);
73
74 fclose(fin);
75 fclose(fout);
76
77 return 0;
78 }
11.2 numar
Problema 2 - numar 100 de
puncte
Se d un num r raµional strict pozitiv q , sub form de fracµie zecimal .
Cerinµe
S se determine dou numere naturale a ³i b astfel încât q a
b
iar modulul diferenµei dintre a
³i b s e minim.
Date de intrare
Fi³ierul numar.in conµine
- pe prima linie dou valori naturale ni ³i nz . ni reprezint num rul de cifre care formeaz
partea întreag a lui q iar nz reprezint num rul de cifre care formeaz partea fracµionara a lui q .
- pe a doua linie, ni cifre care reprezint partea întreag a lui q . Între dou cifre se a câte
un caracter spaµiu.
- pe a treia linie, nz cifre care reprezint partea zecimal a lui q . Între dou cifre se a câte
un caracter spaµiu.
Date de ie³ire
³ierul numar.out va conµine:
- pe prima linie un num r natural n1 care reprezint num rul de cifre din care este alc tuit
num rul a;
- pe a doua linie, cifrele num rului a, f r spaµiu între ele.
- pe a treia linie un num r natural n2 care reprezint num rul de cifre din care este alc tuit
num rul b;
- pe a patra linie, cifrele numarului b, f r spaµiu între ele.
Restricµii ³i preciz ri
- 1 & n1, n2 $ 2000
- 1 & n1 n2 & 2000
- Cifrele din care este alc tuit q sunt cele din sistemul zecimal.
- Pentru 20% dintre teste, n1 n2 & 9; pentru alte 15% dintre teste, 10 & n1 n2 & 16
Exemple
numar.in numar.out Explicaµii
13 1 q 0.375 83
0 3 Exist ³i alte perechi de valori naturale x, y astfel încât
375 1 x
y
0.375, dar pentru oricare alt pereche, ¶x y ¶ % ¶3 8¶
8 (¶...¶ reprezint modulul)
37 7
012 1234567 q 12.34567 1234567
100000
3456700 6
100000
CAPITOLUL 11. OJI 2010 211
Se ia iniµial
- a = num rul format din cifrele lui q din care se scoate punctual zecimal
- b = 1 urmat de atâtea cifre de 0 câte cifre are partea zecimal (fracµionar ).
Evident, a ³i b trebuie implementate ca numere mari - ecare cifr ca element al unui vector.
Apoi simplic m fracµia format din a ³i b.
Matematic, simplicarea ar trebui facut cu cmmmdc-ul dintre a ³i b, dar nu are rost s
calcul m acest num r deoarece a ³i b sunt numere mari ³i acest calcul s-ar face prin sc deri
repetate sau implementarea imparµirii pe numere mari, ceea ce e complicat ³i nu garanteaz
încadrarea în timp.
De fapt, cele dou numere a ³i b nu se pot simplica decât cu o putere a lui 2 sau a lui 5,
având în vedere c b este o putere a lui 10 - a³a c tot ce trebuie s facem este s implement m
împarµirea unui num r mare la un num r de o singur cifr .
Pentru punctaje parµiale, putem lucra cu variabile numerice:
- dac folosim tipuri pe 16 biµi (integer în Pascal) obµinem 10 de puncte
- dac folosim tipuri pe 36 biµi (longint în Pascal respective long sau int în C/C++) obµinem
20 de puncte
- dac folosim tipuri pe 64 biµi (int64 în Pascal respective long long în C/C++) obµinem 35
de puncte
Mai putem prinde 2 teste în care partea întreag ³i/sau partea zecimal au mai mult de 16
cifre, îns ele conµin multe 0-uri redundante, pe care trebuie s nu le includem în numerele pe care
le construim.
Putem lucra ³i cu tipuri reale (dar care s ne permit precizii cat mai bune: extended în Pascal
sau long double în C) conform unuia dintre urm torii algoritmi, ceea ce ne permite obµinerea unor
punctaje parµiale (de exemplu al doilea dintre algoritmii descri³i mai jos prind 6 teste)
citim valoarea q într-o variabil real
a q 10
nz
b 10
nz
c cmmdc a, b
a a©c, b b©c
sau
citim valoarea q într-o variabil real
pentru i 1, valoare arbitrar foarte mare
dac q i este valoare natural atunci
a qi
b i
break
12
13 void initializare(vector v)
14 {
15 v[0] = 0;
16 }
17
18 void atribuire(vector v, unsigned long x)
19 {
20 v[0] = 0;
21 while (x)
22 {
23 ++v[0];
24 v[v[0]] = x % 10;
25 x /= 10;
26 }
27 }
28
29 void inmultire(vector v, unsigned long x) /* v <- v*x */
30 {
31 unsigned long i,t=0;
32
33 for (i=1;i<=v[0];i++)
34 {
35 v[i]=v[i]*x+t;
36 t=v[i]/10;
37 v[i]=v[i]%10;
38 }
39
40 while (t) /* Cat timp exista transport */
41 {
42 v[++v[0]]=t%10;
43 t/=10;
44 }
45 }
46
47 void adunare(vector a, vector b) /* a <- a+b */
48 {
49 unsigned long i,t=0;
50
51 if (b[0]>a[0])
52 {
53 for (i=a[0]+1;i<=b[0];)
54 a[i++]=0;
55
56 a[0]=b[0];
57 }
58 else
59 for (i=b[0]+1;i<=a[0];)
60 b[i++]=0;
61
62 for (i=1;i<=a[0];i++)
63 {
64 a[i]+=b[i]+t;
65 t=a[i]/10;
66 a[i]%=10;
67 }
68
69 if (t)
70 a[++a[0]]=t;
71 }
72
73
74 void scriere(vector v)
75 {
76 unsigned long i;
77
78 for(i=v[0];i>=1;i--)
79 g<<v[i];
80
81 g<<endl;
82 }
83
84 void shl(vector a, int p) /* H <- H*10ACount */
85 {
86 long i;
87
CAPITOLUL 11. OJI 2010 213
164 shl(s,m);
165 if (m==0)
166 {
167 g<<n<<"\n";
168 scriere(v);
169
170 g<<1<<"\n";
171 scriere(s);
172
173 return 0;
174 }
175
176 for(i=0;i<=1;i++)
177 while (mod(v,prim[i])==0&&mod(s,prim[i])==0)
178 {
179 divide(v,prim[i]);
180 divide(s,prim[i]);
181 }
182
183 g<<v[0]<<"\n";
184 scriere(v);
185 g<<s[0]<<"\n";
186 scriere(s);
187
188 f.close();
189 g.close();
190
191 return 0;
192 }
OJI 2009
12.1 expresie
Problema 1 - expresie 100 de puncte
Costel are de rezolvat o tem grea la matematic : având la dispoziµie N numere naturale nenule
trebuie s a³eze între acestea 2 operaµii de înmulµire ³i N 3 operaµii de adunare, astfel încât
rezultatul calculelor s e cel mai mare posibil. Nu este permis modicarea ordinii numerelor
date.
De exemplu, dac N 5 ³i numerele sunt 4, 7, 1, 5, 3, operaµiile pot a³ezate 4 7 1 5 3,
4 7 1 5 3 e.t.c
Cerinµe
Scrieµi un program care s a³eze dou operaµii de înmulµire ³i N 3 operaµii de adunare între
cele N valori date astfel încât valoarea expresiei obµinute s e maxim .
Date de intrare
Fi³ierul de intrare expresie.in are urm toarea structur :
Pe prima linie se a un num r natural N , reprezentând num rul elementelor date.
Pe urm toarele linii se a cele N numere naturale date, ecare pe câte o linie.
Date de ie³ire
Fi³ierul de ie³ire expresie.out va conµine, pe prima linie, valoarea maxim obµinut prin
evaluarea expresiei.
Restricµii ³i preciz ri
4 & N & 1000
Numerele date sunt numere naturale între 1 ³i 10000
Exemple
expresie.in expresie.out Explicaµii
5 44 Valoarea maxim se obµine prin a³ezarea operaµiilor sub forma:
4 47153
7
1
5
3
215
CAPITOLUL 12. OJI 2009 216
Memor m cele N numere naturale date în tabloul unidimensional T . Calcul m suma celor N
valori, deoarece presupunem c , iniµial, avem în expresia noastr doar operaµii de adunare.
Exist dou cazuri posibile pentru a introduce dou operaµii de înmulµire în expresie:
Cazul 1. Cele dou înmulµiri sunt consecutive. Obµinem valoarea maxim a expresiei în
variabila suma1, luând pe rând toate tripletele de numere consecutive ti, ti 1, ti 2 ³i
alegând tripletul pentru care suma ti ti 1 ti 2 ti ti 1 ti 2 este maxim .
Cazul 2. Cele dou operaµii de înmulµire nu sunt a³ezate consecutiv. Obµinem valoarea maxim
a expresiei în variabila suma1, luând pe rand toate perechile (ti, ti 1) ³i (tj , tj 1) ³i
alegând combinaµia pentru care suma ti ti 1 tj tj 1 ti ti 1 tj tj 1
este maxim .
Deoarece numerele date sunt între 1 ³i 10000, valoarea expresiei poate dep ³i tipul de date
longint (long int).
Pentru exemplul din enunt, avem:
1 2 3 4 5
T: 4 7 1 5 3
Suma iniµial este suma=20.
Cazul 1. Avem expresiile posibile:
4*7*1+5+3 = 36
4+7*1*5+3 = 42
4+7+1*5*3 = 26
deci valoarea maxim de pân acum este 42
Cazul 2 Avem expresiile posibile:
4*7+1*5+3 = 28+5+3 = 36
4*7+1+5*3 = 28+1+15= 44
4+7*1+5*3 = 4+7+15=26
deci valoarea maxim este 44
12.2 placare
Problema 2 - placare 100 de puncte
O suprafaµ dreptunghiular de în lµime N ³i l µime M unit µi trebuie acoperit perfect (pla-
cat ) prin utilizarea unor pl ci de form dreptunghiular de dimensiune 1 P sau P 1, unde P
este un num r natural nenul. Suprafaµa dat poate privit ca un caroiaj cu N M p tr µele
egale cu unitatea.
O placare corect a suprafeµei iniµiale se memoreaz într-un ³ier text folosind urm toarele
convenµii de codicare:
a pe prima linie se precizeaz dimensiunile N ³i M ale suprafeµei;
a o plac dreptunghiular de laµime P este codicat prin num rul natural P , iar o plac de
înalµime P se codic prin num rul întreg P ;
a convenim ca placa având ambele dimensiuni egale cu unitatea s se codice cu valoarea 1;
a pe ecare din cele N linii ale codic rii se a câte un ³ir de valori întregi reprezentând, în
ordine de la stânga la dreapta, codurile pl cilor care se g sesc amplasate începând de la respectiva
linie;
a codul P strict mai mare ca 1 al unei placi orizontale apare o singur dat pe linia corespun-
z toare pe care se a placa, iar codul P al unei placi verticale va apare o singur dat ³i anume
pe prima linie de la care placa respectiv este amplasat în jos pe o anumita coloan a suprafeµei;
a Dac pe o anumit linie a suprafeµei nu exist astfel de coduri de pl ci, atunci pe respectiva
linie din ³ier este o singur valoare de 0.
CAPITOLUL 12. OJI 2009 217
Folosind codicarea unei plac ri a suprafeµei iniµiale, se poate determina imaginea acestei
plac ri sub forma unui tablou bidimensional A, cu N linii ³i M coloane, unde Aij = valoarea
absolut a codului pl cii care se suprapune peste p tr µelul de pe linia i ³i coloana j.
Cerinµe
Cunoscând codicarea unei plac ri corecte a suprafeµei date s se obµin imaginea acestei
plac ri (matricea de valori corespunz toare codic rii suprafeµei).
Date de intrare
Fi³ierul de intrare placare.in are urm toarea structur :
- pe prima linie valorile naturale N M , separate printr-un spaµiu, unde N este în lµimea
suprafeµei, M este l µimea suprafeµei.
- pe ecare din urm toarele N linii se a un ³ir de valori întregi, separate prin câte un spaµiu,
reprezentând codicarea respectivei linii a plac rii.
Date de ie³ire
În ³ierul de ie³ire placare.out se va tip ri tabloul bidimensional ce reprezint imaginea
plac rii, compus din N linii, pe ecare dintre ele aându-se M valori naturale separate prin câte
un spaµiu, cu semnicaµia din enunµ.
Restricµii ³i preciz ri
- 1 & N, M & 100 pentru 80% din teste;
- 100 $ N, M & 300 pentru 20% din teste
- dimensiunea P sau P a unei pl ci este aleas astfel încât acoperirea obµinut s nu dep -
³easc în lµimea N sau l µimea M a suprafeµei.
- datele din ³ierul de intrare sunt corecte în sensul c reprezint codicarea unei acoperiri a
zonei dreptunghiulare de dimensiuni N ³i M .
Exemple
placare.in placare.out Explicaµii
44 4 1 1 1 Valoarea 4 codic o plac de în lµime 4 ³i laµime 1 plasat
-4 1 1 1 4 1 2 2 începând din p tratul de coordonate 1, 1 ³i pîn în p tratul
12 4 2 2 1 de coordonate 4, 1
21 4 3 3 3 Valoarea 3 de pe ultima linie a codic rii desemneaz o plac de
3 l µime 3 ³i în lµime 1, plasat orizontal, începând din p tr µelul
de coordonate 4, 2.
32 32
-3 -2 32
0 31
1
Se citesc datele de intrare folosind un vector A, care va reµine, succesiv, câte o linie a ³ierului
de intrare.
Construim soluµia printr-o parcurgere a datelor de intrare.
Folosim ca memorie auxiliara o matrice REST U RI cu dou linii ³i 300 coloane.
Pentru ecare poziµie J , REST U RI 1, J va memora valoarea asociat unei pl ci întâlnite
pe una din liniile anterioare, iar REST U RI 2, J va memora num rul r mas de linii pe care se
a³eaz placa respectiv .
Pe o linie oarecare I , a codic rii, sunt posibile trei situaµii:
- dac exist plac vertical pe coloana curent , ce ocup spaµiu ³i pe linia I , se va memora
valoarea corespunz toare acelei pl ci sc zându-se cu o unitate valoarea de pe linia 2 a matricei
CAPITOLUL 12. OJI 2009 218
auxiliare REST U RI .
- dac nu, se cite³te urm toarea valoare din vectorul A de pe coloana I ³i se a³eaz placa
gasit pe linia I , orizontal dac valoarea este pozitiv sau vertical dac valoarea este negativ ; în
acela³i timp se actualizeaz matricea REST U RI , în cazul în care placa este asezat pe vertical ;
- în al treilea caz, singura valoare de pe linia curent este 0, aceasta însemnând c pe aceast
linie a plac rii exist doar placi verticale plasate pe liniile anterioare; pentru aceasta e sucient s
plas m valorile memorate în matricea REST U RI , actualizând REST U RI 2, J .
Procedeul se repet pentru ecare linie a codic rii.
Utilizarea unor tablouri bidimensionale pentru construirea imaginii plac rii determin obµine-
rea a 80 de puncte, datorit dimensiunilor prea mari ale acestora.
Observaµie: Algorimul nu necesit tehnici de programare ³i este insprirat din deniµia tabelelor
HT M L, în care o celul se poate extinde pe mai multe linii sau coloane. Programul simuleaz
modul in care tabelul este interpretat de browser ³i asat pe ecran ca pagin web.
OJI 2008
13.1 Concurs
Problema 1 - concurs 100 de puncte
La Olimpiada Naµional de Informatic particip elevi din mai multe judeµe, ecare judeµ
ind identicat în mod unic printr-un num r natural. Elevii din ecare judeµ au asociat câte
un num r natural care permite identicarea în mod unic a elevului în cadrul judeµului. Astfel,
orice participant la olimpiada poate identicat prin dou numere: identicatorul judeµului ³i
identicatorul elevului în cadrul judeµului.
Pentru a repartiza elevii la calculatoare, organizatorii au nevoie de o list care s respecte
urm toarele condiµii:
- lista conµine toµi elevii participanµi la olimpiad ;
- oricare doi elevi consecutivi în list sunt din judeµe diferite;
- elevii din orice judeµ apar în list în ordinea cresc toare a numerelor de identicare.
Cerinµe
Scrieµi un program care s genereze lista necesar organizatorilor.
Date de intrare
Fi³ierul de intrare concurs.in conµine pe prima linie un num r natural P reprezentând num -
rul total de participanµi la ONI. Pe urm toarele P linii este descris lista participanµilor, câte un
participant pe o linie. Pentru ecare participant sunt scrise dou numere naturale separate prin
spaµiu J E , unde J reprezint identicatorul judeµului, iar E reprezint identicatorul elevului în
cadrul judeµului.
Date de ie³ire
Fi³ierul de ie³ire concurs.out va conµine pe prima linie un num r natural N J , reprezentând
num rul de judeµe din care exist participanµi la olimpiad . Pe cea de a doua linie sunt scrise
N J numere naturale nenule separate prin câte un spaµiu reprezentând (în ordinea cresc toare a
numerelor de identicare a judeµelor) num rul de participanµi din ecare judeµ. Pe urm toarele P
linii este descris lista necesar organizatorilor, câte un elev pe o linie. Pentru ecare elev este scris
mai întâi identicatorul judeµului din care face parte, urmat de un spaµiu, apoi de identicatorul
elevului în cadrul judeµului.
Restricµii ³i preciz ri
Identicatorii judeµelor sunt numere naturale cuprinse între 1 ³i 50.
Identicatorii elevilor în cadrul judeµelor sunt numere naturale cuprinse între 1 ³i 1000.
Num rul total de elevi participanµi la olimpiad nu dep ³e³te 500.
Pentru datele de test exist întotdeauna soluµie, nu neap rat unic .
Pentru determinarea corect a num rului de judeµe se acord 20% din punctaj. Pentru deter-
minarea corect a num rului de judeµe, precum ³i a num rului de participanµi din ecare judeµ
se acord 30% din punctaj. Punctajul se acord integral pentru rezolvarea tuturor celor 3 cerinµe
(num r de judeµe, num r de participanµi din ecare judeµ ³i lista necesar organizatorilor).
219
CAPITOLUL 13. OJI 2008 220
Exemple
concurs.in concurs.out
7 3
1 3 4 12
2 4 1 2
1 2 5 2
5 2 1 3
5 3 5 3
1 6 1 6
1 9 2 4
1 9
Vom utiliza o matrice A cu maxim 50 de linii. Pe linia i vor memorate numerele de identicare
ale elevilor din judeµul i.
Mai exact:
Ai0 reprezint num rul de elevi din judeµul i;
Ai1, Ai2, ..., AiAi0 sunt elevii din judeµul i.
Pentru a num ra judeµele din care exist participanµi este sucient s parcurgem coloana 0 a
matricei ³i s num r m liniile i pentru care Ai0 j 0.
Pentru a rezolva cerinµa 2, vom parcurge din nou coloana 0 (începând de la 1) ³i vom a³a
valorile nenule Ai0.
Pentru a construi lista necesar organizatorilor:
1. vom sorta cresc tor elevii din ecare judeµ;
2. vom repartiza elevii astfel:
- la ecare pas determin m dou judeµe cu num r maxim de participanµi la ONI
- plasez în list câte un elev din ecare dintre cele dou judeµe (astfel judeµele vor alterna).
Pentru a p stra ordinea cresc toare a elevilor în cadrul judeµelor vom reµine pentru ecare
judeµ poziµia elevului curent (cel care urmeaz a plasat în list ).
Când plas m în list un elev dintr-un judeµ avem grij s decrement m num rul de elevi
disponibili din judeµul respectiv (pentru a putea calcula la ecare pas care sunt judeµele cu num r
maxim de elevi disponibili).
Când num rul total de elevi este impar trebuie s m atenµi la ultimul pas, indc nu trebuie
s mai select m doi elevi, ci unul singur.
21 if (a[i][0])
22 nrJ++;
23
24 fout=fopen("concurs.out","w");
25 fprintf(fout,"%d\n",nrJ);
26
27 for (i=1; i<=JMax; i++)
28 if (a[i][0])
29 fprintf(fout,"%d ",a[i][0]);
30 fprintf(fout,"\n");
31
32 for (i=1; i<=JMax; i++)
33 if (a[i][0])
34 sortare(i);
35
36 for (j=1; j<=JMax; j++) inc[j]=1;
37
38 for (k=1; k<=P; i++)
39 {
40 //determina max1 si max2
41 max1=max2=0;
42 pozmax1=pozmax2=0;
43
44 for (j=1; j<=JMax; j++)
45 if (a[j][0]>max1)
46 {
47 max2=max1;
48 pozmax2=pozmax1;
49 max1=a[j][0];
50 pozmax1=j;
51 }
52 else
53 if (a[j][0]>max2)
54 {
55 max2=a[j][0];
56 pozmax2=j;
57 }
58
59 //distribuie primii 2 elevi in lista
60 lista[k][0]=pozmax1;
61 lista[k][1]=a[pozmax1][inc[pozmax1]];
62 if (max2)
63 {
64 lista[k+1][0]=pozmax2;
65 lista[k+1][1]=a[pozmax2][inc[pozmax2]];
66 }
67 k+=2;
68
69 //elimina elevii repartizati
70 a[pozmax1][0]--;
71 a[pozmax2][0]--;
72 inc[pozmax1]++;
73 inc[pozmax2]++;
74 }
75
76 for (i=1; i<=P; i++)
77 fprintf(fout,"%d %d\n", lista[i][0], lista[i][1]);
78
79 fclose(fout);
80 return 0;
81 }
82
83 void read()
84 {
85 int i, el, jud;
86 FILE * fin = fopen("concurs.in", "rt");
87
88 fscanf(fin, "%d", &P);
89 for (i=1; i<=P; i++)
90 {
91 fscanf (fin,"%d %d",&jud, &el);
92 a[jud][0]++;
93 a[jud][a[jud][0]]=el;
94 }
95
96 fclose(fin);
CAPITOLUL 13. OJI 2008 222
97 }
98
99 void sortare (int i)
100 {
101 int ok, j, aux;
102
103 do
104 {
105 ok=1;
106 for (j=1; j<a[i][0]; j++)
107 if (a[i][j]>a[i][j+1])
108 {
109 aux=a[i][j];
110 a[i][j]=a[i][j+1];
111 a[i][j+1]=aux;
112 ok=0;
113 }
114 } while (!ok);
115 }
13.2 Pluricex
Problema 2 - Pluricex 100 de
puncte
Anul acesta se organizeaz prima ediµie a Olimpiadei Pluridisciplinare pentru Centrele de
Excelenµ , PluriCEX. Fiecare Centru de Excelenµ din µar va trimite la concurs o echip format
din k membri (toµi participanµi la Centrul de Excelenµ ). Echipa va trebui s rezolve probleme
interdisciplinare, disciplinele vizate ind cele de la Centrul de Excelenµ (D discipline, pe care le
vom considera numerotate de la 1 la D).
Directorul CEX Ia³i a f cut o list cu primii n cei mai buni elevi de la CEX, apoi a numerotat
elevii de la 1 la n, în ordinea apariµiei lor în list . Pentru ecare elev, directorul a notat disciplinele
la care el particip la CEX.
Cerinµe
Scrieµi un program care s determine toate echipele ce pot formate din k dintre cei n elevi
de pe lista directorului, cu condiµia ca pentru ecare disciplin s existe în echip cel puµin un
membru care s studieze la CEX disciplina respectiv .
Date de intrare
Fi³ierul de intrare pluricex.in conµine pe prima linie trei numere naturale n k D (cu semni-
caµia din enunµ). Urmeaz n linii care descriu particip rile la CEX ale celor n elevi de pe lista
directorului. Mai exact, pe linia i 1 este descris participarea elevului i astfel:
nr d1 d2 ... dnr
Primul num r de pe linie (nr) indic num rul de discipline la care particip elevul i. Urm -
toarele nr numere reprezint disciplinele la care particip elevul i. Numerele scrise pe aceea³i linie
sunt separate prin spaµiu.
Date de ie³ire
Fi³ierul de ie³ire pluricex.out va conµine toate echipele ce se pot forma respectând condiµiile
din enunµ, câte o echip pe o linie. Membrii unei echipe vor scri³i în ordine cresc toare, separaµi
prin câte un spaµiu. Echipele vor scrise în ordine lexicograc .
Restricµii ³i preciz ri
a 0 $ n & 22
a 0$k&8
a 0 $ D & 10
a Pentru datele de test problema admite întotdeauna soluµie, num rul de soluµii ind $ 20000.
CAPITOLUL 13. OJI 2008 223
Exemple
pluricex.in pluricex.out
6 3 5 234
1 2 345
2 1 4
3 2 43
1 5
2 3 1
1 3
Vom genera în ordine lexicograc toate submulµimile de k elemente ale mulµimii r1, 2, ..., nx
(combin ri de n luate câte k ) printr-un algoritm de tip succesor.
Pentru ecare submulµime vom verica dac pentru ecare disciplin exist cel puµin un mem-
bru al echipei care s studieze la CEX disciplina respectiv (în caz armativ, soluµia va a³at ).
Generare combin ri
Fie n ³i k dou numere naturale, 1 & k & n & 22.
S se genereze în ordine lexicograc toate submulµimile formate din k elemente ale mulµimii
r1, 2, ..., nx.
Soluµie
Vom reprezenta o submulµime ca un vector C cu k elemente (elementele submulµimii).
Evident, 1 & C i & n.
Deoarece ordinea elementelor într-o submulµime nu conteaz , pentru a nu genera de mai multe
ori aceea³i submulµime vom conveni c plas m elementele în submulµime în ordine cresc toare:
C i $ C i 1, pentru orice 1 & i $ k .
Vom genera submuµimile printr-un algoritm de tip succesor.
Cea mai mic submulµime (din pdv lexicograc) este 1, 2, ..., k.
Cea mai mare submulµime este: n-k+1,..., n-1, n
Intrebare: care este cea mai mare valoare care poate plasat pe poziµia i:
Poziµie k k 1 k 2 ... i ... 1
Valoare maxim n n 1 n 2 ... ? ... n k 1
Observ m c atunci când poziµia scade cu 1, valoarea maxim scade cu 1, deci diferenµa dintre
V aloarea_maxima ³i P ozitie este constant :
V aloare_maxima P ozitie n k ? i.
Deducem c valoarea maxim care poate plasat pe poziµia i este n k i.
Pas 1. Iniµializ m vectorul C (C i 1, pentru orice 1 & i & k )
Pas 2. Cât timp este posibil (mai exist succesor)
- a³ m submulµimea curent (dac veric condiµiile din enunµ);
- gener m submulµimea urm toare; în acest scop c ut m prima component (începând din
dreapta c tre stânga) care poate m rit (adic C i $ n k i; dac g sim o astfel de
component o m rim, ³i repunem pe cea mai mic valoare posibil toate componentele urm toare
(C j C j 1 1, i $ j & k ); dac nu g sim o astfel de component deducem c generarea s-a
încheiat, acesta a fost cea mai mare submulµime din punct de vedere lexicograc.
Generare submulµimi
O alt soluµie posibil este de a genera toate submulµimile mulµimii r1, 2, ..., nx ³i de a verica
corectitudinea acelor soluµii care au k elemente. O astfel de abordare ar obµine în principiu 80 de
puncte (70 sau 90 ind punctaje posibile, funcµie de calculatorul de evaluare ³i ecienµa veric rii
condiµiilor).
CAPITOLUL 13. OJI 2008 224
71 a[i][d]=1;
72 }
73 }
74
75 fclose(fin);
76 }
77
78 void write()
79 {
80 int i;
81 for (i=1; i<k; i++)
82 fprintf(fout,"%d ",sol[i]);
83
84 fprintf(fout,"%d\n",sol[k]);
85 }
14.1 Cartele
În sediul unei rme se intr doar cu ajutorul cartelelor magnetice. De câte ori se schimb
codurile de acces, cartelele trebuie formatate. Formatarea presupune imprimarea unui model
prin magnetizare. Dispozitivul în care se introduc cartelele, numit cititor de cartele, veric acest
model. Toate cartelele au acelea³i dimensiuni, suprafaµa p trat ³i grosimea neglijabil . Cele dou
feµe plane ale unei cartele se împart ecare în N N celule p trate, identice ca dimensiuni. Prin
formatare unele celule, marcate cu negru în exemplu, se magnetizeaz permiµând radiaµiei infraro³ii
s treac dintr-o parte în cealalt a cartelei. În interiorul cititorului de cartele se ilumineaz
uniform una dintre feµele cartelei. De cealalt parte fasciculele de lumin care str bat cartela sunt
analizate electronic. Pentru a permite accesul în cl dire modelul imprimat pe cartel trebuie s
coincid exact cu modelul ³ablonului care memoreaz codul de intrare. Prin fanta dispozitivului
nu se pot introduce mai multe cartele deodat . Cartela se poate introduce prin fant cu oricare
dintre muchii spre deschiz tura fantei ³i cu oricare dintre cele dou feµe orientate c tre ³ablon.
Dup introducere cartela se dispune în plan paralel cu ³ablonul, lipit de acesta, astfel încât cele
patru colµuri ale cartelei se suprapun exact cu colµurile ³ablonului. Modelele imprimate pe cele
dou feµe ale unei cartele sunt identice. Unei celule magnetizate îi corespunde pe faµa opus tot
o celul magnetizat , iar unei celule nemagnetizate îi corespunde una nemagnetizat . O celul
magnetizat este transparent pentru radiaµia infraro³ie indiferent de faµa care se ilumineaz .
Un angajat al rmei are mai multe cartele. Pe unele dintre acestea a fost imprimat noul cod
de intrare, iar pe altele sunt coduri mai vechi. Pentru a aa care sunt cartelele care-i permit
accesul în sediul rmei angajatul este nevoit s le verice pe toate, introduc ndu-le pe rând, în
toate modurile pe care le consider necesare, în fanta cititorului de cartele.
Cerinµ
Scrieµi un program care determin care dintre cartele permite accesul în sediul rmei.
Date de intrare
Fi³ierul de intrare cartele.in conµine pe prima linie dou numere naturale N ³i C desp rµite
printr-un spaµiu. N este dimensiunea tablourilor care reprezint modelul ³ablon ³i modelele car-
telelelor. C reprezint num rul de cartele. Urmeaz C 1 blocuri de câte N linii ecare. Primul
bloc de N linii codic ³ablonul. Urm toarele C blocuri de câte N linii codic ecare câte o
cartel . Pe ecare linie sunt câte N valori întregi, desp rµite printr-un singur spaµiu. Celulelor
magnetizate le corespunde valoarea 1, iar celorlalte, valoarea 0.
226
CAPITOLUL 14. OJI 2007 CLASA A IX-A 227
Date de ie³ire
În ³ierul de ie³ire cartele.out se vor scrie C linii, câte o valoare pe linie. Pe linia i se va scrie
valoarea 1 dac cartela i permite accesul în cl dire ³i valoarea 0 în caz contrar.
Restricµii ³i preciz ri
1 $ N, C & 50
Exemplu
cartele.in cartele.out Explicaµii
3 2 1 Datele de intrare corespund situaµiei din gur .
0 1 0 0 Cartela 1 se potrive³te perfect ³ablonului, dac
0 0 1 se rote³te în sens trigonometric cu 90 de grade.
1 0 0 Cartela 2 nu se potrive³te ³ablonului, indiferent
1 0 0 de modul în care se introduce în fant .
0 0 1
0 1 0
0 0 1
0 0 1
0 1 0
Timp maxim de execuµie/test: 1 secund
Pentru ecare cartel , se compar element cu element, matricea care reprezint sablonul, cu
urm toarele tablouri:
1. Cartela
2. Cartela rotit cu 90 grade
3. Cartela rotit cu 180 grade
4. Cartela rotit cu 270 grade
Dac nu s-a gasit o coincidenµ , se întoarce cartela, printr-o operaµie de oglindire faµ de linia
i n©2, (sau faµ de coloana j n©2), dup care se compar ³ablonul cu urm toarele tablouri:
5. Cartela oglindit
6. Cartela oglindit rotit cu 90 grade
7. Cartela oglindit rotit cu 180 grade
8. Cartela oglindit rotit cu 270 grade
Rotirile se pot face în sens trigonometric sau orar.
Dac s-a g sit o coincidenµ la oricare dintre pa³ii de mai sus, se opre³te c utarea, se aseaz
1 ³i se trece la prelucrarea urm toarei cartele.
Dac nici dup pasul 8 nu s-a gasit o potrivire exact , se a³eaz 0 ³i se trece la prelucrarea
urm toarei cartele.
94 b[i][j] = aux[i][j];
95 }
Varianta 1:
44 {
45 st.nextToken(); b[i][j]=(int)st.nval;
46 if(b[i][j]!=a[i][j]) identice=false;
47 }
48
49 for(int f=1;f<=2&&!identice;f++) // pentru fata 1 si 2
50 {
51 for(r=1;r<=4&&!identice;r++) // la a patra rotatie se revine la matricea
initiala
52 {
53 roteste(); // cu 90 in sens trigonometric
54 if(egale()) identice=true;
55 }
56 if(!identice) inverseaza();
57 }
58 if(identice) out.println(1); else out.println(0);
59 }// for k
60 }// rezolva(...)
61
62 static boolean egale()
63 {
64 for(int i=1;i<=n;i++)
65 for(int j=1; j<=n; j++)
66 if(a[i][j]!=b[i][j] ) return false;
67 return true;
68 }// egale(...)
69
70 static void inverseaza()
71 {
72 int i, j, temp;
73 for(i=1;i<=n/2;i++)
74 for(j=1;j<=n;j++) { temp=b[i][j]; b[i][j]=b[n-i+1][j]; b[n-i+1][j]=temp; }
75 } // inverseaza(...)
76
77 static void roteste()
78 {
79 int i, j;
80 for(i=1;i<=n;i++)
81 for(j=1;j<=n;j++) aux[n-j+1][i]=b[i][j];
82
83 for(i=1;i<=n;i++)
84 for(j=1;j<=n;j++) b[i][j]=aux[i][j];
85 }// roteste(...)
86 }// class
Varianta 2:
28 st.nextToken(); a[i][j]=(int)st.nval;
29 }
30
31 for(k=1;k<=c;k++)
32 {
33 for(i=1;i<=n;i++) // citesc cartela k
34 for(j=1;j<=n;j++)
35 {
36 st.nextToken(); b[i][j]=(int)st.nval;
37 }
38
39 ok=true;
40 for(i=1;i<=n&&ok;i++) // direct
41 for(j=1;j<=n&&ok;j++)
42 if(a[i][j]!=b[i][j]) ok=false;
43 if(ok) {out.println(1); continue;} // cu alta cartela
44
45 ok=true;
46 for(i=1;i<=n&&ok;i++) // rotit cu 90 (ceas!)
47 for(j=1;j<=n&&ok;j++)
48 if(a[i][j]!=b[j][n-(i-1)]) ok=false;
49 if(ok) {out.println(1); continue;} // cu alta cartela
50
51 ok=true;
52 for(i=1;i<=n&&ok;i++) // rotit cu 180 (ceas!)
53 for(j=1;j<=n&&ok;j++)
54 if(a[i][j]!=b[n-(i-1)][n-(j-1)]) ok=false;
55 if(ok) {out.println(1); continue;} // cu alta cartela
56
57 ok=true;
58 for(i=1;i<=n&&ok;i++) // rotit cu 270 (ceas!) <==> 90 trig
59 for(j=1;j<=n&&ok;j++)
60 if(a[i][j]!=b[n-(j-1)][i]) ok=false;
61 if(ok) {out.println(1); continue;} // cu alta cartela
62
63 ok=true;
64 for(i=1;i<=n&&ok;i++) // invers + direct
65 for(j=1;j<=n&&ok;j++)
66 if(a[i][j]!=b[i][n-(j-1)]) ok=false;
67 if(ok) {out.println(1); continue;} // cu alta cartela
68
69 ok=true;
70 for(i=1;i<=n&&ok;i++) // invers + rotit 90 (ceas!)
71 for(j=1;j<=n&&ok;j++)
72 if(a[i][j]!=b[n-(j-1)][n-(i-1)]) ok=false;
73 if(ok) {out.println(1); continue;} // cu alta cartela
74
75 ok=true;
76 for(i=1;i<=n&&ok;i++) // invers + rotit 180 (ceas!)
77 for(j=1;j<=n&&ok;j++)
78 if(a[i][j]!=b[n-(i-1)][j]) ok=false;
79 if(ok) {out.println(1); continue;} // cu alta cartela
80
81 ok=true;
82 for(i=1;i<=n&&ok;i++) // invers + rotit cu 270 (ceas!) <==> 90 trig
83 for(j=1;j<=n&&ok;j++)
84 if(a[i][j]!=b[j][i]) ok=false;
85 if(ok) {out.println(1); continue;} // cu alta cartela
86
87 out.println(0); // nu s-a potrivit
88 } // for k
89 out.close();
90 }// main
91 }// class
Varianta 3:
8
9 static int[][] a=new int[DIM][DIM]; // sablonul
10 static int[][] b=new int[DIM][DIM]; // cartela
11
12 static int n, c;
13
14 public static void main(String[] args) throws IOException
15 {
16 int i, j, k;
17
18 st=new StreamTokenizer(new BufferedReader(new FileReader("1.in")));
19 out=new PrintWriter(new BufferedWriter(new FileWriter("cartele.out")));
20
21 st.nextToken(); n=(int)st.nval;
22 st.nextToken(); c=(int)st.nval;
23
24 for(i=1;i<=n;i++) // citesc sablonul
25 for(j=1;j<=n;j++)
26 {
27 st.nextToken(); a[i][j]=(int)st.nval;
28 }
29
30 for(k=1;k<=c;k++)
31 {
32 for(i=1;i<=n;i++) // citesc cartela k
33 for(j=1;j<=n;j++)
34 {
35 st.nextToken(); b[i][j]=(int)st.nval;
36 }
37
38 if(egale(1,0,0,0, 0,1,0,0)) {out.println(1); continue;} // direct
39 if(egale(0,1,0,0, 0,0,1,0)) {out.println(1); continue;} // rotit cu 90 (ceas!)
40 if(egale(0,0,1,0, 0,0,0,1)) {out.println(1); continue;} // rotit cu 180 (ceas!)
41 if(egale(0,0,0,1, 1,0,0,0)) {out.println(1); continue;} // rotit cu 270 (ceas!)
42 if(egale(1,0,0,0, 0,0,0,1)) {out.println(1); continue;} // invers + direct
43 if(egale(0,0,0,1, 0,0,1,0)) {out.println(1); continue;} // invers + rotit 90 (ceas
!)
44 if(egale(0,0,1,0, 0,1,0,0)) {out.println(1); continue;} // invers + rotit 180 (
ceas!)
45 if(egale(0,1,0,0, 1,0,0,0)) {out.println(1); continue;} // invers + rotit cu 270 (
ceas!)
46
47 out.println(0); // nu s-a potrivit
48 } // for k
49 out.close();
50 }// main
51
52 static boolean egale(int i1,int j1, int ni1, int nj1, int i2, int j2, int ni2, int nj2
)
53 {
54 int i,j;
55 boolean ok=true;
56 for(i=1;i<=n&&ok;i++)
57 for(j=1;j<=n&&ok;j++)
58 if(a[i][j]
59 !=
60 b[i*i1+j*j1+(n-i+1)*ni1+(n-j+1)*nj1][i*i2+j*j2+(n-i+1)*ni2+(n-j+1)*nj2])
61 ok=false;
62 return ok;
63 }// egale(...)
64 }// class
14.2 Paritate
În vederea asigur rii unei transmiteri cât mai exacte a informaµiilor pe reµea, transmiterea se
efectueaz caracter cu caracter, ecare caracter ind dat prin codul s u ASCII, adic o grup de
8 biµi (octet). Pentru ecare 8 biµi transmi³i se calculeaz un bit de paritate care are valoarea 0
(dac codul ASCII al caracterului conµine un num r par de cifre binare 1) sau 1 (în caz contrar).
Deoarece în problema noastr se transmit numai caractere ASCII standard, cu codul ASCII
din intervalul [32,127], codul lor ASCII are bitul 7 (primul bit din stnga) egal cu 0. Pe aceast
poziµie va pus bitul de paritate, economisind astfel câte un bit pentru ecare caracter transmis.
CAPITOLUL 14. OJI 2007 CLASA A IX-A 233
De exemplu, dac mesajul care trebuie trasmis conµine caracterele "Paritate", succesiunea de biµi
transmis va :
În plus, pe lâng caracterele amintite, în mesaj mai poate s apar un caracter special care
indic trecerea la începutul unui nou rând. Acest caracter are codul ASCII 10.
Cerinµ
S se scrie un program care s verice dac un text a fost sau nu transmis corect.
Date de intrare
Fi³ierul de intrare paritate.in are pe prima linie o succesiune de caractere '0' ³i '1' care
reprezint mesajul transmis. Între caractere nu exist spaµii. Linia se termin cu caracterul
marcaj de sfâr³it de linie (newline).
Date de ie³ire
Fi³ierul de ie³ire paritate.out are pe prima linie mesajul DA dac textul a fost transmis corect
sau NU în caz contrar. În cazul în care mesajul de pe prima linie este DA liniile urm toare vor
conµine textul transmis în clar. În cazul în care mesajul de pe prima linie este NU linia urm toare
va conµine numerele de ordine ale caracterelor care nu au fost transmise corect, în ordine strict
cresc toare, separate prin câte un spaµiu.
Restricµii ³i preciz ri
a Cei 8 biµi ai codului ASCII a unui caracter se numeroteaz de la 0 la 7, de la dreapta la
stânga, cel mai din stânga bit ind bitul 7 iar cel mai din dreapta bitul 0.
a Textul transmis are cel mult 60000 caractere.
a Num rul de caractere '0' ³i '1' din prima linie a ³ierului de intrare este multiplu de 8.
a Codurile ASCII ale caracterelor din text aparµin mulµimii r10, 32 127x, codul 10 însemnând
trecerea la începutul unui rând nou.
a Nici o linie din ³ierul de iec sire nu va avea mai mult de 255 caractere.
a Caracterele din text sunt numerotate începând de la 0.
a mesajele DA/NU din prima linie a ³ierului de ie³ire se scriu cu majuscule.
Exemplul 1:
paritate.in
0101000011100001011100100110100101110100111000010111010001100101
paritate.out Explicaµie
DA Toate codurile sunt
Paritate
Exemplul 2:
paritate.in
1101000011100001111100100110100101110100111000010111010011100101
paritate.out Explicaµie
NU Primul caracter a fost transmis ca succesiunea de biµi 11010000
027 ceea ce înseamn c f r bitul de paritate ar trebuit s existe
un num r impar de cifre 1, ceea ce este fals. Deci caracterul nu
a fosttransmis corect. Acela³i lucru se veric ³i pentru
caracterele cu numerele de ordine 2 ³i 7.
Exemplul 3:
paritate.in
010000011111101001101001000010100110010100001010011010100110111101101001
paritate.out Explicaµie
DA Toate codurile sunt corecte.
Azi În text exist dou caractere cu cod ASCII 10
e
joi
Timp maxim de execuµie/test: 1 secund
CAPITOLUL 14. OJI 2007 CLASA A IX-A 234
40 a[i]=1; //pun 1
41 Eroare=i; //si retin pozitia
42 }
43 fscanf(f, "%c", &c);
44 }
45
46 if (Eroare==0) //daca nu sunt erori
47 { //scrie DA si
48 fprintf(g, "DA\n");
49 for (j=0; j<=i; j++) //afiseaza cele i+1 caractere
50 if (a[j]==10) //avand grija la caracterul cu codul 10
51 fprintf(g, "\n");
52 else //altfel
53 fprintf(g, "%c", a[j]); //scrie caracterul
54 // fprintf(g, "\n");
55 }
56 else //eroare!!!
57 {
58 fprintf(g, "NU\n"); //scrie NU si
59 for (j=0; j<Eroare; j++)
60 if (a[j]==1) //cauta erorile - cod 01
61 fprintf(g, "%ld ", j); //si afiseaza pozitia lor
62 fprintf(g, "%ld\n", Eroare); //afiseaza pozitia ultimei erori
63 }
64
65 fclose(g);
66 return 0;
67 }
Varianta 1: Versiunea este o prelucrare a variantei ociale; comentariile din sursa au r mas
nemodicate pentru c sunt un exemplu bun!
38 Bit=c-’0’;
39 if(Bit==1) Nr1++; // daca e 1 il numar
40 Cod=Cod*2+Bit; // formez codul
41 }
42
43 if((Nr1+BitP)%2==0) // daca cod corect
44 a[i]=Cod; // pun caracterul in vector
45 else // altfel
46 {
47 a[i]=1; // pun 1
48 Eroare=i; // si retin pozitia
49 }
50 ++k;
51 }// while
52
53 if(Eroare==0) // daca nu sunt erori
54 {
55 out.println("DA"); // scrie DA si
56 for(j=0;j<=i;j++) // afiseaza cele i+1 caractere
57 if(a[j]==10) // avand grija la caracterul cu codul 10
58 out.println();
59 else // altfel
60 out.print((char)a[j]); // scrie caracterul
61 }
62 else // eroare!!!
63 {
64 out.println("NU"); // scrie NU si
65 for(j=0;j<Eroare;j++)
66 if(a[j]==1) // cauta erorile - cod 01
67 out.print(j+" "); // si afiseaza pozitia lor
68 out.println(Eroare); // afiseaza pozitia ultimei erori
69 }
70
71 out.close();
72 }// main
73 }// class
Capitolul 15
15.1 Flori
Cristina Bohm
Fetiµele din grupa mare de la gr diniµ culeg ori ³i vor s împleteasc coroniµe pentru festivi-
tatea de premiere. În gr din sunt mai multe tipuri de ori. Fiecare dintre cele n fetiµe culege un
buchet având acela³i num r de ori, îns nu neap rat de acela³i tip. Pentru a împleti coroniµele
fetiµele se împart în grupe. O fetiµ se poate ata³a unui grup numai dac are cel puµin o oare de
acela³i tip cu cel puµin o alt fetiµ din grupul respectiv.
Cerinµ
Fiind dat un num r natural n reprezentând num rul fetiµelor ³i num rul natural k reprezentând
num rul de ori dintr-un buchet, s se determine grupele care se formeaz .
Date de intrare
Fi³ierul de intrare ori.in conµine pe prima linie, separate printr-un spaµiu, numerele naturale
n ³i k , reprezentând num rul de fetiµe ³i respectiv num rul de ori din ecare buchet. Fiecare
dintre urm toarele n linii conµine, pentru ecare fetiµ , câte k valori separate prin câte un spaµiu
reprezentând tipurile de ori culese.
Date de ie³ire
Fi³ierul de ie³ire ori.out va conµine pe ecare linie câte o grup format din numerele de
ordine ale fetiµelor separate prin câte un spaµiu, în ordine cresc toare, ca în exemplu.
Restricµii ³i preciz ri
a 1 & n & 150
a 1 & k & 100
a Tipul unei ori este un num r întreg din intervalul 0, 100.
a Într-o grup numerele de ordine ale fetiµelor trebuie date în ordine strict cresc toare.
a În ³ierul de ie³ire grupele vor a³ate în ordinea cresc toare a num rului de ordine al
primei fetiµe din grup .
Exemplu
ori.in ori.out Explicaµie
5 4 134 Fetiµele 1 ³i 3 au cules amândou ori de tipul 1,
1 2 3 4 2 iar fetiµele 1 ³i 4 au cules amândou ori de tipurile
5 6 9 6 5 2,3 ³i 4, deci toate cele trei fetiµe (1, 3, 4) se vor aa
1 1 1 1 în aceea³i grup . Fetiµele 2 ³i 5 vor forma ecare câte
2 4 4 3 o grup deoarece nu au cules ori de acela³i tip cu
7 7 7 7 nici una dintre celelalte fetiµe.
Timp de rulare/test: 1 secund
Soluµia comisiei
237
CAPITOLUL 15. OJI 2006 CLASA A IX-A 238
- construiesc matricea a denita astfel : pe linia i sunt tipurile distincte de ori ale fetiµei cu
num rul de ordine i
- a[i][0] = num rul de elemente de pe linia i; acesta va deveni 0 dac linia a fost reunit
în alt linie
- vectorul viz are n elemente ³i pe parcursul prelucr rii , fetiµele care ajung în aceea³i grup
vor avea aceea³i valoare în vectorul viz: de exemplu, dac fetiµa 3 ajunge în grupa în care
e fetiµa 1 atunci viz[3]=viz[1];
- funcµia reuneste face reuniunea mulµimilor de pe liniile i ³i j în linia i; dac s-a f -
cut o astfel de reuniune, scad i (i ) ³i astfel se rezolv situaµia în care de exemplu
i rel j, not ( i rel k) , j rel k; executând i--, k va ajunge tot în grup cu
i; altfel k ar ajunge în alt grup
- a³area grupelor presupune selectarea din vectorul viz a poziµiilor care au aceea³i valoare:
toate poziµiile i care au viz[i]=1 (de exemplu) sunt în prima grup ; pun pe 0 poziµiile
a³ate pentru a nu le mai relua o dat .
43 int main()
44 {
45 int viz[150],i,j,val,ok;
46 fscanf(f,"%d %d",&n,&k);
47
48 for(i=1;i<=n;i++)
49 for(j=1;j<=k;j++)
50 {
51 fscanf(f,"%d",&val);
52 if(!apartine(val,i))
53 {
54 a[i][0]++; // pe prima coloana am nr. de tipuri distincte
55 // de flori
56 a[i][ a[i][0] ]=val; // in multimea de pe linia i am tipurile
57 // distincte de flori al fetitei i
58 }
59 }
60
61 for(i=1;i<=n;i++)
62 viz[i]=i; //initial exista n grupe
63
64 for(i=1;i<=n;i++)
65 {
66 ok=0;
67 if(a[i][0])
68 {
69 for(j=i+1;j<=n;j++)
70 if(irelj(i,j))
71 {
72 viz[j]=viz[i]; //j trebuie sa ajunga in grupa cu i
73 reuneste(i,j); //reunesc in linia i linia j
74 a[j][0]=0;//consider ca in multimea j am 0 elemente acuma
75 ok=1;
76 }
77 }
78
79 if (ok) i--;// faptul ca am reunit in i cel putin o multime j implica
80 // sa continui cu aceeasi linie i
81 // daca as lasa i sa se incrementeze conform for-ului,
82 // ar gresi in sensul ca
83 // pt. i rel j si i nu e in rel cu k si j rel k
84 // ar pune j in grupa i dar k ar ajunge in alta grupa
85 }
86
87 for(i=1;i<=n;i++)
88 if(viz[i])
89 {
90 fprintf(g,"%d ",i);
91 for(j=i+1;j<=n;j++)
92 if(viz[i]==viz[j])
93 {
94 fprintf(g,"%d ",j);
95 viz[j]=0; //ca sa nu mai fie prelucrat
96 }
97
98 fprintf(g,"\n");
99 }
100
101 fclose(g);
102 return 0;
103 }
Variant iterativ :
Variant recursiv :
Listing 15.1.3: ori2.java
1 import java.io.*;
2 class Flori2
3 {
4 static int n,k,ng;
5 static char[][] a=new char[151][101];
6 static int[] gf=new int[151];
7
8 public static void main(String[] args) throws IOException
9 {
10 int i,j,fij;
11 StreamTokenizer st=new StreamTokenizer(
12 new BufferedReader(new FileReader("flori.in")));
13 PrintWriter out=new PrintWriter(
CAPITOLUL 15. OJI 2006 CLASA A IX-A 241
15.2 Pluton
Marinel erban
În timpul acµiunii "Furtun în de³ert" din cauza unei furtuni de nisip, n soldaµi s-au r t cit de
plutoanele lor. Dup trecerea furtunii se pune problema regrup rii acestora pe plutoane. Pentru
aceasta se folosesc pl cuµele de identicare pe care soldaµii le poart la gât. Pe aceste pl cuµe
sunt scrise numere care pot identica ecare soldat ³i plutonul din care acesta face parte. Astfel,
soldaµii din acela³i pluton au num rul de identicare format din acelea³i cifre, dispuse în alt
ordine ³i numerele de identicare sunt unice. De exemplu, numerele de identicare 78003433,
83043073, 33347008 indic faptul c cei trei soldaµi care le poart fac parte din acela³i pluton.
Cerinµ
Fiind date cele n numere de pe pl cuµele de identicare, s se regrupeze cei n soldaµi pe
plutoane, indicându-se num rul de plutoane g site (un pluton ref cut trebuie s aib minimum
un soldat), num rul de soldaµi din cel mai numeros pluton, num rul de plutoane care au acest
num r maxim de soldaµi precum ³i componenµa unui astfel de pluton (cu num r maxim de soldaµi
regrupaµi).
Date de intrare
Fi³ierul de intrare pluton.in conµine pe prima linie num rul n de soldaµi recuperaµi, iar pe
ecare dintre urm toarele n linii câte un num r de identicare a celor n soldaµi.
Date de ie³ire
Fi³ierul de ie³ire pluton.out va conµine pe prima linie num rul de plutoane ref cute. Linia a
doua va conµine num rul de soldaµi din cel mai numeros pluton ref cut. Linia a treia va conµine
num rul de plutoane care au num rul maxim de soldaµi recuperaµi. Linia a patra va conµine
CAPITOLUL 15. OJI 2006 CLASA A IX-A 242
componenµa unui astfel de pluton, cu num r maxim de soldaµi recuperaµi, numerele de identicare
ale soldaµilor din componenµ ind scrise unul dup altul separate prin câte un spaµiu.
Restricµii ³i preciz ri
a 0 $ n & 4000
a 0 $ num r de identicare $ 2.000.000.000
Observaµii
Deoarece linia a patra conµine numerele de identicare ale soldaµilor unuia dintre plutoanele
cu un num r maxim de soldaµi, pot exista mai multe soluµii corecte. Se poate alege oricare dintre
acestea.
Se acord punctaje parµiale astfel: pentru valoarea corect de pe prima linie se acord 30%
din punctaj; pentru valorile corecte de pe prima ³i a doua linie se acord 50% din punctaj, pentru
valorile corecte de pe prima, a doua ³i a treia linie se acord 70% din punctaj, iar pentru rezolvarea
corect a tuturor cerinµelor se acord punctajul integral aferent testului.
Exemplu
pluton.in pluton.out Explicaµie
10 6 Au fost recuperaµi soldaµi din 6 plutoane
1223 3 distincte, cei mai mulµi soldaµi recuperaµi
123 2 dintr-un pluton ind în num r de 3.
666 321 312 123
321 Exist 2 plutoane cu num r maxim de
7890 soldaµi recuperaµi (3), unul dintre ele
2213 ind format din soldaµii cu numerele
312 321 312 123.
655
1000 De remarcat c ³i soluµia
1322 1223 2213 1322 este corect .
Timp de rulare/test: 1 secund
Soluµia comisiei
Soluµia 1:
în timpul citirii creez un nou vector care conµine pe poziµiile corespunz toare numerele de
identicare din vectorul iniµial în ordinea descrescatoare a cifrelor
în etapa a doua se parcurge vectorul nou format grupând toate numerele de identicare
identice; dup formarea unui grup (pluton) se determin m rimea acestuia reµinâdu-se acesta
dac e cel mai numeros g sit pân în acel moment sau contorizându-l dac num rul de soldaµi
determinat este egal cu cel maxim determinat anterior.
Soluµia 2:
citesc numerele de identicare în vectorul a[]
ordonez cei trei vectori cresc tor dup num rul de cifre distincte (dup c[]) ³i dup num rul
de cifre, deci cheia de sortare va un num r construit dup formula c[i]*10+b[i]
formez ³i num r plutoanele; plutoanele le voi reµine pe linii distincte a matricei G[MAX][2]
la cerinµa 4
Soluµia 3:
se utilizeaza notiunea de lista: dintr-o lista fac parte toti membrii unui pluton
se construieste un vector ajutator care retine pentru ecare element elementul care il urmeaza
in lista
pe parcursul formarii listelor se determina lista cea mai numeroasa precum si numarul de
liste de acest tip
38 void Citire(void)
39 {
40 int i, j;
41 long x;
42
43 fscanf(Fin, "%ld", &n);
44 for (i=1; i<=n; i++)
45 {
46 fscanf(Fin, "%ld", &a[i]);
47 /*construiesc 2 vectori ajutatori
48 - vectorul b care va contine numarul de cifre al fiecarui element
49 - vectorul c care va contine numarul de cifre distincte a fiecarui element*/
50 for (j=0; j<=9; j++) cifre[j]=0;
51 x=a[i];
52 while (x)
53 {
54 b[i]++; //numar total de cifre
55 cifre[x%10]=1;
56 x/=10;
57 }
58 for (j=0; j<=9; j++)
59 c[i]+=cifre[j]; //numar de cifre distincte
60 }
61 }
62
63 void Sortare(void)
64 {
65 int i, j;
66 long min, pm, x, aux;
67
68 /*ordonez cei trei vectori crescator dupa numarul de cifre (dupa b)
69 si dupa numarul de cifre distincte, deci cheia de sortare va fi un numar
70 construit dupa formula b[i]*10+c[i] */
71 for (i=1; i<=n-1; i++)
72 {
73 min=b[i]*10+c[i]; pm=i;
74 for (j=i+1; j<=n; j++)
75 {
76 x=b[j]*10+c[j];
77 if (x<min)
78 {
79 min=x; pm=j;
80 }
81 }
82
83 aux=c[i]; c[i]=c[pm]; c[pm]=aux;
84 aux=b[i]; b[i]=b[pm]; b[pm]=aux;
85 aux=a[i]; a[i]=a[pm]; a[pm]=aux;
86 }
87 }
88
89 void FormarePlutoane(void)
90 {
91 int i, j;
92
93 /*formez si numar plutoanele
94 - plutoanele le voi retine pe linii distincte a matricii G
95 - in fiecare linie, elementul 0 va contine numarul de elemente din pluton
96 iar elementul 1 reprezentantul plutonului, primul care apare in a*/
97 while (!ToatePuse())
98 {
99 i=1;
100 while (Pus[i]) i++; //caut primul nepus inca
101
102 //retinem primul element nepus din pluton cu caracteristicile lui
103 btest=b[i]; ctest=c[i];
104 NrG=NrG+1; G[NrG][0]=1;
105 G[NrG][1]=a[i]; Pus[i]=TRUE; //il pun in pluton
106 Cifrele(a[i], cifreTest); //retin cifrele in cifreTest[]
107
108 //verific elementele cu aceleasi caracteristici daca fac parte din
109 //acelasi pluton cu primul element pe care l-am retinut
110 i++;
111 while ((b[i]==btest) && (c[i]==ctest) && (i<=n))
112 { //ar putea face parte din acelasi pluton
113 Cifrele(a[i], cifre);//aflu cifrele in cifre[]
CAPITOLUL 15. OJI 2006 CLASA A IX-A 245
2 #include <conio.h>
3 #include <cstring>
4
5 using namespace std;
6
7 int verif(long int a,long int b)
8
9 // verifica daca a si b au aceleasi cifre
10 { int x[10],y[10],i;
11
12 memset(x,0,sizeof(x)); // x[i] retine numarul de cifre de i din a
13 memset(y,0,sizeof(y)); // y[i] retine numarul de cifre de i din b
14
15 while (a)
16 { x[a%10]++;
17 a/=10;
18 }
19
20 while (b)
21 { y[b%10]++;
22 b/=10;
23 }
24
25 for (i=0;i<10;i++)
26 if (x[i]!=y[i])
27 return 0;
28
29 return 1;
30 }
31
32 int main()
33 { long int x[4000],t;
34 int y[4000],z[4000],a[4000],b[4000],urm[4000],max,q,i1,j,p;
35
36 memset(x,0,sizeof(x)); // numerele de identificare ale soldatilor
37 memset(y,0,sizeof(y)); // bitul j, j=0,1,...,9, a lui y[i] este 1 daca
38 // x[i] contine cifra j
39 memset(z,0,sizeof(z)); // z[i]=numarul de cifre (distincte sau nu) din x[i]
40 memset(a,0,sizeof(a)); // a[i] = numaarum plutonului din care face parte i
41
42 // soldatii i si j fac parte din acelasi pluton daca:
43 // 1. y[i]=y[j], adica au aceleasi cifre distincte
44 // 2. z[i]=z[j], adica au acelasi numar total de cifre
45 // dar aceste doua conditii nu sunt suficiente (vezi de exemplu 112 si 122)
46 // 3. verif(x[i],y[j])=1, adica au exact aceleasi cifre
47
48 memset(b,0,sizeof(b));
49 memset(urm,0,sizeof(urm)); // urm[i] memoreaza indicele urmatorului soldat
50 // din acelasi pluton cu i
51
52 int n,i,k;
53
54 ifstream f("pluton.in");
55
56 f>>n; // numarul de soldati
57
58 for (i=0;i<n;i++)
59 { f>>x[i];
60 k=0;
61 t=x[i];
62 y[i]=0; z[i]=0;
63 while (t)
64 { y[i]=y[i] | (1<<(t%10));
65 t=t/10; z[i]++;
66 }
67 }
68
69 t=0; // t = numarul total de plutoane
70 max=0; // max = numarul maxim de soldati dintr-un pluton
71 q=0; // p = indicele primului soldat din plutonul cu
72 // numar maxim de soldati
73 // q = numarul de putoane cu numar maxim de soldati
74 for (i=0;i<n;i++)
75 if (a[i]==0)
76 { i1=i; t++;
77 k=1; a[i]=t;
CAPITOLUL 15. OJI 2006 CLASA A IX-A 247
78 for (j=i+1;j<n;j++)
79 if ((a[j]==0)&&(y[i]==y[j])&&(z[i]==z[j]))
80 { if (verif(x[i],x[j]))
81 { a[j]=t;
82 urm[i1]=j;
83 i1=j;
84 k++;
85 }
86 }
87
88 if (k>max) { max=k; p=i; q=1; }
89 else
90 if (k==max)
91 q++;
92 }
93
94 ofstream g("pluton.out");
95 g<<t<<endl;
96 g<<max<<endl;
97 g<<q<<endl;
98
99 i=p;
100 do
101 { g<<x[i]<<" ";
102 i=urm[i];
103 } while (i!=0);
104
105 g.close();
106 f.close();
107
108 return 0;
109 }
41 fstream f;
42
43 f.open("pluton.in",ios::in);
44 f>>n; //se citesc din fisierul pluton.in numarul n si
45 for(i=1;i<=n;i++) //elementele vectorului Nr si se completeaza valorile
46 { //corespunzatoare in vectorul NrSort
47 f>>Nr[i];
48 NrSort[i]=SortareCifre(Nr[i]);
49 }
50 f.close();
51
52 i=1; //pozitia curenta din vectori Nr si NrSort(soldatul curent i)
53 nrp=nrmax=maxx=0;
54 while(i<=n)
55 {
56 p=i; //se salveaza pozitia curenta i in variabila p
57 j=i+1; //se cauta soldati j din acelasi pluton cu soldatul curent i
58 while(j<=n) //adica soldati pentru care NrSort[j]=NrSort[i]
59 {
60 if(NrSort[i]==NrSort[j]) //in cazul in care se gaseste un astfel de soldat
61 { //acesta este adus langa soldatul curent i
62 i++;
63 aux=Nr[i]; Nr[i]=Nr[j]; Nr[j]=aux;
64 aux=NrSort[i]; NrSort[i]=NrSort[j]; NrSort[j]=aux;
65 }
66 j++;
67 }
68
69 i++; //s-au adus langa soldatul i toti posibilii sai colegi de pluton
70 nrp++; //deci s-a mai refacut un pluton intre pozitiile p si i-1 din
71 //cei doi vectori Nr si NrSort
72
73 if(i-p>maxx) //daca numarul de soldati din ultimul pluton refacut (adica i-p)
74 { //este mai mare strict decat max se actualizeaza valorile
75 maxx=i-p; //variabilelor max si nrmax
76 nrmax=1;
77 pmax=p; //pmax retine pozitia la care incepe in vectorul Nr plutonul
78 } //cu numar maxim de soldati
79 else
80 if(i-p==maxx) nrmax++; //daca numarul de soldati din ultimul pluton refacut
81 } //este egal cu max se actualizeaza valoarea lui nrmax
82
83 f.open("pluton.out",ios::out); //se scriu in fisierul pluton.out rezultatele
84 f<<nrp<<endl<<maxx<<endl<<nrmax<<endl;
85 for(i=pmax;i<pmax+maxx;i++) f<<Nr[i]<<" ";
86 f.close();
87
88 return 0;
89 }
19
20 while(nr!=0) { fc[(int)(nr%10)]++; nr=nr/10; nc++; }
21
22 k=0;
23 for(i=9;i>=0;i--)
24 if(fc[i]!=0)
25 for(j=1;j<=fc[i];j++) { k++; x[k]=i; }
26
27 for(i=1;i<=nc;i++) nrcd=nrcd*10+x[i];
28 return nrcd;
29 }// cifre(...)
30
31 public static void main(String[] args) throws IOException
32 {
33 int i,j;
34 int max,npmax,pmax;
35
36 StreamTokenizer st=new StreamTokenizer(
37 new BufferedReader(new FileReader("9-pluton.in")));
38 PrintWriter out=new PrintWriter(
39 new BufferedWriter(new FileWriter("pluton.out")));
40
41 st.nextToken(); n=(int)st.nval;
42 for(i=1;i<=n;i++) {st.nextToken(); ni[i]=(int)st.nval;}
43
44 for(i=1;i<=n;i++) nid[i]=cifre(ni[i]);
45
46 np=0;
47 for(i=1;i<=n;i++)
48 {
49 if(nip[i]!=0) continue;
50 np++;
51 nip[i]=np;
52 for(j=i+1;j<=n;j++)
53 if(nip[j]==0)
54 if(nid[j]==nid[i]) nip[j]=np;
55 }
56
57 out.println(np);
58
59 for(i=1;i<=np;i++)
60 for(j=1;j<=n;j++) if(nip[j]==i) z[i]++;
61
62 max=0;
63 npmax=0;
64 pmax=0;
65
66 for(i=1;i<=np;i++) if(z[i]>max) {max=z[i];pmax=i;}
67 out.println(max);
68
69 for(i=1;i<=np;i++) if(z[i]==max) npmax++;
70 out.println(npmax);
71
72 for(i=1;i<=n;i++) if(nip[i]==pmax) out.print(ni[i]+" ");
73
74 out.println();
75 out.close();
76 }// main
77 }// class
12
13 static void nrcd(int nr,int i0)
14 {
15 int i,j,k,nc;
16 int nrcd1, nrcd2; // nr cu cifre descrescatoare = |nrcd1|nrcd2|
17
18 for(i=0;i<=9;i++) fc[i]=0;
19 for(i=0;i<=10;i++) x[i]=0;
20
21 nc=0;
22 while(nr!=0) { fc[(int)(nr%10)]++; nr=nr/10; nc++; }
23
24 k=0;
25 for(i=0;i<=9;i++)
26 if(fc[i]!=0)
27 for(j=1;j<=fc[i];j++) { k++; x[k]=i; }
28
29 nrcd1=0;
30 for(i=nc;i>=6;i--) nrcd1=nrcd1*10+x[i];
31
32 nrcd2=0;
33 for(i=5;i>=1;i--) nrcd2=nrcd2*10+x[i];
34
35 nid1[i0]=nrcd1;
36 nid2[i0]=nrcd2;
37 }// cifre(...)
38
39 public static void main(String[] args) throws IOException
40 {
41 int i, j, max, npmax, pmax;
42
43 StreamTokenizer st=new StreamTokenizer(
44 new BufferedReader(new FileReader("pluton.in")));
45 PrintWriter out=new PrintWriter(
46 new BufferedWriter(new FileWriter("pluton.out")));
47
48 st.nextToken(); n=(int)st.nval;
49 for(i=1;i<=n;i++) {st.nextToken(); ni[i]=(int)st.nval;}
50 for(i=1;i<=n;i++) nrcd(ni[i],i);
51
52 np=0;
53 for(i=1;i<=n;i++)
54 {
55 if(nip[i]!=0) continue;
56 np++;
57 nip[i]=np;
58 for(j=i+1;j<=n;j++)
59 if(nip[j]==0)
60 if((nid1[j]==nid1[i])&&(nid2[j]==nid2[i])) nip[j]=np;
61 }
62 out.println(np);
63
64 for(i=1;i<=np;i++)
65 for(j=1;j<=n;j++) if(nip[j]==i) z[i]++;
66
67 max=0; npmax=0; pmax=0;
68
69 for(i=1;i<=np;i++) if(z[i]>max) {max=z[i];pmax=i;}
70 out.println(max);
71
72 for(i=1;i<=np;i++) if(z[i]==max) npmax++;
73 out.println(npmax);
74
75 for(i=1;i<=n;i++) if(nip[i]==pmax) out.print(ni[i]+" ");
76
77 out.println(); out.close();
78 }// main
79 }// class
Capitolul 16
16.1 Numere
Doru Popescu Anastasiu
Mircea este pasionat de programare. El a început s rezolve probleme din ce în ce mai
grele. Astfel a ajuns la o problem , care are ca date de intrare un tablou p tratic cu n linii ³i
2
n coloane, componente tabloului ind toate numerele naturale distincte de la 1 la n . Pentru a
verica programul pe care l-a scris îi trebuie un ³ier care s conµin tabloul respectiv. Dup ce a
creat acest ³ier, fratele s u, pus pe ³otii îi umbl în ³ier ³i îi schimb câteva numere consecutive,
cu num rul 0. Când se întoarce Mircea de la joac constat cu stupoare c nu îi merge programul
pentru testul respectiv. Dup câteva ore de depanare î³i d seama c programul lui este corect ³i
c ³ierul de intrare are probleme.
Cerinµ
Scrieµi un program care s -l ajute pe Mircea, g sindu-i cel mai mic ³i cel mai mare dintre
numerele consecutive schimbate de fratele s u.
Date de intrare
În ³ierul numere.in se d pe prima linie n, iar pe urm toarele n linii elementele tabloului,
câte n elemente pe o linie, separate între ele prin câte un spaµiu, dup modic rile f cute de fratele
lui Mircea.
Date de ie³ire
În ³ierul numere.out se va scrie pe un singur rând cu un singur spaµiu între ele numerele
cerute (primul ind cel mai mic).
Restricµii ³i preciz ri
a 0 $ n & 500.
a Fratele lui Mircea schimb cel puµin un num r în ³ier.
a Numerele schimbate de fratele lui Mircea sunt mai mici sau cel mult egale cu 60000.
Exemplu
numere.in numere.out Explicaµie
3 24 În ³ierul de intrare au fost înlocuite cu 0
507 numerele 2, 3, 4.
001
698
Timp maxim de execuµie: 1 secund /test
Soluµia ocial
Se folose³te un vector cu componente 0 sau 1, x x1 , ..., xm , unde m este 64000 dac
2 2
num rul de componente al tabloului (n ) este mai mare decât 64000, respectiv m n în cel lalt
caz.
Iniµial vectorul x are toate componentele 0. Pe m sur ce se citesc numere v din ³ier, com-
ponentele corespunz toare din x se schimb în 1 (xv 1).
251
CAPITOLUL 16. OJI 2005 CLASA A IX-A 252
Dup citirea numerelor din ³ier se obµine în x o secvenµ de 0. Indicii corespunz tori acestei
secvenµe formeaz mulµimea de numere consecutive care au fost înlocuite cu 0 de fratele lui Mircea.
O alt modalitate de rezolvare const în calculul sumei tuturor numerelor din tablou ³i obµi-
nerea astfel a sumei secvenµei de numere consecutive ³terse de Mircea. Din p cate sumele sunt
prea mari ³i dep ³esc tipurile predenite. Dac se folosesc implement ri pe numere mari se obµine
punctajul maxim, altfel doar jum tate din punctaj.
Soluµie prezentat în GInfo nr. 15/3
Pentru rezolvarea acestei probleme este sucient s utiliz m un ³ir de biµi care vor indica dac
un num r apare sau nu în ³ier.
Vom avea nevoie întotdeauna de cel mult 250.000 de biµi, deci 31250 de octeµi.
Iniµial toµi biµii vor avea valoarea 0, iar pe m sur ce sunt citite numerele care formeaz
matricea, valoarea bitului corespunz tor unui num r citit devine 1.
irul de biµi va conµine în nal o secvenµ de zerouri care va reprezenta soluµia problemei.
Exist ³i posibilitatea de a utiliza heap-ul pentru a p stra 250.000 de valori booleene sau întregi
care vor permite ³i ele determinarea secvenµei care lipse³te.
16.2 MaxD
Maria ³i Adrian Niµ
Fiind elev în clasa a IX-a, George, î³i propune s studieze capitolul divizibilitate cât mai
bine. Ajungând la num rul de divizori asociat unui num natural, constat c sunt numere într-un
interval dat, cu acela³i num r de divizori.
De exemplu, în intervalul 1, 10, 6, 8 ³i 10 au acela³i num r de divizori, egal cu 4. De asemenea,
4 ³i 9 au acela³i num r de divizori, egal cu 3 etc.
Cerinµ
Scrieµi un program care pentru un interval dat determin care este cel mai mic num r din
interval ce are num r maxim de divizori. Dac sunt mai multe numere cu aceast proprietate se
cere s se numere câte sunt.
Date de intrare
Fi³ierul de intrare maxd.in conµine pe prima linie dou numere a ³i b separate prin spaµiu
(a & b) reprezentând extremit µile intervalului.
Date de ie³ire
Fi³ierul de ie³ire maxd.out va conµine pe prima linie trei numere separate prin câte un spaµiu
min nrdiv contor cu semnicaµia:
min = cea mai mic valoare din interval care are num r maxim de divizori
nrdiv = num rul de divizori ai lui min
contor = câte numere din intervalul citit mai au acela³i num r de divizori egal cu nrdiv
Restricµii ³i preciz ri
a 1 & a & b & 1.000.000.000
a 0 & b a & 10.000
Punctaj
Dac aµi determinat corect min, obµineµi 50% din punctaj.
Dac aµi determinat corect nrdiv , obµineµi 20% din punctaj
Dac aµi determinat corect contor, obµineµi 30% din punctaj.
Exemple
CAPITOLUL 16. OJI 2005 CLASA A IX-A 254
Varianta 1:
15 st.nextToken(); b=(int)st.nval;
16 x=new int[b-a+2];
17 for(i=a;i<=b;i++) x[i-a+1]=descfact(i);
18 int max=-1;
19 int imax=-1;
20 for(i=1;i<=b-a+1;i++)
21 if(x[i]>max) { max=x[i]; imax=i; }
22 int nrmax=0;
23 for(i=1;i<=b-a+1;i++) if(x[i]==max) nrmax++;
24
25 PrintWriter out=new PrintWriter(
26 new BufferedWriter(new FileWriter("maxd.out")));
27 out.println((imax+a-1)+" "+max+" "+nrmax);
28 out.close();
29 t2=System.currentTimeMillis();
30 System.out.println("Timp = "+(t2-t1));
31 }
32
33 static int descfact(int nr)
34 {
35 int d;
36 int nrd;
37 int p=1;
38
39 d=2;
40 nrd=0;
41 while(nr%d==0) { nrd++; nr=nr/d; }
42 p=p*(nrd+1);
43
44 d=3;
45 while(d*d<=nr)
46 {
47 nrd=0;
48 while(nr%d==0) { nrd++; nr=nr/d; }
49 p=p*(nrd+1);
50 d=d+2;
51 }
52 if(nr>1) p*=2;
53 return p;
54 }
55 }
Varianta 2:
17.1 Expresie
Se d un ³ir de n numere naturale nenule x1 , x2 , ..., xn ³i un num r natural m.
Cerinµ
Ó
S se verice dac valoarea expresiei m x1 ...xn exte un num r natural.
În caz armativ s se a³eze acest num r descompus în factori primi.
Date de intrare
În ³ierul exp.in se a pe prima linie m, pe linia a doua n, iar pe linia a treia numerele
x1 , x2 , ..., xn separate între ele prin câte un spaµiu.
Date de ie³ire
În ³ierul exp.out se va scrie pe prima linie cifra 0, dac valoarea expresiei nu este un num r
natural, respectiv 1 dac este un num r natural. Dac valoarea expresiei este un num r natural pe
urm toarele linii se vor scrie perechi de forma p e (p este factor prim care apare în descompunere
la puterea e ' 1). Aceste perechi se vor scrie în ordine cresc toare dup primul num r (adic p).
Restricµii ³i preciz ri
a n - num r natural nenul $ 5000
a xi - num r natural nenul $ 30000, i " 1, 2, ..., n
a m - poate una din cifrele 2, 3, 4
Exemple
exp.in exp.out exp.in exp.out
2 0 2 1
4 4 24
32 81 100 19 32 81 100 18 33
51
Timp maxim de execuµie: 1 secund /test
257
CAPITOLUL 17. OJI 2004 CLASA A IX-A 258
Dac toate elementele îndeplinesc aceast condiµie, expresia este un num r natural ³i se trece
la a³are.
Se poate renunµa la vectorul de 30000 de elemente, p strându-se în locul acestuia un vector
în care se memoreaz numerele prime mai mici decât 30000 ³i un vector care arat la ce puteri
apar aceste numere în descompunere. Aceast abordare introduce în plus operaµii pentru a g si
indicele unui anumit num r prim; se poate folosi cu succes c utarea binar . Pe de alt parte, la
descompunerea în factori primi se va testa numai împ rµirea prin numere prime.
Analiza complexit µii Ó
Descompunerea unui num r x în factori primi are ordinul de complexitate O x, dac nu se
folose³te lista de numere prime.
Ó Pasul de descompunere ³i completare a vectorului P are deci ordinul de complexitate O n
30000.
Citirea datelor, vericarea dac expresia este un num r natural ³i a³area au ordinul de com-
plexitate O n.
În concluzie, ordinul de complexitate
Ó al algoritmului de rezolvare a acestei probleme este O n,
dac facem abstracµie de constanta 30000.
49 end;
50 end;
51
52 begin
53 cit;
54 prime;
55
56 for i := 1 to dp do
57 f[i] := 0;
58 for i := 1 to n do
59 begin
60 j := 1;
61 while x[i]<>1 do
62 begin
63 while x[i] mod p[j]=0 do
64 begin
65 inc(f[j]);
66 x[i] := x[i] div p[j];
67 end;
68 inc(j);
69 end;
70 end;
71 sw := true;
72 for i := 1 to dp do
73 if f[i] mod m<>0 then
74 begin
75 sw := false;
76 break;
77 end;
78
79 assign(ff, ’exp.out’); rewrite(ff);
80 if not sw then
81 writeln(ff, 0)
82 else
83 begin
84 writeln(ff, 1);
85 for i := 1 to dp do
86 if f[i]>0 then
87 writeln(ff, p[i], ’ ’, f[i] div m);
88 end;
89 close(ff);
90 end.
Prima variant :
25 {
26 out.println(1);
27 for(i=2;i<30000;i++)
28 if(p[i]!=0) out.println(i+" "+p[i]);
29 }
30 out.close();
31 }
32
33 static void descfact(int nr)
34 {
35 int d=2;
36 while(nr%d==0)
37 {
38 p[d]++;
39 nr=nr/d;
40 }
41 d=3;
42 while(d<=nr)
43 {
44 while(nr%d==0) { p[d]++; nr=nr/d; }
45 d=d+2;
46 }
47 }
48 }
A doua variant :
48 }
49 ok=true;
50 for(i=1;i<=nnp;i++)
51 if(e[i]%m==0) e[i]=e[i]/m; else {ok=false; break;}
52 }
53
54 static void prime()
55 {
56 int i,j;
57 p[1]=2; p[2]=3; nnp=2;
58 i=5;
59 while(i<valmax)
60 {
61 if(estePrim(i)) p[++nnp]=i;
62 i+=2;
63 }
64 }
65
66 static boolean estePrim(int nr) // folosind lista numerelor prime !
67 {
68 int i=1;
69 while((p[i]*p[i]<nr)&&(nr%p[i]!=0)) i++;
70 if(p[i]*p[i]>nr) return true; return false;
71 }
72 }
A treia variant :
17.2 Reactivi
Într-un laborator de analize chimice se utilizeaz N reactivi.
CAPITOLUL 17. OJI 2004 CLASA A IX-A 263
Se ³tie c , pentru a evita accidentele sau deprecierea reactivilor, ace³tia trebuie s e stocaµi
în condiµii de mediu speciale. Mai exact, pentru ecare reactiv x, se precizeaz intervalul de
temperatur minx , maxx în care trebuie s se încadreze temperatura de stocare a acestuia.
Reactivii vor plasaµi în frigidere.
Orice frigider are un dispozitiv cu ajutorul c ruia putem stabili temperatura (constant ) care
va în interiorul acelui frigider (exprimat într-un num r întreg de grade Celsius).
Cerinµ
Scrieµi un program care s determine num rul minim de frigidere necesare pentru stocarea
reactivilor chimici.
Date de intrare
Fi³ierul de intrare react.in conµine:
pe prima linie num rul natural N , care reprezint num rul de reactivi;
pe ecare dintre urm toarele N linii se a min max (dou numere întregi separate printr-un
spaµiu); numerele de pe linia x 1 reprezint temperatura minim , respectiv temperatura maxim
de stocare a reactivului x.
Date de ie³ire
Fi³ierul de ie³ire react.out va conµine o singur linie pe care este scris num rul minim de
frigidere necesar.
Restricµii ³i preciz ri
a 1&N & 8000
a 100 & minx & maxx & 100 (numere întregi, reprezentând grade Celsius), pentru orice x de
la 1 la N
a un frigider poate conµine un num r nelimitat de reactivi
Exemple
react.in react.out react.in react.out react.in react.out
3 2 4 3 5 2
-10 10 25 -10 10
-25 57 10 12
20 50 10 20 -20 10
30 40 7 10
78
Timp maxim de execuµie: 1 secund /test
Facem o prim observaµie: pentru orice soluµie optim exist o soluµie cu acela³i num r de
puncte (frigidere), în care ecare punct s e sfâr³itul unui interval. Aceasta se poate obµine
mutând ecare punct spre dreapta, pân când ar ajunge la sfâr³itul intervalului care se termin
cel mai repede, dintre intervalele care îl conµin. Se observ c noua soluµie respect restricµiile din
enunµ.
În continuare ne vom concentra pe g sirea unei soluµii de acest tip.
Sort m reactivii dup sfâr³itul intervalului. Pentru intervalul care se termin cel mai repede,
alegem ultimul punct al s u ca temperatur a unui frigider. Se observ c aceast alegere este
cea mai bun , dintre toate alegerile unui punct în intervalul respectiv, în sensul c mulµimea
intervalelor care conµin punctul este mai mare (conform relaµiei de incluziune), decât mulµimea
corespunz toare oric rei alte alegeri. Acest fapt este adev rat, deoarece mutarea punctului mai la
stânga nu duce la selectarea unor noi intervale.
Intervalele care conµin punctul respectiv sunt eliminate (reactivii corespunz tori pot plasaµi
într-un frigider), iar procesul continu cu intervalele r mase, în acela³i mod.
Analiza complexit µii
CAPITOLUL 17. OJI 2004 CLASA A IX-A 264
Not m cu D num rul de temperaturi întregi din intervalul care conµine temperaturile din
enunµ. Se observ c D este cel mult 201.
Citirea datelor de intrare are ordinul de complexitate O N .
Sortarea intervalelor dup cap tul din dreapta are ordinul de complexitate O N logN .
Urmeaz F pa³i, unde F este num rul de frigidere selectate. Deoarece ecare frigider este
setat la o temperatur întreag , F & D.
În cadrul unui pas, determinarea intervalului care se termin cel mai repede, pe baza vectorului
sortat, are ordinul de complexitate O 1. Eliminarea intervalelor care conµin un anumit punct
(sfâr³itul intervalului care se termin cel mai repede) are ordinul de complexitate O N .
A³area rezultatului are ordinul de complexitate O 1.
În concluzie, ordinul de complexitate al algoritmului de rezolvare a acestei probleme este O N
D N logN ; deoarece în general D % logN , consider m ordinul de complexitate ca ind O N D.
66 char x, y;
67 Fisier=fopen("reactivi.in", "rt");
68 fscanf(Fisier, "%d", &N);
69 for (i=1; i<=N; i++)
70 fscanf(Fisier, "%d %d", &r[i].min, &r[i].max, &x, &y);
71 Ordoneaza(); //ordonez intervalele de temperatura
72 //crescator dupa temperatura minima si
73 //descrescator dupa temperatura maxima
74
75 //pun primul reactiv (deci cel cu intervalul cel mai mare)
76 //in primul frigider
77 f[1].min=r[1].min; f[1].max=r[1].max; Cate=1;
78 for (i=2; i<= N; i++) //pentru toate celelalte
79 {
80 min=r[i].min; max=r[i].max;
81 j=Cauta(min, max); //caut un frigider in care a mai fost pus ceva
82 if (j>0) //daca gasesc
83 Intersectie(j, min, max);//ajustez temperatura din frigider
84 else //altfel
85 {
86 Cate++; //"deschid" un frigider nou
87 f[Cate].min=min; //si pun aici reactivul
88 f[Cate].max=max;
89 }
90 }
91
92 fclose(Fisier);
93
94 Fisier=fopen("reactivi.out", "wt");
95 fprintf(Fisier, "%d\n", Cate);
96 fclose(Fisier);
97
98 return 0;
99 }
39 Else
40 If (f[i].min<=min) And (f[i].max>=max) Then
41 Begin Cauta := i; Break End
42 Else
43 If (f[i].max<min) Or (f[i].min>max) Then
44 Cauta := -1
45 End;
46 End;
47
48 Procedure Intersectie(j: Integer; min, max: ShortInt);
49 Begin
50 f[j].min := Maxim(min, f[j].min);
51 f[j].max := Minim(max, f[j].max)
52 End;
53
54 Procedure Ordoneaza;
55 Var i, j, ptmin: Integer;
56 tmax, tmin: ShortInt;
57 Begin
58 For i := 1 To N-1 Do
59 Begin
60 tmin := r[i].min; tmax := r[i].max; ptmin := i;
61 For j := i+1 To N Do
62 If r[j].min<tmin Then
63 Begin
64 tmax := r[j].max; tmin := r[j].min; ptmin := j
65 End
66 Else
67 If r[j].min=tmin Then
68 If r[j].max>tmax Then
69 Begin
70 tmax := r[j].max; tmin := r[j].min; ptmin := j
71 End;
72 r[ptmin].min := r[i].min; r[ptmin].max := r[i].max;
73 r[i].min := tmin; r[i].max := tmax
74 End
75 End;
76
77
78 Begin
79 Assign(Fisier, ’reactivi.in’); Reset(Fisier);
80 ReadLn(Fisier, N);
81 For i := 1 To N Do
82 ReadLn(Fisier, r[i].min, r[i].max);
83 Ordoneaza;
84 f[1].min := r[1].min; f[1].max := r[1].max; Cate := 1;
85 For i := 2 To N Do
86 Begin
87 min := r[i].min; max := r[i].max;
88 j := Cauta(min, max);
89 If j>0 Then
90 Intersectie(j, min, max)
91 Else
92 Begin
93 Inc(Cate);
94 f[Cate].min := min;
95 f[Cate].max := max
96 End
97 End;
98 Close(Fisier);
99 Assign(Fisier, ’reactivi.out’); ReWrite(Fisier);
100 WriteLn(Fisier, Cate);
101 Close(Fisier)
102 End.
18.1 Text
Vasile lucreaz intens la un editor de texte. Un text este format din unul sau mai multe
paragrafe. Orice paragraf se termin cu Enter ³i oricare dou cuvinte consecutive din acela³i
paragraf sunt separate prin spaµii (unul sau mai multe). În funcµie de modul de setare a paginii,
num rul maxim de caractere care încap în pagin pe o linie este unic determinat (Max).
Funcµia pe care Vasile trebuie s o implementeze acum este alinierea în pagin a ec rui
paragraf din text la stânga ³i la dreapta. Pentru aceasta el va trebui s împart ecare paragraf
în linii separate de lungime Max (ecare linie terminat cu Enter).
Împ rµirea se realizeaz punând num rul maxim posibil de cuvinte pe ecare linie, f r împ r-
µirea cuvintelor în silabe.
Pentru aliniere stânga-dreapta, Vasile trebuie s repartizeze spaµii în mod uniform între cu-
vintele de pe ecare linie, astfel încât ultimul caracter de pe linie s e diferit de spaµiu, iar
num rul total de caractere de pe linie s e egal cu Max. Excepµie face numai ultima linie din
paragraf, care r mâne aliniat la stânga (cuvintele ind separate printr-un singur spaµiu, chiar
dac linia nu este plin ).
În general, este puµin probabil ca alinierea s e realizabil prin plasarea aceluia³i num r de
spaµii între oricare dou cuvinte consecutive de pe linie. Vasile consider c este mai elegant ca,
dac între unele cuvinte consecutive trebuie plasat un spaµiu în plus faµ de alte perechi de cuvinte
consecutive, acestea s e plasate la începutul liniei.
Cerinµ
Scrieµi un program care s citeasc lungimea unei linii ³i textul dat ³i care s alinieze textul la
stânga ³i la dreapta.
Date de intrare
Fi³ierul de intrare text.in conµine pe prima linie Max, lungimea maxim a unui rând. Pe
urm toarele linii este scris textul.
Date de ie³ire
Fi³ierul de ie³ire text.out conµine textul aliniat stânga-dreapta.
Restricµii ³i preciz
uri
a 2 & Max & 1000.
a Lungimea maxim a oric rui cuvânt din text este 25 caractere ³i nu dep ³e³te Max.
a Lungimea unui paragraf nu dep ³e³te 1000 de caractere.
a Soluµia este unic .
Exemple
text.in text.out
20 Vasile are multe
Vasile are multe bomboane bune. bomboane bune.
Explicaµie
Pe prima linie au fost plasate câte 3 spaµii între cuvintele consecutive.
270
CAPITOLUL 18. OJI 2003 CLASA A IX-A 271
text.in text.out
20 Ana are mere.
Ana are mere. Ion are multe pere
Ion are multe pere galbene? galbene?
Explicaµie
Între Ion ³i are exist 2 spaµii, între are ³i multe - 2 spaµii, iar între multe ³i pere - 1 spaµiu.
Observaµi c paragraful Ana are mere. (care are lungimea mai mic decât 20) a r mas aliniat
la stânga, iar ultima linie din ecare paragraf r mâne aliniat la stânga, cuvintele consecutive
ind separate printr-un singur spaµiu.
Timp maxim de executare: 1 secund /test.
Fiecare paragraf se preia într-un vector de string-uri, elementele vectorului conµinând cuvintele
din paragraf. Se parcurge acest vector, începând cu prima poziµie, determinând cel mai mare
indice i1 care permite plasarea cuvintelor de pe poziµiile 1, ..., i1 pe acela³i rând. Se destribuie
spaµiile disponibile, conform cerinµei problemei ³i se a³eaz aceast linie. Se continu prelucrarea
vectorului începând cu poziµia i1 1, ³i a³a mai departe!
45 LgLinie=-1;
46 nrl=0;
47 p=strtok(prg," ");
48
49 while (p)
50 {
51 LgCuv=strlen(p);
52 if (LgLinie+LgCuv+1<=Max)
53 {
54 strcpy(cuv[nrl],p);
55 nrl++;
56 LgLinie+=LgCuv+1;
57 }
58 else
59 {
60 afiseaza_linie(0);
61 nrl=1;
62 LgLinie=LgCuv;
63 strcpy(cuv[0],p);
64 }
65
66 p=strtok(NULL," ");
67 }
68
69 afiseaza_linie(1);
70 }
71
72 void afiseaza_linie(int u)
73 {
74 int i, j, cate, rest, nrsp;
75
76 if (u)
77 for (i=0; i<nrl-1; i++)
78 fout<<cuv[i]<<’ ’;
79 else
80 {
81 cate=Max-LgLinie;
82 rest=cate%(nrl-1);
83 nrsp=cate/(nrl-1);
84
85 for (i=0; i<nrl-1;i++)
86 {
87 fout<<cuv[i];
88 for (j=0; j<=nrsp;j++)
89 fout<<’ ’;
90 if (rest)
91 {
92 fout<<’ ’;
93 rest--;
94 }
95 }
96 }
97
98 if (nrl>0)
99 fout<<cuv[nrl-1]<<endl;
100 else
101 fout<<endl;
102 }
21
E cerul sus
Ca niste-ntinse brate
N-au crengile de ce sa se agate
0000:0000 32 31 0D 0A 45 20 63 65 72 75 6C 20 73 75 73 0D
0000:0010 0A 43 61 20 6E 69 73 74 65 2D 6E 74 69 6E 73 65
0000:0020 20 62 72 61 74 65 0D 0A 4E 2D 61 75 20 63 72 65
0000:0030 6E 67 69 6C 65 20 64 65 20 63 65 20 73 61 20 73
0000:0040 65 20 61 67 61 74 65 0D 0A 1A
CAPITOLUL 18. OJI 2003 CLASA A IX-A 273
71 }
72 }
73
74 static void ultimulRand() throws IOException
75 {
76 int i;
77 out.print(s[cs]);
78 for(i=cs+1;i<=cd;i++) out.print(" "+s[i]);
79 out.println();
80 }
81 }
18.2 Numere
Gigel este un mare pasionat al cifrelor. Orice moment liber ³i-l petrece jucându-se cu numere.
Jucându-se astfel, într-o zi a scris pe hârtie 10 numere distincte de câte dou cifre ³i a observat
c printre acestea exist dou submulµimi disjuncte de sum egal .
Desigur, Gigel a crezut c este o întâmplare ³i a scris alte 10 numere distincte de câte dou
cifre ³i spre surpriza lui, dup un timp a g sit din nou dou submulµimi disjuncte de sum egal .
Cerinµ
Date 10 numere distincte de câte dou cifre, determinaµi num rul de perechi de submulµimi
disjuncte de sum egal care se pot forma cu numere din cele date, precum ³i una dintre aceste
perechi pentru care suma numerelor din ecare dintre cele dou submulµimi este maxim .
Date de intrare
Fi³ierul de intrare numere.in conµine pe prima linie 10 numere naturale distincte separate
prin câte un spaµiu x1 x2 ... x10 .
Date de ie³ire
Fi³ierul de ie³ire numere.out conµine trei linii. Pe prima linie se a num rul de perechi de
submulµimi de sum egal , precum ³i suma maxim obµinut , separate printr-un spaµiu. Pe linia
a doua se a elementele primei submulµimi, iar pe linia a treia se a elementele celei de a doua
submulµimi, separate prin câte un spaµiu.
NrSol Smax NrSol - num rul de perechi; Smax - suma maxim
x1 ... xk elementele primei submulµimi
y1 ... yp elementele celei de a doua submulµimi
Restricµii ³i preciz ri
a 10 & xi , yi & 99, pentru 1 & i & 10.
a 1 & k, p & 9.
a Ordinea submulµimilor în perechi nu conteaz .
a Perechea de submulµimi determinat nu este obligatoriu unic .
Exemplu
numere.in numere.out
60 49 86 78 23 97 69 71 32 10 130 276
78 97 69 32
60 49 86 71 10
Explicaµie:
130 de soluµii; suma maxim este 276; s-au folosit 9 din cele 10 numere; prima submulµime are
4 elemente, a doua are 5 elemente.
Timp maxim de executare: 1 secund /test
Num rul mic al numerelor (numai 10 numere distincte) permite generarea tuturor submulµi-
milor, vericarea condiµiilor din problem pentru ecare pereche de submulµimi ³i determinarea
informaµiilor cerute.
CAPITOLUL 18. OJI 2003 CLASA A IX-A 275
71 }
72 }
73 }
74 }
75
76 void afisare()
77 {
78 int i;
79
80 g<<solutii<<" "<<Smax<<endl;
81
82 for(i=1; i<=10; i++)
83 if (s1max[i])
84 g<<a[i]<<’ ’;
85 g<<endl;
86
87 for(i=1; i<=10; i++)
88 if (s2max[i])
89 g<<a[i]<<’ ’;
90 g<<endl;
91 g.close();
92 }
93
94 int main()
95 {
96 citire();
97 rezolva();
98 afisare();
99 return 0;
100 }
38 }// main
39
40 static int suma(int i)
41 {
42 int s=0,k=0;
43 for(k=0;k<=9;k++) if( (i&(1<<k)) != 0 ) s+=x[k];
44 return s;
45 }
46
47 static void afis(int i)
48 {
49 int k=0;
50 while(i!=0)
51 {
52 if(i%2!=0) out.print(x[k]+" ");
53 k++;
54 i/=2;
55 }
56 out.println();
57 }
58 }// class
Capitolul 19
19.1 Poarta
Se consider harta universului ca ind o matrice cu 250 de linii ³i 250 de coloane. În ecare
celul se g se³te o a³a numit poart stelar , iar în anumite celule se g sesc echipaje ale porµii
stelare.
La o deplasare, un echipaj se poate deplasa din locul în care se a în oricare alt loc în care
se g se³te o a doua poart , în cazul nostru în orice alt poziµie din matrice.
Nu se permite situarea simultan a mai mult de un echipaj într-o celul . La un moment dat
un singur echipaj se poate deplasa de la o poart stelar la alta.
Cerinµ
Dându-se un num r p (1 $ p $ 5000) de echipaje, pentru ecare echipaj ind precizate po-
ziµia iniµial ³i poziµia nal , determinaµi num rul minim de deplas ri necesare pentru ca toate
echipajele s ajung din poziµia iniµial în cea nal .
Datele de intrare
Se citesc din ³ierul text poarta.in în urm torul format:
pe prima linie num rul natural p reprezentând num rul de echipaje,
pe urm toarele p linii câte 4 numere naturale, primele dou reprezentând coordonatele
poziµiei iniµiale a unui echipaj (linie coloan ), urm toarele dou reprezentând coordonatele poziµiei
nale a aceluia³i echipaj (linie coloan ).
Datele de ie³ire
Pe prima linie a ³ierului text poarta.out se scrie un singur num r reprezentând num rul
minim de deplas ri necesar.
Restricµii ³i preciz ri
coordonatele poziµiilor iniµiale ³i nale ale echipajelor sunt numere naturale din intervalul
1, 250;
poziµiile iniµiale ale celor p echipaje sunt distincte dou câte dou ;
poziµiile nale ale celor p echipaje sunt distincte dou câte dou .
Exemplu
poarta.in poarta.out
3 4
1234
6539
3412
278
CAPITOLUL 19. OJI 2002 CLASA A IX-A 279
Fie NrStationare num rul echipajelor staµionare (care au poziµiile iniµiale ³i nale egale) ³i
NrCircuite num rul circuitelor grafului orientat format astfel: nodurile sunt echipajele ³i exist
arc de la echipajul i la echipajul j dac ³i numai dac poziµia nal a echipajului i coincide cu
poziµia iniµial a echipajului j .
Atunci NrMinDeplasari=p+NrCircuite-NrStationare.
19.2 Mouse
Un experiment urm re³te comportarea unui ³oricel pus într-o cutie dreptunghiular , împ rµit
în m n c m ruµe egale de form p trat . Fiecare c m ruµ conµine o anumit cantitate de hran .
oricelul trebuie s porneasc din colµul 1, 1 al cutiei ³i s ajung în colµul opus, mâncând cât
mai mult hran . El poate trece dintr-o camer în una al turat (dou camere sunt al turate dac
au un perete comun), m nânc toat hrana din c m ruµ atunci când intr ³i nu intr niciodat
într-o camer f r hran .
Cerinµ
Stabiliµi care este cantitatea maxim de hran pe care o poate mânca ³i traseul pe care îl poate
urma pentru a culege aceast cantitate maxim .
Datele de intrare
Fi³ierul de intrare mouse.in conµine pe prima linie dou numere m ³i n reprezentând num rul
de linii respectiv num rul de coloane ale cutiei, iar pe urm toarele m linii cele m n numere
reprezentând cantitatea de hran existent în ecare c m ruµ , câte n numere pe ecare linie,
separate prin spaµii. Toate valorile din ³ier sunt numere naturale între 1 ³i 100.
Datele de ie³ire
În ³ierul de ie³ire mouse.out se vor scrie
a pe prima linie dou numere separate printr-un spaµiu: num rul de c m ruµe vizitate ³i
cantitatea de hran maxim culeas ;
a pe urm toarele linii un traseu posibil pentru cantitatea dat , sub form de perechi de numere
(linie coloan ) începând cu 1 1 ³i terminând cu m n.
Exemplu
mouse.in mouse.out
24 7 21
1263 1 1
3412 2 1
2 2
1 2
1 3
1 4
2 4
Explicaµie
CAPITOLUL 19. OJI 2002 CLASA A IX-A 281
Dac m ³i n sunt pare atunci num rul de c m ruµe vizitate este mn 1 iar cantitatea de hran
maxim culeas este suma cantit µilor de hran din toate c m ruµele cu excepµia celei care are
cea mai mic cantitate ³i se a pe linia i ³i coloana j ³i i j este num r impar. Traseul este
determinat de o parcurgere pe vertical sau orizontal ³i ocolirea acelei c m ruµe.
Dac m este impar atunci num rul de c m ruµe vizitate este mn iar cantitatea de hran
maxim culeas este suma cantit µilor de hran din toate c m ruµele. Traseul este determinat de
o parcurgere pe orizontal .
Analog pentru situaµia în care n este impar.
36 i=1;
37 while(i+1<m)
38 {
39 for(j=1;j<=n;j++) out.println(i+" "+j);
40 i++;
41 for(j=n;j>=1;j--) out.println(i+" "+j);
42 i++;
43 }
44 for(j=1;j<=n;j++) out.println(m+" "+j);
45 }
46
47 static void nimpar()
48 {
49 int i,j;
50 j=1;
51 out.println(m*n+" "+s);
52 while(j+1<n)
53 {
54 for(i=1;i<=m;i++) out.println(i+" "+j);
55 j++;
56 for(i=m;i>=1;i--) out.println(i+" "+j);
57 j++;
58 }
59 for(i=1;i<=m;i++) out.println(i+" "+n);
60 }
61
62 static void mnpare()
63 {
64 int i,j;
65 imin=0;jmin=0;min=101;
66 for(i=1;i<=m;i++)
67 for(j=1;j<=n;j++)
68 if((i+j)%2==1)
69 if(a[i][j]<min) { min=a[i][j]; imin=i; jmin=j; }
70 out.println((m*n-1)+" "+(s-a[imin][jmin]));
71
72 j=1;
73 while(j+1<jmin) // stanga
74 {
75 for(i=1;i<=m;i++) out.println(i+" "+j);
76 j++;
77 for(i=m;i>=1;i--) out.println(i+" "+j);
78 j++;
79 }
80
81 i=1;
82 while(i+1<imin) // sus
83 {
84 out.println(i+" " +j);
85 out.println(i+" " +(j+1));
86 out.println((i+1)+" " +(j+1));
87 out.println((i+1)+" " +j);
88 i=i+2;
89 }
90
91 out.println(i+" "+j); // patratel
92 if((i==imin)&&(j+1==jmin)) out.println((i+1)+" " +j);
93 else out.println(i+" " +(j+1));
94 out.println((i+1)+" " +(j+1));
95
96 i=i+2;
97 while (i<m) // jos
98 {
99 out.println(i+" " +(j+1));
100 out.println(i+" " +j);
101 out.println((i+1)+" " +j);
102 out.println((i+1)+" " +(j+1));
103 i=i+2;
104 }
105
106 j=j+2;
107 while(j+1<=n) // dreapta
108 {
109 for(i=m;i>=1;i--) out.println(i+" "+j);
110 j++;
111 for(i=1;i<=m;i++) out.println(i+" "+j);
CAPITOLUL 19. OJI 2002 CLASA A IX-A 283
112 j++;
113 }
114 }
115 }//class
Partea II
284
Capitolul 20
ONI 2020
20.1 ***
Problema 1 - ... 100 de puncte
Cerinµe
Date de intrare
Date de ie³ire
Restricµii ³i preciz ri
Exemple:
20.2 ***
Problema 2 - ... 100 de puncte
Cerinµe
Date de intrare
Date de ie³ire
Restricµii ³i preciz ri
285
CAPITOLUL 20. ONI 2020 286
Exemple:
CAPITOLUL 20. ONI 2020 287
20.3 ***
Problema 3 - ... 100 de puncte
Cerinµe
Date de intrare
Date de ie³ire
Restricµii ³i preciz ri
Exemple:
20.4 ***
Problema 4 - ... 100 de puncte
Cerinµe
CAPITOLUL 20. ONI 2020 288
Date de intrare
Date de ie³ire
Restricµii ³i preciz ri
Exemple:
20.5 ***
Problema 5 - ... 100 de puncte
Cerinµe
Date de intrare
Date de ie³ire
Restricµii ³i preciz ri
Exemple:
20.6 ***
Problema 6 - ... 100 de puncte
Cerinµe
Date de intrare
Date de ie³ire
Restricµii ³i preciz ri
Exemple:
ONI 2019
21.1 amat
Problema 1 - amat 100 de puncte
Pasionat de informatic ³i de puzzle-uri, Dorel a construit o matrice A de dimensiunea N M
lipind mai multe piese dreptunghiulare de diferite dimensiuni. Fiecare pies este compus din
elemente de dimensiunea 1 1 ³i reµin o aceea³i valoare (vezi exemplele). Matricea rezultat nu
are spaµii libere, iar piesele din care este compus nu se suprapun. Nu exist dou piese cu aceea³i
valoare.
De³i iniµial p rea c acest design este unul inedit, nu a durat mult pân când Dorel s-a plictisit.
Astfel, acum el dore³te s upgradeze matricea construit . Dorel alege o submatrice delimitat
de coordonatele x1, y1 - colµul stânga-sus, x2, y2 - colµul dreapta-jos (1 & x1 & x2 & N ,
1 & y1 & y2 & M ), unde cre³te toate valorile elementelor submatricei cu valoarea V .
Dorel efectueaz în ordine Q operaµii de upgrade, operaµii numerotate de la 1 la Q. La
nalizarea celor Q operaµii de upgrade, toate elementele din matrice au valoarea mai mare sau
egal cu K . Dup o operaµie de upgrade, structura iniµial a matricei se modic .
Cerinµe
Cum priceperea lui Dorel este proverbial , trebuie s îl ajutaµi în rezolvarea urm toarelor
cerinµe:
1) determinarea coordonatelor piesei cu num r maxim de elemente înainte ca Dorel s efectueze
operaµiile de upgrade;
2) determinarea num rului minim de operaµii de upgrade dup care toate elementele matricei
au valoarea mai mare sau egal cu K .
Date de intrare
Datele de intrare se citesc din ³ierul amat.in, care are urm toarea structur :
a pe prima linie se a num rul natural C , care poate egal cu 1 sau 2, în funcµie de cerinµa
ce trebuie rezolvat ;
a pe linia urm toare se a dou numerele naturale N ³i M cu semnicaµia din enunµ;
a pe urm toarele N linii se g sesc elementele matricei A.
a dac C 2 atunci ³ierul de intrare mai conµine:
- pe linia N 2 numerele naturale Q K cu semnicaµiile din enunµ;
- pe urm toarele Q linii descrierea submatricelor asupra c rora se efectueaz operaµii de
upgrade de forma: x1 y1 x2 y2 V
Date de ie³ire
Datele de ie³ire se vor scrie în ³ierul amat.out, astfel:
Dac C 1 se vor scrie, separate prin spaµiu patru numere naturale nenule x1 y1 x2 y2 ce
reprezint coordonatele colµului stânga-sus, respectiv colµului dreapta-jos unde este plasat piesa
cu num r maxim de elemente înainte de upgrade. Dac exist mai multe astfel de piese, atunci
vor scrise coordonatele piesei pentru care coordonatele colµului stânga-sus are valoarea liniei cea
mai mare, iar la linii egale, se va alege piesa cu coordonata coloanei cea mai mare.
Dac C 2 se va scrie num rul natural nenul N R ce reprezint num rului minim de operaµii
de upgrade dup care toate elementele matricei au valoarea mai mare sau egal cu K .
290
CAPITOLUL 21. ONI 2019 291
Restricµii ³i preciz ri
a 2 & N, M & 1000; 1 & Q & 100000; 1 & V & 1000
a 1000 & elementele matricei A înainte de upgrade & 1000
a Operaµiile de upgrade se efectueaz obligatoriu în ordinea citirii
a Pentru teste în valoare de 30 de puncte, C 1
a Pentru teste în valoare de 30 de puncte, C 2 ³i N, M, Q & 250
a Pentru teste în valoare de 50 de puncte, C 2 ³i Q & 4000
a Pentru teste în valoare de 70 de puncte, C 2.
Exemple
28
29 for(int i = 1; i <= n; i++)
30 for(int j = 1; j <= m; j++)
31 fin >> init[i][j];
32
33 fin >> qq >> k;
34
35 for(int i = 1; i <= qq; i++)
36 fin >> q[i].x1 >> q[i].y1 >> q[i].x2 >> q[i].y2 >> q[i].val;
37
38 int st = 1;
39 int dr = qq;
40 int rasp = 0;
41 while(st <= dr)
42 {
43 int mij = (st + dr) / 2;
44 int ok = 1;
45 for(int i = 1; i <= mij; i++)
46 dp[q[i].x1][ q[i].y1 ] += q[i].val,
47 dp[q[i].x2 + 1][ q[i].y2 + 1] += q[i].val,
48 dp[q[i].x1][ q[i].y2 + 1 ] -= q[i].val,
49 dp[q[i].x2 + 1][ q[i].y1] -= q[i].val;
50
51 for(int i = 1; i <= n; i++)
52 for(int j = 1; j <= m; j++)
53 {
54 dp[i][j] += dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1];
55 if(dp[i][j] + init[i][j] < k)
56 ok = 0;
57 }
58
59 for(int i = 1; i <= n; i++)
60 for(int j = 1; j <= m; j++)
61 dp[i][j] = 0;
62
63 if(ok)
64 rasp = mij, dr = mij - 1;
65 else
66 st = mij + 1;
67 }
68
69 fout << rasp << ’\n’;
70 return 0;
71 }
50 if(init[i][j] < k)
51 ok = 0;
52 }
53
54 if(ok)
55 {
56 fout << mij << ’\n’;
57 return 0;
58 }
59 }
60
61 return 0;
62 }
60 }
61
62 return 0;
63 }
69 subAns.x2 = lin - 1;
70 subAns.y2 = col - 1;
71
72 maxCnt = cnt;
73 }
74 }
75 }
76
77 fout << subAns.x1 << ’ ’ << subAns.y1 << ’ ’ <<
78 subAns.x2 << ’ ’ << subAns.y2 << ’\n’;
79 }
80
81 int solve(int nrQ)
82 {
83 int val;
84 memset(aux, 0, sizeof(aux));
85
86 for (i = 1 ; i <= nrQ ; i++)
87 {
88 val = queries[i].v;
89 aux[queries[i].x1][queries[i].y1] += val;
90 aux[queries[i].x1][queries[i].y2 + 1] += -val;
91 aux[queries[i].x2 + 1][queries[i].y1] += -val;
92 aux[queries[i].x2 + 1][queries[i].y2 + 1] += val;
93 }
94
95 for (i = 1 ; i <= n ; i++)
96 for (j = 1 ; j <= m ; j++)
97 aux[i][j] += aux[i][j - 1];
98
99 for (j = 1 ; j <= m ; j++)
100 for (i = 1 ; i <= n ; i++)
101 aux[i][j] += aux[i - 1][j];
102
103 /**
104 cout << nrQ << ’\n’;
105 DEBUG_endmatrix();
106 cout << "-----------------\n";
107 */
108
109 for (i = 1 ; i <= n ; i++)
110 for (j = 1 ; j <= m ; j++)
111 if (aux[i][j] + mat[i][j] < k) return 0;
112
113 return 1;
114 }
115
116 void maintask()
117 {
118 int ls = 1, ld = q, mij, best = q;
119
120 while (ls <= ld)
121 {
122 mij = (ls + ld) / 2;
123
124 if (solve(mij))
125 {
126 best = mij;
127 ld = mij - 1;
128 }
129 else
130 {
131 ls = mij + 1;
132 }
133 }
134
135 fout << best;
136 }
137
138 int main()
139 {
140 fin >> c;
141 fin >> n >> m;
142
143 assert(c == 1 || c == 2);
144 assert(2 <= n && n <= NMAX);
CAPITOLUL 21. ONI 2019 300
111 {
112 adv = 0;
113 continue;
114 }
115
116 for (int i = 0; i < n; ++i)
117 {
118 for (int j = 0; j < m; ++j)
119 {
120 a[i][j] += mars[i][j];
121 }
122 }
123
124 sol += step;
125 }
126 }
127
128 assert(sol < q);
129 cout << sol + 1 << endl;
130 }
131
132 return 0;
133 }
50 cnt = 0;
51 for (lin = i ; lin <= n ; lin++)
52 {
53 if (mat[lin][j] != crt) break;
54 for (col = j ; col <= m ; col++)
55 {
56 if (mat[lin][col] != crt) break;
57 aux[lin][col] = 1;
58
59 cnt++;
60 }
61 }
62
63 if (cnt >= maxCnt)
64 {
65 subAns.x1 = i;
66 subAns.y1 = j;
67 subAns.x2 = lin - 1;
68 subAns.y2 = col - 1;
69
70 maxCnt = cnt;
71 }
72 }
73 }
74
75 fout << subAns.x1 << ’ ’ << subAns.y1 << ’ ’ <<
76 subAns.x2 << ’ ’ << subAns.y2 << ’\n’;
77 }
78
79 int solve(int nrQ)
80 {
81 int val;
82 memset(aux, 0, sizeof(aux));
83
84 for (i = 1 ; i <= nrQ ; i++)
85 {
86 val = queries[i].v;
87 aux[queries[i].x1][queries[i].y1] += val;
88 aux[queries[i].x1][queries[i].y2 + 1] += -val;
89 aux[queries[i].x2 + 1][queries[i].y1] += -val;
90 aux[queries[i].x2 + 1][queries[i].y2 + 1] += val;
91 }
92
93 for (i = 1 ; i <= n ; i++)
94 for (j = 1 ; j <= m ; j++)
95 aux[i][j] += aux[i][j - 1];
96
97 for (j = 1 ; j <= m ; j++)
98 for (i = 1 ; i <= n ; i++)
99 aux[i][j] += aux[i - 1][j];
100
101 /**
102 cout << nrQ << ’\n’;
103 DEBUG_endmatrix();
104 cout << "-----------------\n";
105 */
106
107 for (i = 1 ; i <= n ; i++)
108 for (j = 1 ; j <= m ; j++)
109 if (aux[i][j] + mat[i][j] < k) return 0;
110
111 return 1;
112 }
113
114 void maintask()
115 {
116 int ls = 1, ld = q, mij, best = q;
117 while (ls <= ld)
118 {
119 mij = (ls + ld) / 2;
120
121 if (solve(mij))
122 {
123 best = mij;
124 ld = mij - 1;
125 }
CAPITOLUL 21. ONI 2019 304
126 else
127 {
128 ls = mij + 1;
129 }
130 }
131
132 fout << best;
133 }
134
135 int main()
136 {
137 fin >> c;
138 fin >> n >> m;
139
140 assert(c == 1 || c == 2);
141 assert(2 <= n && n <= NMAX);
142 assert(2 <= m && m <= NMAX);
143
144 for (i = 1 ; i <= n ; i++)
145 for (j = 1 ; j <= m ; j++)
146 {
147 fin >> mat[i][j];
148
149 assert(VALMIN <= mat[i][j] && mat[i][j] <= 1000);
150 }
151
152 if (c == 1)
153 {
154 subtask();
155 }
156 else
157 {
158 fin >> q >> k;
159 assert(VALMIN <= k && k <= VALMAX);
160 assert(1 < q && q <= 100000);
161
162 for (i = 1 ; i <= q ; i++)
163 {
164 fin >> queries[i].x1 >> queries[i].y1 >>
165 queries[i].x2 >> queries[i].y2 >> queries[i].v;
166
167 assert(1 <= queries[i].x1 && queries[i].x1 <= n);
168 assert(1 <= queries[i].y1 && queries[i].y1 <= m);
169 assert(1 <= queries[i].x2 && queries[i].x2 <= n);
170 assert(1 <= queries[i].y2 && queries[i].y2 <= m);
171 assert(queries[i].x1 <= queries[i].x2 &&
172 queries[i].y1 <= queries[i].y2);
173 }
174
175 maintask();
176 }
177
178 return 0;
179 }
21.2 Comun
Problema 2 - Comun 100 de puncte
Tocmai ai primit un ³ir v de K numere naturale nenule distincte. Plecând de la acest ³ir, te-ai
gândit s construie³ti un ³ir w de N numere naturale distincte, astfel încât un num r x este în
³irul w dac ³i numai dac exista iniµial în ³irul v sau se pot alege cel puµin dou numere din ³irul
v astfel încât x este cel mai mare divizor comun al acelor numere.
De exemplu, dac v r4, 6, 7x atunci w r1, 2, 4, 6, 7x.
Uimit de propriet µile matematice frumoase ale noului ³ir w, ai uitat din p cate ³irul original
v de la care ai pornit.
CAPITOLUL 21. ONI 2019 305
Cerinµe
Dându-se ³irul w, s se g seasc un ³ir posibil iniµial v având un num r minim de elemente.
Date de intrare
Fi³ierul de intrare comun.in conµine pe prima linie un num r natural N . Pe cea de-a doua
linie se a N numere naturale nenule distincte, în ordine strict cresc toare, reprezentând
³irul w.
Date de ie³ire
Fi³ierul de ie³ire comun.out va conµine pe prima linie num rul minim K de elemente ale ³irului
v . Pe cea de-a doua linie se vor aa K numere naturale distincte, în ordine strict cresc toare,
reprezentând ³irul propriu-zis.
Restricµii ³i preciz ri
a Toate valorile din ³ierul de intrare sunt numere naturale nenule mai mici sau egale cu
100000.
a Pentru teste în valoare de 15 puncte, toate valorile din ³ierul de intrare sunt mai mici sau
egale cu 20.
a Pentru teste în valoare de 50 de puncte, toate valorile din ³ierul de intrare sunt mai mici
sau egale cu 2000.
a Se garanteaz c exist m car o soluµie.
a Dac exist mai multe ³iruri iniµiale cu num r minim de elemente, oricare este acceptat.
Exemple
comun.in comun.out Explicaµii
5 3 1 = cmmdc(6, 7) = cmmdc(4, 6, 7).
12467 467 2 = cmmdc(4, 6).
Se poate demonstra c orice alt ³ir cu proprietatea cerut are
m car 3 elemente.
4 4 Nu exist niciun ³ir de mai puµin de 4 elemente cu proprietatea
2 4 8 16 2 4 8 16 cerut .
Soluµie 15p
Exist o multitudine de soluµii care se încadreaz în aceste limite. în continuare va prezentat
una dintre posibilele soluµii.
O prim observaµie este c cel mai mare num r se reg se³te mereu în ³ir, deoarece nu se poate
obµine aplicând c.m.m.d.c. asupra altor numere. Mai mult, dac un num r din w este cel mai
mare divizor comun al altor numere din w, nu are sens s îl includem în soluµie, deoarece orice
num r pe care l-ar putea genera x îl putem genera, în schimb, cu numerele care îl genereaz .
Din aceste considerente, se poate deduce c soluµia de lungime minim este unic . Un algoritm
pentru a o calcula este urm torul: dac exist un num r x care este c.m.m.d.c. al altor numere
înc neeliminate, îl elimin m. Algoritmul se va opri atunci când nu se mai pot elimina numere.
N
O implementare naiv a acestui algoritm are complexitate O 2 N ³i ar trebui s obµin
minimum 15 puncte. în continuare vom optimiza algoritmul pentru a rula mai rapid.
Soluµie 50p
Observaµia cheie este c , în cadrul raµionamentului de mai sus, este sucient s consider m
doar perechi de câte dou numere.
CAPITOLUL 21. ONI 2019 306
Un algoritm este urm torul: pentru ecare pereche x, y de numere distincte din ³irul de
intrare, calcul m d cmmdc x, y ³i îl ³tergem din ³ir. ³tergerea se poate face folosind un vector
caracteristic.
2
O astfel de soluµie are complexitate O N log V (unde V este valoarea maxim din ³irul de
intrare) ³i ar trebui s obµin minimum 50 de puncte.
Soluµie 100p
O alt modalitate de a optimiza algoritmul menµionat anterior este c , pentru a ne decide
dac un num r trebuie eliminat sau nu, este de ajuns s calcul m cel mai mare divizor comun al
multiplilor s i din ³ir.
În acest caz, putem menµine ³irul într-un vector caracteristic ³i s veric m ecare num r
folosind un algoritm foarte asem n tor ciurului lui Eratostene.
2
Aceast soluµie, de³i la prima vedere are complexitate O N V log V , se poate demonstra
c complexitatea este de fapt O N V log V . Demonstraµia este l sat ca exerciµiu. O astfel
de soluµie ar trebui s obµin punctajul maxim.
Soluµie alternativ
Se poate demonstra c , în loc s consider m toµi multiplii unui num r x, putem considera doar
perechile de multipli în care unul dintre cele dou este cel mai mic multiplu al lui x din ³ir.
În acest caz, complexitatea soluµiei este tot O N V log V , din acelea³i considerente ca ³i
soluµia precedent .
36 }
37
38 if (g_c_d == i)
39 v[i] = 0, n--;
40 }
41
42 fout << n << ’\n’;
43 for (i = 1 ; i <= valmax ; i++)
44 {
45 if (v[i] == 1) fout << i << ’ ’;
46 }
47
48 return 0;
49 }
7 while (b)
8 {
9 int r = a % b;
10 a = b;
11 b = r;
12 }
13 return a;
14 }
15
16 int main()
17 {
18 ifstream cin("comun.in");
19 ofstream cout("comun.out");
20
21 int n; cin >> n;
22
23 vector<int> v(n);
24
25 int maxx = 0;
26 for (auto& x : v)
27 {
28 cin >> x;
29 maxx = max(maxx, x);
30 }
31
32 vector<bool> w(maxx + 1);
33 for (auto x : v)
34 w[x] = true;
35
36 for (int x = maxx; x >= 1; --x)
37 {
38 if (w[x] == false) continue;
39
40 for (int pos = 0; pos < (int)v.size(); ++pos)
41 {
42 int y = v[pos];
43 int gc = gcd(x, y);
44 if (gc < x && gc < y)
45 w[gc] = false;
46 }
47 }
48
49 v.clear();
50
51 for (int i = 1; i <= maxx; ++i)
52 if (w[i])
53 v.push_back(i);
54
55 cout << v.size() << endl;
56
57 for (auto x : v)
58 cout << x << " ";
59 cout << endl;
60
61 return 0;
62 }
29 if (all_gcd == i)
30 vals[i] = false;
31 }
32 return vals;
33 }
34
35 int main()
36 {
37 ifstream cin("comun.in");
38 ofstream cout("comun.out");
39
40 int n;
41 cin >> n;
42
43 vector<bool> v(100001, false);
44
45 for (int i = 0; i < n; ++i)
46 {
47 int x; cin >> x; v[x] = true;
48 }
49
50 v = Sparsify(v);
51 vector<int> out;
52
53 for (int i = 0; i < (int)v.size(); ++i)
54 if (v[i])
55 out.push_back(i);
56
57 cout << out.size() << endl;
58 for (auto x : out)
59 cout << x << " ";
60 cout << endl;
61
62 return 0;
63 }
38 ofstream cout("comun.out");
39
40 int n;
41 cin >> n;
42 vector<bool> v(100001, false);
43
44 for (int i = 0; i < n; ++i)
45 {
46 int x; cin >> x; v[x] = true;
47 }
48
49 v = Sparsify(v);
50 vector<int> out;
51 for (int i = 0; i < (int)v.size(); ++i)
52 if (v[i])
53 out.push_back(i);
54
55 cout << out.size() << endl;
56 for (auto x : out)
57 cout << x << " ";
58 cout << endl;
59
60 return 0;
61 }
21.3 pro3
Problema 3 - pro3 100 de puncte
Se consider 3 progresii aritmetice de numere naturale nenule.
Not m cu Pi , 1 & i & 3, mulµimile formate cu elementele progresiei i.
Fie P P1 < P2 < P3 reuniunea mulµimilor P1 , P2 , P3 .
Cerinµe
S se determine cardinalul mulµimii P .
Date de intrare
Fi³ierul de intrare pro3.in conµine 3 linii.
Pe linia i, 1 & i & 3 se vor g si câte 3 numere naturale ai , ri , ni , separate prin câte un spaµiu,
ce reprezint în aceast ordine primul termen, raµia ³i num rul de termeni ai progresiei P i.
Date de ie³ire
Fi³ierul de ie³ire pro3.out va conµine pe prima linie cardinalul mulµimii P .
Restricµii ³i preciz ri
Pentru teste în valoare de 40 puncte, 0 $ ai , ri & 10 ³i 0 $ ni & 10 , 1 & i & 3
2 6
a
Pentru teste în valoare de 72 puncte, 0 $ ai , ri & 10 ³i 0 $ ni & 10 , 1 & i & 3
2 9
a
Pentru teste în valoare de 100 puncte, 0 $ ai , ri & 10 ³i 0 $ ni & 10 , 1 & i & 3
6 9
a
Exemple
pro3.in pro3.out Explicaµii
2 2 10 24 Prima progresie are primul termen 2, raµia 2 ³i 10 termeni.
348 A doua progresie are primul termen 3, raµia 4 ³i 8 termeni.
1 3 12 A treia progresie are primul termen 1, raµia 3 ³i 12 termeni.
A³adar:
P1 r2, 4, 6, 8, 10, 12, 14, 16, 18, 20x
P2 r3, 7, 11, 15, 19, 23, 27, 31x
P3 r1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34x
Reuniunea termenilor celor trei progresii este mulµimea
P r1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 22, 23,
CAPITOLUL 21. ONI 2019 313
Soluµie 20p
Se poate utiliza un vector de frecvenµ pentru a determina dac un num r natural cuprins
între 1 ³i cel mai mare element dintre cele 3 progresii face parte din m car o progresie.
Soluµia necesit un spaµiu de memorie foarte mare ³i nu poate utilizat pentru valori mari ale
num rului de termeni ale unei progresii, dar va obµine aproximativ 20 30 de puncte, în funcµie
de diverse optimiz ri de memorie.
Soluµie 40p
Se poate realiza o interclasare concomitent a celor 3 ³iruri, f r a mai construi un vector cu
rezultatele reuniuni. La ecare pas al interclas rii se va determina elementul minim al celor trei
progresii ³i se va incrementa indicele corespunz tor.
Dup ce unul dintre cele 2 ³iruri se va âtermina se va testa care dintre ³iruri s-a terminat
³i se va acµiona asem n tor pe dou ³iruri apoi pe un singur ³ir.
Aceast soluµie are complexitate O n1 n2 n3 ³i ar trebui s obµin minimum 40 de puncte.
Soluµie 72p
Observaµia cheie este c elementele comune a dou sau mai multe progresii aritmetice, dac
exist , formeaz tot o progresie aritmetic .
Astfel, observ m c este mai u³or ³i mai ecient s calcul m elementele comune a dou /trei
progresii ³i s folosim principiul includerii ³i excluderii pentru a calcula r spunsul.
Deoarece în acest caz termenii iniµiali ³i raµiile progresiilor sunt cel mult egale cu 100, se pot
g si primii doi termeni ai progresiei comune (³i, implicit, raµia acesteia), vericând pe rând valori
candidat, în ordine cresc toare. Dac exist termeni comuni, se poate demonstra c primul dintre
ei ³i raµia nu pot dep ³i 2 1003.
3 3
Aceast soluµie are complexitate O r1 r2 r3 a1 a2 a3 ³i ar trebui s obµin
minimum 72 de puncte.
Soluµie 100p
în soluµia anterioar ne-am bazat pe faptul c primul termen ³i raµia progresiei comune a dou
progresii a1 Xr1 ³i a2 Xr2 sunt mai mici sau egale cu a1 r1 a2 r2 . în loc s veric m
ecare candidat pe rând, vom itera doar prin elementele progresiei 1. Astfel, num rul de pa³i este
O a1 r1 a2 r2 © a1 r1 O a2 r2 . Este esenµial c aceast complexitate nu depinde
de parametrii progresiei 1, astfel c intersecµia celor trei progresii se poate calcula intersectând
progresiv progresia 1 cu progresia 2 ³i rezultatul cu progresia 3.
Complexitatea acestei soluµii este O r1 r2 r3 a1 a2 a3 ³i ar trebui s obµin 100 de
puncte.
16 while(r)
17 {
18 x = y;
19 y = r;
20 r = x%y;
21 }
22 return y;
23 }
24
25 long long inter2(int x, int y)
26 {
27 long long maxi = min(a[x] + (n[x] - 1) * r[x], a[y] + (n[y] - 1) * r[y]);
28 for(int i = 0; i < 1000000; i++)
29 {
30 long long termen = a[x] + i * r[x];
31 if(termen > maxi)
32 return 0;
33 if( (termen - a[y]) % r[y] == 0 && termen >= a[y])
34 {
35 return (maxi - termen) / (r[x] * r[y] / gcd(r[y], r[x])) + 1;
36 }
37 }
38 return 0;
39 }
40
41 long long inter3()
42 {
43 long long maxi = min(a[1] + (n[1] - 1) * r[1], a[2] + (n[2] - 1) * r[2]);
44 long long termen;
45 long long ratie = r[1] * r[2] / gcd(r[1], r[2]);
46 int i;
47
48 for(i = 0; i < 1000000; i++)
49 {
50 termen = a[1] + i * r[1];
51 if(termen > maxi)
52 return 0;
53 if( (termen - a[2]) % r[2] == 0 )
54 {
55 break;
56 }
57 }
58
59 maxi = min(maxi, a[3] + (n[3] - 1) * r[3]);
60
61 if(termen > maxi || i == 1000000)
62 return 0;
63
64 for(i = 0; i < 1000000; i++)
65 {
66 if(i)
67 termen += ratie;
68 if(termen > maxi)
69 return 0;
70 if( (termen - a[3]) % r[3] == 0 )
71 {
72 return (maxi - termen) / (ratie * r[3] / gcd(r[3], ratie)) + 1;
73 }
74 }
75
76 return 0;
77 }
78
79 int main()
80 {
81 for(int i = 1; i <= 3; i++)
82 fin >> a[i] >> r[i] >> n[i];
83 fout << n[1] + n[2] + n[3] - inter2(1, 2) - inter2(1, 3) -
84 inter2(2, 3) + inter3() << ’\n’;
85
86 return 0;
87 }
37
38 d=cmmdc(x.r,y.r);
39 t = (y.a - y.r) - (x.a - x.r);
40 if (t%d==0) // ecuatia are solutii
41 {
42 //determin primul element comun celor doua siruri
43 i=1;j=1;x0=0;
44 while (i<=x.n && j<=y.n)
45 {
46 if (x.a+x.r*(i-1) < y.a+y.r*(j-1)) i++;
47 if (x.a+x.r*(i-1) > y.a+y.r*(j-1)) j++;
48 if (x.a+x.r*(i-1) == y.a+y.r*(j-1)) {x0 = i; break;}
49 }
50
51 if (x0 == 0) {z.a = 0; z.r = 0; z.n = 0;}
52 else
53 {
54 z.a = x.a + x.r*(x0 - 1);
55 z.r = (x.r*y.r)/d;
56
57 x.an=x.a+x.r*(x.n-1);
58 y.an=y.a+y.r*(y.n-1);
59
60 if (x.an < y.an)
61 z.n = (x.an - z.a)/z.r + 1;
62 else
63 z.n = (y.an - z.a)/z.r + 1;
64
65 z.an = z.a + z.r*(z.n - 1);
66 }
67 }
68 else // ecuatia nu are solutii
69 {z.a = 0;z.r = 0;z.n = 0;}
70
71 return z;
72 }
73
74 int32_t main()
75 {
76 ifstream f("pro3.in");
77 ofstream g("pro3.out");
78
79 pro x,y,z,xy,xz,yz,xyz;
80
81 f >> x.a >> x.r >> x.n;
82 f >> y.a >> y.r >> y.n;
83 f >> z.a >> z.r >> z.n;
84
85 xy = progresie(x,y);
86 xz = progresie(x,z);
87 yz = progresie(y,z);
88 xyz = progresie(xy,z);
89
90 // aplic PINEX
91 g << x.n + y.n + z.n - xy.n - xz.n - yz.n + xyz.n;
92
93 f.close();
94 g.close();
95
96 return 0;
97 }
21.4 Cub
Problema 4 - Cub 100 de puncte
Ionel are de rezolvat o nou problem . El trebuie s construiasc un ³ir de N numere naturale.
Numerele din ³ir pot avea ca divizori primi doar numere prime de o cifr . Dup construirea ³irului,
Ionel a constatat c exist subsecvenµe în ³ir pentru care produsul elementelor este cubul unui
num r natural.
Cerinµe
Ionel vrea s determine num rul subsecvenµelor din ³irul construit care au produsul elementelor
o valoare ce este cubul unui num r natural.
Date de intrare
Fi³ierul de intrare cub.in va conµine pe prima linie num rul natural N , iar pe linia urm toare
se vor aa N numere naturale separate prin câte un spaµiu, elementele ³irului construit de Ionel.
Date de ie³ire
Fi³ierul de ie³ire cub.out va conµine pe prima linie un num r natural reprezentând num rul
subsecvenµelor din ³irul construit care au produsul elementelor egal cu o valoare ce este cubul unui
num r natural.
Restricµii ³i preciz ri
a N ³i elemente ³irului sunt numere naturale din intervalul 2, 1000000
a Prin subsecvenµ a unui ³ir se înµelege o succesiune de unul sau mai mulµi termeni din ³ir
aaµi pe poziµii consecutive.
a Pentru teste în valoare de 20 de puncte, N & 1000.
a Pentru teste în valoare de 40 de puncte, N & 10000.
Exemple
cub.in cub.out Explicaµii
8 6 Sunt 6 subsecvenµe în ³ir cu produsul elementelor egal cu o va-
15 3 5 15 7 63 21 125 loare care este cubul unui num r natural:
15 3 5 15
7 63 21
125
15 3 5 15 7 63 21
7 63 21 125
15 3 5 15 7 63 21 125
19 {
20 fin >> n;
21 for (i = 1 ; i <= n ; i++)
22 {
23 fin >> x;
24
25 for (j = 0 ; j < 4 ; j++)
26 {
27 nr = 0;
28 while (x % divs[j] == 0)
29 {
30 nr++;
31 x /= divs[j];
32 crtState[j]++;
33 }
34
35 crtState[j] %= 3;
36 }
37
38 v[i] = convert();
39 }
40
41 for (i = 0 ; i < n ; i++)
42 for (j = i + 1 ; j <= n ; j++)
43 if (v[i] == v[j])
44 sol++;
45
46 fout << sol;
47
48 return 0;
49 }
46 }
47
48 r--;
49 //g<<"i2="<<i<<" i3="<<j<<" i5="<<k<<" i7="<<r<<"\n"; //19 12 8 7
50 // calculez numerele mai mici decat 1000000 ce sunt divizibile
51 // doar cu 2, 3 ,5 sau 7
52 for(i1=0;i1<=i;i1++)
53 for(j1=0;j1<=j;j1++)
54 for(k1=0;k1<=k;k1++)
55 for(r1=0;r1<=r;r1++)
56 {
57 p=d[i1]*t[j1]*c[k1]*s[r1];
58 if(p<=1000000)
59 {
60 ex2[p]=i1;
61 ex3[p]=j1;
62 ex5[p]=k1;
63 ex7[p]=r1;
64 //w++;
65 }
66 }
67
68 //g<<"nr numere ="<<w<<"\n";// 1273
69 // citesc numerele si formez exponentii cumulati
70 // ai lui 2, 3 ,5 si 7
71 e2=0;e3=0;e5=0;e7=0;
72 f>>n;
73 for(i=1;i<=n;i++)
74 f>>v[i];
75 for(i=1;i<=n;i++)
76 {
77 x=v[i]; ;
78 e2=(e2+ex2[x])%3;
79 e3=(e3+ex3[x])%3;
80 e5=(e5+ex5[x])%3;
81 e7=(e7+ex7[x])%3;
82 cod=e2*27+e3*9+e5*3+e7;//scriu in baza 3
83 viz[cod]++;
84 }
85
86 sol=viz[0];
87 for(i=0;i<=80;i++)
88 sol=sol+viz[i]*(viz[i]-1)/2;
89
90 g<<sol<<’\n’ ;
91 g.close();
92 return 0;
93 }
25 t[0]=1;
26 j=0;
27 while(t[j]<=1000000)
28 {
29 j++;
30 t[j]=t[j-1]*3;
31 }
32
33 j--;
34 c[0]=1;
35 k=0;
36 while(c[k]<=1000000)
37 {
38 k++;
39 c[k]=c[k-1]*5;
40 }
41
42 k--;
43 s[0]=1;
44 r=0;
45 while(s[r]<=1000000)
46 {
47 r++;
48 s[r]=s[r-1]*7;
49 }
50 r--;
51 //g<<"i2="<<i<<" i3="<<j<<" i5="<<k<<" i7="<<r<<"\n"; //19 12 8 7
52 // calculez numerele mai mici decat 1000000 ce sunt divizibile
53 // doar cu 2, 3 ,5 sau 7
54 for(i1=0;i1<=i;i1++)
55 for(j1=0;j1<=j;j1++)
56 for(k1=0;k1<=k;k1++)
57 for(r1=0;r1<=r;r1++)
58 {
59 p=1ll*d[i1]*t[j1]*c[k1]*s[r1];
60 if(p<=1000000)
61 {
62 ex2[p]=i1;
63 ex3[p]=j1;
64 ex5[p]=k1;
65 ex7[p]=r1;
66 //w++;
67 }
68 }
69 //g<<"nr numere ="<<w<<"\n";// 1273
70 // citesc numerele si formez exponentii cumulati
71 // ai lui 2, 3 ,5 si 7
72
73 e2=0; e3=0; e5=0; e7=0;
74 f>>n;
75 for(i=1;i<=n;i++)
76 f>>v[i];
77
78 for(i=1;i<=n;i++)
79 {
80 x=v[i]; ;
81 e2=(e2+ex2[x])%3;
82 e3=(e3+ex3[x])%3;
83 e5=(e5+ex5[x])%3;
84 e7=(e7+ex7[x])%3;
85 cod=e2*27+e3*9+e5*3+e7;//scriu in baza 3
86 viz[cod]++;
87 }
88
89 sol=viz[0];
90 for(i=0;i<=80;i++)
91 sol=sol+viz[i]*(viz[i]-1)/2;
92
93 g<<sol<<’\n’ ;
94 g.close();
95 return 0;
96 }
CAPITOLUL 21. ONI 2019 326
21.5 bofrac
Problema 5 - bofrac 100de puncte
Fie ³irul Fibonacci dat prin F1 1, F2 1 ³i relaµia de recurenµ Fk Fk1 Fk2 , k ' 3.
Se consider un num r natural N .
Cerinµe
S se scrie un program care determin num rul F al fracµiilor diferite ireductibile subunitare,
ce se pot forma utilizând primii N termeni ai ³irului Fibonacci.
Date de intrare
Fi³ierul de intrare bofrac.in conµine pe prima linie num rul N .
Date de ie³ire
Fi³ierul de ie³ire bofrac.out va conµine pe prima linie num rul F ,cu semnicaµia de mai sus.
Restricµii ³i preciz ri
a Pentru teste în valoare de 24 puncte, 0 $ N $ 80
a Pentru teste în valoare de 40 puncte, 0 $ N $ 1101
a Pentru teste în valoare de 56 puncte, 0 $ N $ 50001
a Pentru teste în valoare de 100 puncte, 0 $ N $ 1000000
a Dou fracµii ireductibile a©b ³i c©d sunt diferite dac a j c sau b j d.
0&F $2
63
a
Exemple
bofrac.in bofrac.out Explicaµii
7 14 N=7; Primii 7 termeni ai ³irului Fibonacci sunt: 1, 1, 2, 3, 5, 8,
13 Se pot forma 14 fracµii diferite ireductibile subunitare:
, , , , 1 , 2, 2, 2 , 3, 3, 3 , 5, 5 , 8 .
1 1 1 1
2 3 5 8 13 3 5 13 5 8 13 8 13 13
2019 1547722 Se pot forma 1547722 fracµii diferite ireductibile subunitare uti-
lizând primii 2019 termeni ai ³irului Fibonacci.
500000 94988288219 Se pot forma 94988288219 fracµii diferite ireductibile subunitare
utilizând primii 500000 termeni ai ³irului Fibonacci.
Soluµia 1
Gener m termenii ³irului Fibonacci ³i form m toate perechile posibile F a©F b cu F a $ F b.
Pentru ecare pereche calcul m F a, F b ³i contoriz m pentru acele perechi care au (Fa, Fb) = 1.
Deoarece termenii ³irului Fibonacci cresc repede se obµin erori pentru N % 80. Soluµia are ordin de
2
complexitate O n ³i obµine aproximativ 24 puncte. Pentru obµinerea unor puncte suplimentare
s-ar putea lucra cu numere mari.
Soluµia 2
Dac o fracµie F a©F b este ireductibil atunci F a, F b este 1. Se cunoa³te îns c F a, F b =
F a, b. Cum F a, F b trebuie s e 1, rezult c F a, b poate F 1 sau F 2, pentru c F 1 1
CAPITOLUL 21. ONI 2019 327
3
4 #include <fstream>
5 #define nmax 1000003
6
7 using namespace std;
8
9 int n,i,j;
10
11 long long T=0;
12 int fi[nmax];
13
14 ifstream f("fibofrac.in");
15 ofstream g("fibofrac.out");
16
17 int main()
18 {
19
20 f>>n;
21
22 // calculez fi(i)
23 for (i=1;i<=n;i++)
24 fi[i] = i-1;
25
26 fi[1]=1;
27 for (i=2;i<=n;i++)
28 for (j=i+i;j<=n;j+=i)
29 fi[j] -= fi[i];
30
31 for(i=1;i<=n/2;i++)
32 T+=2*fi[i];
33
34 for(i=n/2+1;i<=n;i++)
35 T+=fi[i];
36
37 g<<T - (n-2) - 3<<"\n";
38
39 f.close();
40 g.close();
41
42 return 0;
43 }
32
33 f.close();
34 g.close();
35
36 return 0;
37 }
67 {
68 fi[i]=i;
69 desc(i);
70 for(j=1;j<=nf;j++)
71 {
72 fi[i]=fi[i]/b[j];
73 fi[i]=fi[i]*(b[j]-1);
74 }
75 }
76
77 for(i=1;i<=n/2;i++)
78 T+=2*fi[i];
79
80 for(i=n/2+1;i<=n;i++)
81 T+=fi[i];
82
83 g<<T - (n-2) - 3<<"\n";
84
85 f.close();
86 g.close();
87
88 return 0;
89 }
2 // 100 puncte
3
4 #include <bits/stdc++.h>
5 using namespace std;
6
7 #define NMAX 1000005
8
9 ifstream fin("fibofrac.in");
10 ofstream fout("fibofrac.out");
11
12 int phi[NMAX], n, i, j;
13 long long ans;
14
15 int main()
16 {
17 fin >> n;
18 for (int i = 1; i <= n; ++i)
19 phi[i] = i-1;
20 for (int i = 2; i <= n; ++i)
21 for (int j = 2 * i; j <= n; j += i)
22 phi[j] -= phi[i];
23
24 for (i = 1 ; i <= n ; i++)
25 ans += ((i <= (n / 2)) ? 2 : 1 ) * phi[i];
26
27 ans -= n - 1;
28
29 fout << ans;
30
31 return 0;
32 }
21.6 telefon
Problema 6 - telefon 100 de puncte
Dorel, plictisit de puzzle-ul pe care l-a upgradat ieri, a decis s mearg afar cu ceilalµi copii.
El îi prive³te pe cei N copii cum joac âtelefonul f r r.
Jocul decurge în felul urm tor:
- Iniµial, copiii se a³az pe axa Ox, copilul i la distanµa Xi metri faµ de origine.
- Copilul cel mai aproape de origine alege un cuvânt secret ³i îl transmite celui din dreapta lui;
cel din dreapta lui îl transmite urm torului ³i a³a mai departe pân se ajunge la ultimul copil.
Pentru a transmite cuvântul, ecare copil trebuie s mearg pân la copilul din dreapta lui.
Toµi copiii se deplaseaz cu viteza constant de 1 metru/secund .
Cu toate acestea, pentru a evita deplasarea ecare copil dispune de un dispozitiv de tip walkie-
talkie ce permite transmiterea unui cuvânt mai departe. Toate staµiile walkie-talkie au o raz de
acµiune R, setat la începutul unei runde de joc (exprimat în metri) ce nu poate modicat
pe parcursul jocului. Staµiile sunt conectate la aceea³i surs de alimentare care are B unit µi de
energie.
în funcµie de raza de acµiune setat , copiii pot sau nu s foloseasc sistemul walkie-talkie pentru
a nu se mai deplasa. Mai exact, dac un copil ar trebui s parcurg o distanµ mai mic sau egal
cu R ca s transmit cuvântul celui din dreapta sa ³i bateria sursei are cel puµin R unit µi de
energie r mase, acesta poate folosi sistemul walkie-talkie ca s transmit instantaneu cuvântul
secret, iar bateria se va desc rca cu R unit µi de energie. Cu toate acestea, chiar ³i cu sistemul
walkie-talkie, un copil nu are voie s transmit mesajul decât primului copil situat în dreapta lui.
Copiii doresc ca jocul s se termine cât mai repede, a³a c vor seta o raz de acµiune convenabil
³i vor alege s foloseasc sau nu sistemul walkie-talkie, pentru a minimiza timpul necesar ca toµi
cei N copii s ae cuvântul secret.
Dorel dore³te s se al ture jocului, a³a c în a doua parte a jocului va intra ³i el în rând. Dorel
se va a³eza pe axa Ox, undeva între primul ³i ultimul copil, la o anumit distanµ de origine unde
nu se a un alt copil.
Cerinµe
CAPITOLUL 21. ONI 2019 332
Date de intrare
Fi³ierul de intrare telefon.in conµine pe prima linie dou numere naturale N ³i B cu semni-
caµia din enunµ. Pe cea de-a doua linie se a N numere naturale nenule distincte Xi , în ordine
strict cresc toare, unde Xi reprezint distanµa copilului i faµ de origine, 1 & i & N .
Date de ie³ire
Fi³ierul de ie³ire telefon.out va conµine dou numere naturale C1 C2, separate printr-un
spaµiu, unde C1 reprezint r spunsul la cerinµa 1 iar C2 r spunsul la cerinµa 2.
Restricµii ³i preciz ri
a 2N 105
a 1B109, 1Xi109
a Se garanteaz c Dorel are cel puµin o poziµie liber pe care se poate a³eza
a Un copil poate alege între a se deplasa sau a folosi walkie-talkie pentru a transmite un mesaj
a Copiii pot seta o noua raz de acµiune a walkie-talkie când Dorel intr în joc
a Pentru prima cerinµ se acord 40 puncte
a Pentru a doua cerinµ se acord 60 puncte
a Pentru teste în valoare de 15 puncte N, B & 10
2
Exemple
telefon.in telefon.out Explicaµii
6 15 86 N=6, B=15
7 9 12 16 21 27 X[1-6]=[7,9,12,16,21,27]
Pentru a rezolva cerinµa 1 e sucient s consider m c R poate lua valori doar din mulµimea
distanµelor dintre oricare 2 copii.
CAPITOLUL 21. ONI 2019 333
Pentru a rezolva a 2-a cerinµ trebuie s observ m c R poate s nu aparµin din mulµimea
distanµelor dintre oricare 2 copii. De asemenea, trebuie s îl a³ez m pe Dorel astfel încât s
spargem o distanµ în dou buc µi. Mai exact, noi am vrea o distanµ X mai mare decât R (raza
noastra curent ) pe care s o âsp rgem în 2 buc µi, de lungimi R respectiv X R. Mereu
vom folosi distanµa de lungime R dar dac ne uit m mai atent observ m ca exist cazuri în care
am dori s folosim ³i o bucat de lungime X R a³a c vom c uta cea mai mare distanµa X cu
proprietatea c X & 2R (pentru a maximiza X R). Pentru a nu c uta liniar acest X putem
menµine un pointer în faµ .
Soluµie - 15 puncte
Se observ c pentru o valoare xat a lui R strategia optim este s lu m cele mai mari
distanµe mai mici sau egale cu R. Astfel, prima dat vom calcula distanµele între oricare 2 copii
consecutivi ³i le vom sorta cresc tor. Având acest vector sortat, pentru ecare valoare a lui R în
intervalul 1, B c ut m cea mai mare distanµ mai mic sau egal cu R ³i vom verica cât de
mult ne putem extinde în stânga acestei distanµe (în limita bateriei) pentru a minimiza cât mai
mult durata jocului.
2
Aceast soluµie are complexitate O N B
Soluµie - 50 puncte
Pentru a optimiza soluµia anterioar observ m c pentru o valoare xat a lui R este sucient
o singur parcurge a vectorului de distanµe folosind 2 pointeri. Pointerul din dreapta ne spune cea
mai mare distanµ mai mic sau egal cu R iar pointerul din stânga cat de mult ne putem extinde.
De ecare dat când incrementam pointerul din dreapta vom verica dac dap ³im limita bateriei,
caz în care vom incrementa ³i pointerul din stânga.
Complexitate: O N B
Soluµie - 70 puncte
Optimizând în continuare algoritmul, observ m c nu trebuie s iteram prin toate valorile pe
care le poate lua R. În schimb, vom începe cu R 1 ³i vom incrementa R în funcµie de distanµa
maxim pe care o consider m la momentul actual(pointerul din dreapta).
Pentru a 2-a cerinta este necesar sa testam toate valorile pe care le poate lua R si nu doar din
multimea distantelor.
Complexitate: O N log N B
Soluµie - 100 puncte
Continuând soluµia anterioar , algoritmul optim nu va lua în considerare
pentru R toate valorile din intervalul 1, B ci doar valorile din mulµimea
r1, 2, 3, 4, 5, ...., sqrt B , B, B ©2, B ©3, B ©4, B ©5, .., B ©sqrt B x. Astfel reducând cardinalul
mulµimii de valori pentru R de la B la 2 sqrt B .
Complexitate: O N log N sqrt B
Soluµie alternativ - 100 puncte
O mic optimizare a soluµiei anterioare const în observaµia c nu sunt necesare decât cei mai
mari N candidaµi dintre cei 2sqrt B (în esenµ , B , B ©2, B ©3, ..., B ©N ). Astfel se obµine o soluµie
de complexitate O N log N , independent de B .
16 ofstream cout("telefon.out");
17
18 cin >> n >> m;
19 for(int i = 1; i <= n; i++)
20 {
21 int a;
22 cin >> a;
23 v.push_back(a);
24 }
25
26 for(int i = 0; i < v.size() - 1; i++)
27 {
28 dist.push_back(v[i + 1] - v[i]);
29 vals.push_back(v[i + 1] - v[i]);
30 total += v[i + 1] - v[i];
31 }
32
33 sort(dist.begin(), dist.end());
34
35 int i;
36 for(i = 1; i*i <= m; i++)
37 vals.push_back(i),vals.push_back(m/i);
38
39 vals.push_back(i), vals.push_back(i + 1);
40
41 sort(vals.begin(), vals.end());
42
43 int first = 0;
44 int semnal = 0;
45 int second = 0;
46 int extra = 0;
47 current = dist[0];
48
49 while(first < dist.size())
50 {
51 while(semnal + 1 < vals.size() && vals[semnal] < dist[first])
52 semnal++;
53
54 if(vals[semnal] < dist[first])
55 break;
56
57 long long delta = vals[semnal];
58
59 while((first - second + 1) * delta > m)
60 current -= dist[second], second++;
61
62 while(extra+1 < dist.size() && dist[extra+1] - delta <= delta)
63 extra++;
64
65 if(extra == first && extra + 1 < dist.size())
66 extra++;
67
68 int aux = second;
69 long long size = (first-second+1) * delta;
70 if(extra != first)
71 {
72 long long z = current;
73 long long plus = dist[extra] - delta;
74
75 if(size + delta <= m)
76 size += delta, z += delta;
77 else
78 if(aux <= first)
79 z += delta - dist[aux], aux++;
80
81 if(size + delta <= m)
82 size += plus, z += delta;
83 else
84 if(aux <= first && dist[aux] < plus)
85 z += plus - dist[aux];
86
87 best = max(z, best);
88 }
89
90 nokid = max(current, nokid);
91 best = max(current, best);
CAPITOLUL 21. ONI 2019 335
92 if(first + 1 == dist.size())
93 first++;
94 else
95 if(semnal+1 < vals.size() && vals[semnal+1] < dist[first+1])
96 semnal++;
97 else
98 first++,current+= dist[first];
99 }
100
101 long long z = 0;
102 cout<<max(z,total-nokid) << ’ ’;
103 cout<<max(z,total-best) << ’\n’;
104 }
19 if (!opts.count("cands_are_dists"))
20 {
21 cands.clear();
22 for (int i = 1; i <= magic && i <= v; ++i)
23 {
24 cands.push_back(i);
25 cands.push_back(v / i);
26 }
27
28 sort(cands.rbegin(), cands.rend());
29
30 for (auto& x : cands)
31 x = v / x;
32 }
33 else
34 {
35 for (auto x : dists)
36 if (x > 1)
37 cands.push_back(x / 2);
38
39 sort(cands.begin(), cands.end());
40 }
41
42 vector<long long> bests(3, 0);
43
44 long long now = 0;
45 int l = 0, r = 0, p = -1;
46
47 for (auto delta : cands)
48 {
49 // bests[0] = bests[1] = bests[2] = 0;
50
51 int phones = v / delta;
52 while (r < n && dists[r] <= delta)
53 {
54 now += dists[r];
55 ++r;
56 }
57
58 while (r - l > phones)
59 {
60 now -= dists[l];
61 ++l;
62 }
63
64 bests[0] = max(bests[0], now);
65 if (phones >= 1 && r < n)
66 {
67 long long xnow = now + delta;
68 if (r - l == phones) xnow -= dists[l];
69 bests[1] = max(bests[1], xnow);
70 }
71
72 while (p + 1 < n && dists[p + 1] <= 2 * delta)
73 ++p;
74
75 if (phones >= 2 && p >= r)
76 {
77 long long xnow = now + dists[p];
78 if (r - l >= phones - 1) xnow -= dists[l];
79 if (r - l == phones) xnow -= dists[l + 1];
80 bests[2] = max(bests[2], xnow);
81 }
82
83 /*
84 for (auto x : dists) cerr << x << " "; cerr << endl;
85 cerr << "delta: " << delta << endl;
86 cerr << "(phones: " << phones << ")" << endl;
87 cerr << "bests: " << bests[0] << " " << bests[1]
88 << " " << bests[2] << endl;
89 cerr << endl;
90 */
91 }
92
93 long long ans = 0;
94
CAPITOLUL 21. ONI 2019 338
44 bonus[0] = bonus[1] = 0;
45 if (split > 0 && ld != d.size())
46 {
47 bonus[0] = min(signals[k], d[split - 1]);
48 bonus[1] = max(d[split - 1] - signals[k], 0LL);
49 if (bonus[1] > signalSize) bonus[1] = 0;
50 }
51
52 saved = 0;
53 int spaceLeft = b / signalSize - (ld - ls);
54 if (spaceLeft <= 0)
55 {
56 for (int r = ls ; r < ld ; r++)
57 {
58 if (r - ls == 0 || r - ls == 1)
59 saved += (bonus[r - ls] > d[r] ? bonus[r - ls] : d[r]);
60 else
61 saved += d[r];
62 }
63 }
64 else if (spaceLeft == 1)
65 {
66 for (int r = ls ; r < ld ; r++)
67 {
68 if (r - ls == 0)
69 saved += (bonus[1] > d[r] ? bonus[1] : d[r]);
70 else
71 saved += d[r];
72 }
73
74 saved += bonus[0];
75 }
76 else
77 {
78 for (int r = ls ; r < ld ; r++)
79 saved += d[r];
80
81 saved += bonus[0] + bonus[1];
82 }
83
84 best = max(best, saved);
85 }
86
87 fout << total - best;
88 }
89
90 int32_t main()
91 {
92 fin >> n >> b;
93 fin >> x;
94
95 for (i = 2 ; i <= n ; i++)
96 {
97 fin >> y;
98 d.push_back(y - x);
99 total += y - x;
100
101 x = y;
102 }
103
104 sort(d.begin(), d.end());
105 for (i = 0 ; i < d.size() ; i++)
106 {
107 cout << d[i] << ’ ’;
108 }
109
110 for (i = 1 ; i <= sqrt(b) ; i++)
111 signals.push_back(i);
112
113 for (i = int32_t(sqrt(b)) ; i >= 1 ; i--)
114 signals.push_back(b / i);
115
116 subtask();
117 solve();
118
119 return 0;
CAPITOLUL 21. ONI 2019 340
120 }
ONI 2018
22.1 bazaf
Problema 1 - bazaf 100 de puncte
În matematic factorialul unui num r natural nenul K este notat cu K! ³i este egal cu produsul
numerelor naturale nenule mai mici sau egale cu K .
Exemple: 1! 1; 2! 1 2 2; 3! 1 2 3 6, ... , K! 1 2 3 ... K .
Orice num r natural N poate descompus cu ajutorul numerelor factoriale astfel:
Cerinµe
1. S se determine descompunerea în baz factorial a unui num r natural X dat.
2. Cunoscând o descompunere oarecare a unui num r natural Y s se determine descompunerea
în baz factorial a acestuia.
Date de intrare
Fi³ierul de intrare este bazaf.in
Acesta conµine pe primul rând un num r natural V care poate avea doar valorile 1 sau 2 cu
urm toarea semnicaµie:
a dac valoarea lui V este 1, pe a doua linie a ³ierului de intrare se g se³te un num r natural
X cu semnicaµia de mai sus;
a dac valoarea lui V este 2, pe a doua linie a ³ierului de intrare se g se³te o descompunere
a unui num r Y sub forma unui ³ir de valori naturale în care primul termen este m, urmat de m
valori fi , care respect condiµiile fi ' 0, cu 1 & i $ m ³i fm j 0, desp rµite prin câte un spaµiu, cu
semnicaµia de mai sus
Date de ie³ire
Fi³ierul de ie³ire este bazaf.out
Dac valoarea V este 1 atunci ³ierul de ie³ire va conµine descompunerea în baza factorial a
num rului X iar dac valoarea V este 2 atunci ³ierul de ie³ire va conµine descompunerea în baza
factorial a num rului Y .
Descompunerea în baz factorial presupune scrierea în ³ierul de ie³ire a unei singure linii
sub forma unui ³ir de valori naturale în care primul termen este m, urmat de m valori fi , care
respect condiµiile 0 & fi & i, cu 1 & i $ m ³i 0 $ fm & m, desp rµite prin câte un spaµiu, având
semnicaµia de mai sus.
Restricµii ³i preciz ri
341
CAPITOLUL 22. ONI 2018 342
2 & X & 10
15
a
a 1 $ m & 100 000
a 0 & fi & 10
9
a Pentru rezolvarea corect a primei cerinµ se va acorda 30% din punctaj, iar pentru cea de-a
doua cerinµ se va acorda 70% din punctaj.
Exemple:
bazaf.in bazaf.out Explicaµii
1 3122 V 1, deci se rezolv doar prima cerinµ
17 X 17
Descompunerea num rului X 17 în baz factorial conµine 3
termeni ³i este format din coecienµii 1, 2, 2 (17 = 1! 1 + 2!
2 + 3! 2);
2 2 10 5 3013 V 2, deci se rezolv doar a doua cerinµ
Descompunerea 2 10 5 este o descompunere cu 2 termeni având
coecienµii 10, 5 ³i corespunde num rului Y 20.
Descompunerea în baz factorial a num rului
Y = 20 va 3 0 1 3 (20 = 1! 0 + 2! 1 + 3! 3)
Timp maxim de executare/test: 0.8 secunde
Memorie: total 128 MB din care pentru stiv 32 MB
Dimensiune maxim a sursei: 10 KB
Pentru rezolvarea primei cerinµe se construie³te un vector cu toate valorile lui k! pentru k & 20
apoi printr-o strategie Greedy se determin care este cel mai apropiat factorial mai mic decât
num rul dat, se calculeaz coecientul acelui termen, se scade din num rul dat termenul respectiv,
se memoreaz în vectorul de descompuneri coecientul calculat ³i se reia operaµia pân când
num rul curent devine 0.
Pentru rezolvarea celei de-a doua cerinµe se observ înc de la început c o soluµie care s
calculeze num rul Y ³i apoi s determine descompunerea în baz factorial folosind ideea de la
cerinµa anterioar nu poate obµine puncte deoarece descompunerea dat are un num r foarte mare
de termeni ³i corespunde unui num r Y foarte mare.
Soluµia const într-o observaµie matematic ³i anume c se poate parcurge vectorul descom-
punerii ³i dac un coecient este mai mare decât limita impus vom calcula cât din valoarea
respectiv va transportat c tre urm torul coecient.
Se actualizeaz astfel atât coecientul curent cât ³i cel urm tor ³i în cazul c nd ultimul coe-
cient este mai mare decât limita impus se adaug noi coecienµi.
O astfel de soluµie nu presupune calcularea num rului asociat descompunerii.
Exemplu: Pentru descompunerea 4 7 12 14 9 se trece prin urm toarele etape
4 7 12 14 9 (7 1! = 1 + 3 2!)
4 1 15 14 9 (15 2! = 0 + 5 3!)
4 1 0 19 9 (19 3! = 3 + 4 4!)
4 1 0 3 13 (13 4! = 3 + 2 5!) s-a mai ad ugat un termen
5 1 0 3 3 2
4 #include<algorithm>
5 #include<vector>
6 #include<cassert>
7
8 using namespace std;
9
10 #define NMAX 100005
11
12 long long n;
13 int v[NMAX], p;
14
15 void findBazaFactoriala(long long n)
16 {
17 long long fact = 1, k;
18 for(k = 1; ; k++)
19 {
20 if(fact * (k + 1) > n)
21 break;
22 fact *= (k + 1);
23 }
24
25 vector<int> answer;
26
27 for(; k >= 1; k--)
28 {
29 answer.push_back(n / fact);
30 n %= fact;
31 fact /= k;
32 }
33
34 int lim = answer.size();
35 printf("%d ", lim);
36
37 for(int i = lim - 1; i >= 0; i--)
38 printf("%d ", answer[i]);
39 printf("\n");
40 }
41
42 void solve1()
43 {
44 scanf("%lld",&n);
45 assert(1 <= n && n <= 1LL * 1000000000000000);
46 findBazaFactoriala(n);
47 }
48
49 void solve2()
50 {
51 scanf("%lld",&n);
52 assert(1 <= n && n <= 100000);
53 for(int i = 1; i <= n; i++)
54 {
55 assert(0 <= v[i] && v[i] <= 1000000000);
56 scanf("%d",&v[i]);
57 }
58
59 for(long long i = 1; i <= n || v[i] > 0; i++)
60 {
61 v[i + 1] += v[i] / (i + 1);
62 v[i] %= (i + 1);
63 n = max(n, i);
64 }
65
66 printf("%lld ", n);
67 for(int i = 1; i <= n; i++)
68 {
69 printf("%d ", v[i]);
70 }
71 printf("\n");
72 }
73
74 int main ()
75 {
76 freopen("bazaf.in","r",stdin);
77 freopen("bazaf.out","w",stdout);
78
79 scanf("%d", &p);
CAPITOLUL 22. ONI 2018 344
61 fi[i+1]+=c;
62 }
63
64 while (fi[m]>m)
65 {
66 c=fi[m]/(m+1);
67 r=fi[m]%(m+1);
68 fi[m]=r;
69 fi[++m]+=c;
70 }
71
72 fout << m <<" ";
73 for(i=1;i<=m;i++)
74 fout << fi[i]<<" ";
75 fout << "\n";
76 }
77
78 fout.close();
79 fin.close();
80 return 0;
81 }
46 if (p==2)
47 {
48 fin >> m;
49 long long s=0;
50 for(i=1;i<=m;i++)
51 {
52 fin >> fi[i];
53 s+=fi[i]*f[i];
54 }
55
56 v=s;
57 nx=0;
58 for(int j=20;j>=1;j--)
59 {
60 x[j]=v/f[j];
61 if(x[j]>0 && nx==0)
62 {
63 nx=j;
64 }
65 v=v%f[j];
66 }
67 fout<<nx;
68
69 for(int j=1;j<=nx;j++)
70 {
71 fout<<" "<<x[j];
72 }
73
74 fout << "\n";
75 }
76
77 fout.close();
78 fin.close();
79 return 0;
80 }
22.2 mexitate
Problema 2 - mexitate 100 de puncte
Se d o matrice A cu N linii ³i M coloane cu elemente numere naturale nu neap rat distincte.
Pentru o submatrice denim mex-ul acesteia ca ind cea mai mic valoare natural nenul care
nu apare în aceasta.
Cerinµe
S se calculeze produsul mex-urilor tuturor submatricelor având K linii ³i L coloane ale matricei
A.
Date de intrare
Fi³ierul mexitate.in conµine pe prima linie patru numere naturale N , M , K ³i L separate
printr-un spaµiu cu semnicaµia din enunµ.
Pe ecare dintre urm toarele N linii se a câte M numere naturale nenule, desp rµite prin
câte un spaµiu, reprezentând valorile matricei.
Date de ie³ire
Fi³ierul mexitate.out va conµine un singur num r natural reprezentând produsul mex-urilor
tuturor submatricelor având K linii ³i L coloane ale matricei modulo 1 000 000 007.
Restricµii ³i preciz ri
CAPITOLUL 22. ONI 2018 348
Exemple:
mexitate.in mexitate.out Explicaµii
3 4 2 3 400 N = 3 ³i M = 4
1 2 3 2 K = 2 ³i L = 3
2 3 1 4 Submatricile cu 2 linii ³i 3 coloane sunt:
1 1 2 6
1 2 3 cu mex-ul 4
231
2 3 2 cu mex-ul 5
314
2 3 1 cu mex-ul 4
112
3 1 4 cu mex-ul 5
126
Soluµie 20 de puncte:
Pentru ecare submatrice de K * L, se parcurg elementele ³i se pun într-un vector de frecvenµ .
Pentru a determina r spunsul (primul element lips ), este sucient s parcurgem vectorul de
frecvent si s a m prima poziµie cu frecvenµa 0.
Observ m c mutarea la stânga-dreapta o facem de ordinul O(N * M), iar mutarea în jos
de ordinul O(N). Complexitatea pân în acest punct devine O(N * M * K + N * L), ignorând
momentan partea în care trebuie s determin m rapid mex-ul din vectorul de frecvenµ .
2. Avem restrictia N * M <= 400.000
=> K * L <= 400.000
=> min(K, L) <= sqrt(400.000)
Daca K <= L
=> k <= sqrt(400.000) = sqrt(VMAX)
=> complexitatea devine O(N * M * sqrt(VMAX) + N * L)
În schimb, dac K > L este nevoie s rotim matricea ³i s aplic m acela³i procedeu, comple-
xitatea devenind O(N * M * L + M * K), adic O(N * M * sqrt(VMAX) + M * K).
Aplicând acest hibrid, complexitatea devine O(min(N * M * sqrt(VMAX) + N * L, N * M
*sqrt(VMAX) + M * K)). Din moment ce N * L respectiv M * K sunt irelevante, complexitatea
nal va : O(N * M * sqrt(VMAX)).
3. R mâne de v zut cum putem determina rapid care este mex-ul cu ajutorul vectorului de
frecvenµ (din moment ce acesta este foarte mare, nu putem merge element cu element).
Aplicând primele 2 observaµii, deducem c avem O(N * M * sqrt(VMAX)) valori care se
modic (update-uri), respectiv O(N * M) interog ri de mex (query-uri).
Putem echilibra aceast complexitate dac am avea o structur ce foloseste O(1) pe update ³i
O(sqrt(VMAX)) pe query. Putem µine buc µi de dimensiune sqrt(VMAX) pe vectorul de frec-
venµ , ecare bucat având marcat câte elemente apar cel puµin o dat . Vectorul de frecvenµ
³i informaµia pentru ecare bucat de radical se pot menµine u³or la update în O(1). La query,
pentru ecare bucat de radical putem s o s rim dac toate elementele apar în acel interval,
respectiv s aplicam un brute-force dac r spunsul este în interiorul acelui interval. Mai exact, s -
rim elemente din radical în radical (vom face asta de maxim sqrt(VMAX) ori), respectiv c utam
element cu element intr-un interval de lungime radical. Astfel, vom putea determina valoarea
mex-ului în maxim sqrt(VMAX) pa³i.
31 }
32 }
33
34 void addElements(int a, int b, int c, int d)
35 {
36 for(int i = a; i <= c; i++)
37 for(int j = b; j <= d; j++)
38 {
39 int value = matrix[i][j];
40 f[value]++;
41 if(f[value] == 1)
42 fb[indexB[value]]++;
43 }
44 }
45
46 void query()
47 {
48 for(int buc = 1; ; buc++)
49 {
50 if(fb[buc] == bucket)
51 continue;
52 for(int i = (buc - 1) * bucket + 1; ; i++)
53 {
54 if(!f[i])
55 {
56 answer *= i;
57 ans += i;
58 if(answer >= MOD)
59 answer %= MOD;
60 break;
61 }
62 }
63 break;
64 }
65 }
66
67 void initializeaza()
68 {
69 addElements(1,1,k,l);
70 query();
71 }
72
73 int main ()
74 {
75 int value, sign;
76
77 srand(time(0));
78
79 freopen("mexitate.in","r",stdin);
80 freopen("mexitate.out","w",stdout);
81
82 scanf("%d%d%d%d",&n,&m,&k,&l);
83
84 for(int i = 1; i <= n; i++)
85 {
86 matrix2[i].push_back(0);
87 for(int j = 1; j <= m; j++)
88 {
89 scanf("%d",&value);
90 matrix2[i].push_back(value);
91 }
92 }
93 if(k > l)
94 { // linia devine coloana // m linia 1 m - 1 2
95 for(int i = 1; i <= m; i++)
96 for(int j = 0; j <= n; j++)
97 matrix[i].push_back(0);
98
99 for(int i = 1; i <= n; i++)
100 for(int j = 1; j <= m; j++)
101 matrix[m - j + 1][i] = matrix2[i][j];
102
103 int aux = n;
104 n = m;
105 m = aux;
106
CAPITOLUL 22. ONI 2018 351
107 aux = l;
108 l = k;
109 k = aux;
110 }
111 else
112 {
113 for(int i = 1; i <= n; i++)
114 {
115 matrix[i].push_back(0);
116 for(int j = 1; j <= m; j++)
117 {
118 matrix[i].push_back(matrix2[i][j]);
119 }
120 }
121 }
122
123 int last = 1;
124 for(int i = 1; i <= n * m; i++)
125 {
126 indexB[i] = last;
127 if(i % bucket == 0)
128 last++;
129 }
130
131 initializeaza();
132 for(int i = 1; i <= n - k + 1; i++)
133 {
134 sign = ((i&1) ? +1 : -1);
135 if(sign == 1)
136 {
137 for(int j = 2; j <= m - l + 1; j++)
138 {
139 deleteElements(i, j - 1, i + k - 1, j - 1);
140 addElements(i, j + l - 1, i + k - 1, j + l - 1);
141 query();
142 }
143
144 if(i <= n - k)
145 {
146 deleteElements(i, m - l + 1, i, m);
147 addElements(i + k, m - l + 1, i + k, m);
148 query();
149 }
150 }
151 else
152 {
153 for(int j = m - l; j >= 1; j--)
154 {
155 deleteElements(i, j + l, i + k - 1, j + l);
156 addElements(i, j, i + k - 1, j);
157 query();
158 }
159
160 if(i <= n - k)
161 {
162 deleteElements(i, 1, i, l);
163 addElements(i + k, 1, i + k, l);
164 query();
165 }
166 }
167 }
168
169 printf("%lld\n", answer);
170
171 return 0;
172 }
7 #include <cassert>
8
9 using namespace std;
10
11 const int MOD = 1000000007;
12
13 void Update(vector<int>&frecv, vector<int>&buckets, int bucket, int i, int val)
14 {
15 if (frecv[i] == 0)
16 buckets[i/bucket]++;
17 frecv[i] += val;
18 if (frecv[i] == 0)
19 buckets[i/bucket]--;
20 }
21
22 int Query(vector<int>&frecv,vector<int>&buckets, int bucket)
23 {
24 int i;
25 for(i = 0; buckets[i] == bucket; i++);
26 for(i = bucket*i;frecv[i] != 0; i++);
27 return i;
28 }
29
30 int main()
31 {
32 freopen("mexitate.in", "r", stdin);
33 freopen("mexitate.out", "w", stdout);
34
35 int n, m, k, l;
36
37 cin >> n >> m >> k >> l;
38 assert(1 <= n*m && n*m <= 400000);
39
40 vector<vector<int>>a(n, vector<int>(m,0));
41 vector<int>frecv(n * m + 5), buckets(n * m + 5);
42
43 int bucket = 1;
44 for(;bucket*bucket < n*m ;bucket++);
45
46 Update(frecv, buckets, bucket, 0, 1);
47
48 for(auto&line: a)
49 for(auto &elem: line)
50 {
51 cin >> elem;
52 assert(1 <= elem && elem <= n * m);
53 }
54
55 if(k > l)
56 {
57 vector<vector<int>> b = a;
58
59 swap(n, m);
60 swap(k, l);
61
62 a = vector<vector<int>>(n, vector<int>(m,0));
63
64 for (int i = 0; i < n; i++)
65 for (int j = 0; j < m; j++)
66 a[i][j] = b[j][i];
67 }
68
69 for(int i = 0; i < k; i++)
70 {
71 for (int j = 0;j < l;j ++)
72 {
73 Update(frecv, buckets, bucket, a[i][j], 1);
74 }
75 }
76
77 const int left[] = {0, m - 1};
78 const int right[] = {m, -1};
79 long long sol = 1;
80
81 auto mat = vector<vector<int>>(n, vector<int>(m,0));
82
CAPITOLUL 22. ONI 2018 353
22.3 plaja
Problema 3 - plaja 100 de puncte
Zizi î³i va petrece concediul în aceast var într-o frumoas staµiune de la Marea Neagr . Acolo
va sta N zile. Zilele sunt numerotate de la 1 la N . În ecare dintre cele N zile de concediu, ea
intenµioneaz s fac plaj un num r cât mai mare de unit µi de timp. Va trebui s µin seama
totu³i de prognoza meteo, care este nefavorabil în K dintre cele N zile, respectiv în zilele z1 , z2 ,
..., zk . În ecare dintre aceste K zile va ploua sau va prea mult soare, iar Zizi va trebui s -³i
limiteze timpii de plaj la cel mult t1 , t2 , ..., tk unit µi de timp.
Deasemenea, din motive de confort zic, Zizi dore³te ca diferenµa în valoare absolut a timpilor
de plaj între oricare dou zile consecutive s nu dep ³easc T .
Cerinµe
Cunoscând zilele z1 , z2 , ..., zk în care exist limit rile t1 , t2 , ..., tk pentru timpul de plaj ³i
valoarea T , s se determine num rul maxim de unit µi de timp pe care Zizi le poate petrece la
plaj într-o singur zi dintre cele N zile de concediu.
Date de intrare
Fi³ierul plaja.in conµine pe prima linie trei numere naturale N K ³i T separate printr-un
spaµiu, reprezentând num rul de zile de concediu, num rul de zile în care exist limit ri pentru
timpul de plaj ³i diferenµa maxim admis a timpilor de plaj pentru oricare dou zile consecutive.
CAPITOLUL 22. ONI 2018 354
Pe ecare dintre urm toarele K linii se a câte dou numere z ³i t, desp rµite printr-un spaµiu,
reprezentând num rul de ordine al unei zile cu limit ri pentru timpul de plaj , respectiv limita
de timp pentru ziua respectiv .
Valorile z1 , z2 , ..., zk sunt în ordine strict cresc toare.
Date de ie³ire
Fi³ierul plaja.out va conµine pe prima linie un singur num r natural tmax, reprezentând
num rul maxim de unit µi de timp pe care Zizi le poate petrece f când plaj într-una din cele N
zile de concediu.
Restricµii ³i preciz ri
a 1 & N & 1 000 000 000
a 1 & K & 100 000
a 1 & t1 , t2 , ..., tk & 100 000
a 1 & z1 $ z2 $ ... $ zk & N
a 2 & T & 1 000 000
a Pentru 20% din punctajul total exist teste cu 1 & N, K & 1 000
a Pentru 65% din punctajul total exist teste cu 1 & N, K & 100 000
Exemple:
plaja.in plaja.out Explicaµii
313 8 În ziua 1 timpul de plaj este limitat la 2 unit µi de timp. În
12 ziua a doua timpul maxim de plaj este 2 + 3, iar în ziua a
treia, timpul maxim este 2 + 3 + 3 = 8 unit µi de timp.
5 2 11 16 În ziua 2 timpul de plaj este limitat la 2 unit µi de timp, iar în
22 zilele 1 ³i 3 nu exist limitare. Atunci timpul maxim de plaj
45 pentru zilele 1 sau 3 este 2 + 11 = 13.
În ziua 4 timpul de plaj este limitat la 5 unit µi de timp, iar în
ziua 5 nu exist limitare. Deci în ziua 5 timpul maxim de plaj
este 5 + 11 = 16.
Timp maxim de executare/test: 1.0 secunde
Memorie: total 128 MB din care pentru stiv 32 MB
Dimensiune maxim a sursei: 10 KB
un ³ir de dimensiune N , ceea ce duce la dep ³ire de memorie pentru testele cu N foarte mare.
Punctaj acordat: aproximativ 65 de puncte.
Soluµie O(K * log T)
Se observ c parcurgând zilele cu limit ri pentru timpul de plaj , este posibil s g sim o zi
d[i] cu restricµia de timp t[i], care face imposibil faptul ca în ziua d[i + 1] s se ating valoarea t[i
+ 1].
Astfel, vom parcurge cele K zile cu restricµii ³i pentru ecare valoare t[i] vom reduce valoarea
t[i + 1] la o nou valoare posibil a atins . Apoi acela³i lucru se va face pornind de la sfâr³itul
³irului t c tre începutul s u.
În etapa urm toare se poate c uta binar r spunsul pentru ecare pereche de zile de forma (d[i],
d[i + 1]), iar vericarea posibilit µii de a se atinge o valoare propus t0, de face printr-o testare
relativ simpl :
d[i + 1] - d[i] >= (t0 - t[i] + T - 1) / T + (t0 - t[i + 1] + T - 1) / T;
Punctaj acordat: 100 de puncte
Solutie O(k) (Balµatu Andrei-Mircea)
Iniµial se iau cele k zile restricµionate ³i se aduc la valorile maximale posibile, adic pentru o zi
1 <= i <= m cu valoarea initial t(i) ³i pozitia x(i), dac exist o alt zi j ³i t(j) + T * abs(x(i)
- x(j)) < t(i), atunci t(i) se scade deoarece este restricµionat de alte zile. (abs - funcµia modul).
Apoi observ m c putem aa r spunsul între oricare dou zile consecutive în O(1). Având cele
dou zile (X - în stanga, Y - în dreapta), ³tim c ecare va cre³te cu T în drumul spre ziua maxim .
Astfel, aducem pe minimul dintre ele, adic min(t(X), t(Y)) la un num r nr <= max(t(X), t(Y))
cât mai mare, dup care ambele încep s creasc cu T alternativ, spre o pozitia P necunoscut .
În funcµie de paritatea secventei de zile r mase dup ce am crescut minimul dintre ele, putem
aa poziµia de valoare maxim (P) în funcµie de paritatea secvenµei de zile r mase. Punctaj: 100
de puncte
40
41 while (l <= r)
42 {
43 m = (l + r) / 2;
44 if (Try(m))
45 {
46 res = m;
47 l = m + 1;
48 }
49 else
50 r = m - 1;
51 }
52
53 fout << res;
54 }
55
56 bool Try(long long t0)
57 {
58 vector <Entry> e;
59
60 e.push_back( {1, 0} );
61 e.push_back({N + 1, -1});
62
63 int a, b;
64 for (int i = 0; i < K; i++)
65 if (t[i] < t0)
66 {
67 long long x = (t0 - t[i] - 1) / T;
68 a = max(d[i] - x, 1LL);
69 b = min(d[i] + x + 1, (long long)(N + 1));
70
71 e.push_back({a, 1});
72 e.push_back({b, -1});
73 }
74
75 sort(e.begin(), e.end());
76
77 long long cnt = 0;
78 for (int i = 0; i < e.size(); i++)
79 {
80 cnt += e[i].sgn;
81 if (cnt <= 0 && e[i].day <= N)
82 return true;
83 }
84
85 return false;
86 }
22.4 bsrec
Problema 4 - bsrec 100 de puncte
Fie un vector v sortat cresc tor cu N elemente naturale nenule
distincte pe care nu le cunoa³tem, dar pe care ne propunem s le
determin m.
Având la dispoziµie acest vector v , cu ajutorul urm torului algo-
ritm de c utare binar (vezi Figura 1) putem r spunde la query-uri
de forma:
Dându-se un num r X ³i un interval a, b se cere s se determine
cel mai mic element mai mare decât X aat în intervalul determinat
de indicii a ³i b, interval din vectorul v .
Se cunosc pa³ii pe care algoritmul de cautare binar i-a urmat
pentru diferite valori ale tripletului X, a, b.
CAPITOLUL 22. ONI 2018 362
Cerinµe
Dându-se N (lungimea vectorului), Q (num rul de query-uri apelate) ³i cele Q query-uri, s
se determine vectorul iniµial. Dac exist mai multe soluµii se va a³a soluµia minim lexicograc .
Dac nu exist soluµie se va a³a valoarea -1.
Un vector V 1 se consider mai mic lexicograc decât un alt vector V 2 dac exist un indice i
astfel încât: V 11 V 21, V 12 V 22, ..., V 1i 1 V 2i 1 ³i V 1i $ V 2i.
Cele Q query-uri sunt formate din:
Date de intrare
Fi³ierul bsrec.in conµine pe prima linie o valoare T reprezentând num rul de teste ce vor
efectuate.
Pentru ecare din cele T teste se va citi de pe prima linie valoarea N (num rul de elemente
ale vectorului), respectiv Q (num rul de query-uri), desp rµite prin câte un spaµiu.
Urm toarele linii descriu cele Q query-uri.
În cadrul unui query, prima linie va conµine o pereche de numere (X , M ) desp rµite printr-un
spaµiu, unde X reprezint valoarea c utat în vector, iar M num rul de pa³i efectuaµi în c utarea
binar a celei mai mici valori din vector care este mai mare decât X .
Pe urm toarea linie a query-ului se g se³te perechea de valori (a, b) având semnicaµia de mai
sus.
Urm toarele M 1 linii conµin perechi (st, dr) de valori naturale desp rµite prin câte un
spaµiu care reprezint indicii stânga, respectiv dreapta ce sunt a³aµi în urma ec rei iteraµii a
algoritmului de mai sus.
Date de ie³ire
Fi³ierul bsrec.out va conµine T linii, linia i conµinând r spunsul pentru testul i. Dac testul
admite soluµie, se vor a³a N numere naturale nenule strict cresc toare ce vor reprezenta valorile
vectorului v .
Deoarece exist mai multe soluµii, se va a³a soluµia minim lexicograc . Dac testul NU
admite soluµie, se va a³a -1.
Restricµii ³i preciz ri
a 1 & T & 10
a 1 & N, Q & 1000
a 1 & X & 1 000 000 000
a 1 & st & dr & N , cu excepµia ultimei perechi din c utarea binar unde st % dr
a Pentru 20% din punctajul total exist teste cu 1 & N, Q & 10 ³i soluµia minim lexicograc
admite valori pân în 20
a Se garanteaz c M & 15
Exemple:
Parcurgem toate iteraµiile c utarilor binare. Pentru o valoare X (pe care o c utam binar) ³i
o pereche (lef t, right) din c utarea binar se poate deduce o restricµionare de valoare pentru
elementul din mijloc mid lef t right©2, în funcµie de alegerea f cut de iteraµia urm toare.
Mai exact, pentru o pereche (lef t, right) urmat de o pereche (lef t2, right2) avem urm toarele
2 cazuri:
1. left == left2 ³i right2 < right: acest caz presupune c conditia v[mid] < X este fals , deci
v[mid] >= x
2. left < left2 ³i right2 == right: cazul presupune faptul c cond itia v[mid] < x este adevarat ,
deci v[mid] <= x - 1
În urma tuturor acestor relaµii, putem deduce c pentru ecare element v[i] din vector (i de
la 1 la N ), aceast valoare este m rginit inferior de o valoare downi, respectiv superior de o
valoare upi. Dac elementul nu este m rginit, downi este automat 0, iar upi = INF.
Ultima restricµie pe care trebuie s o impunem este faptul c v[i - 1] < v[i], pentru orice i de
la 2 la N.
Pentru a determina soluµia minim lexicograc, aplic m o strategie Greedy parcurgând vectorul
de la stânga la dreapta. Presupunând c am calculat deja soli, soluµia pentru elementul i,
soli 1 va maximul dintre soli 1 ³i downi 1. La nal, r mâne de vericat dac soli
<= upi pentru ecare i de la 1 la N . Dac toate restricµiile se respect , avem soluµie ³i o as m.
Altfel, r spunsul e -1.
75 }
76 }
77
78 return 0;
79 }
68
69 return 0;
70 }
22.5 numinum
Problema 5 - numinum 100 de puncte
Se consider urm toarea structur de date:
Cerinµe
Cunoscând num r torul, respectiv numitorul a dou fracµii ireductibile diferite din struc-
tur , determinaµi num rul minim de segmente de dreapt cu care putem conecta în structura
dat , cele dou fracµii.
Date de intrare
Pe prima linie a ³ierului de intrare numinum.in se g se³te un num r natural N .
Pe ecare dintre urm toarele N linii se g sesc câte 4 numere naturale xi , yi , ai , bi , 1 & i & N ,
desp rµite prin câte un spaµiu unde xi , yi reprezint num r torul, respectiv numitorul primei
fracµii de pe linia i 1, iar ai , bi reprezint num r torul, respectiv numitorul celei de-a doua
fracµii de pe linia i 1.
Date de ie³ire
Fi³ierul de ie³ire numinum.out va conµine N linii. Pe linia i se va scrie num rul minim de
segmente de dreapt necesare pentru a conecta, pe structura dat , fracµia xyi cu fracµia ab i .
i i
Restricµii ³i preciz ri
a 1 & N & 10 000
a 1 & xi , yi , ai , bi & 1 000 000 000, 1 & i & N
Exemple:
numinum.in numinum.out Explicaµii
1 6 N=1
4325 x1 4, y1 3; a1 2, b1 5.
Pentru a conecta fracµia 43 cu fracµia 25 avem nevoie de minim 6
segmente, dup cum urmeaz :
4/3 1/3 1/2 1/1 2/1 2/3 2/5
Timp maxim de executare/test: 0.2 secunde
Memorie: total 128 MB din care pentru stiv 32 MB
Dimensiune maxim a sursei: 10 KB
CAPITOLUL 22. ONI 2018 367
Ce putem deduce în schimb este faptul c dac am determina prima pereche din cele comune
celor 2 perechi, aceasta pereche ar o pereche care se poate determina în mod direct din punctul
de întâlnire.
Denim c dintr-o pereche (a,b) putem ajunge în mod direct în alt pereche (c,d) dac putem
aplica algoritmul de sc deri repetate doar pentru una din variabile (ori a = c ³i modic m doar b,
ori b = d ³i modicam doar a).
Astfel, pornind de la 2 perechi (a,b) ³i (c,d), am redus problema la alte 2 perechi (a2, b2) ³i
(c2, d2), perechi care se pot întâlni în mod direct într-un punct comun. Din acest punct, putem
determina în O 1 distanµa dintre cele 2 perechi aplicând formule simple în funcµie de cazuri.
Exemplu de caz:
A2 < B2, C2 > D2 - din acest caz deducem c prin sc deri repetate A2 r mâne pe loc în timp
ce B2 scade cu c te A2, respectiv D2 r mâne pe loc ³i C2 scade cu câte D2.
Din moment ce ³tim c aceste perechi se vor întâlni într-un punct comun avem relaµiile:
a B2 - k1 * A2 = D2
a C2 - k2 * D2 = A2
Din aceste 2 relaµii putem determina k1 (distanµa primei perechi pân în punctul comun)
respectiv k2 (distanµa celei de a doua perechi pân în punctul comun. Distanµa între cele 2
perechi este desigur k1 + k2.
Restul cazurilor r mâne tema de gandire!
Soluµia 4: prof. Marcel Dr gan - Colegiul Naµional Samuel Von Brukenthal, Sibiu
Pentru complexitate liniar folosim sc deri repetate asupra ambelor fracµii parcurgând astfel
structura înapoi spre vârf. La ecare pas transform m fracµia în componenta c reia intr valoarea
numeric mai mare (la num rator sau numitor) ³i num r m pa³ii realizaµi.
Ne oprim atunci când cele dou fracµii devin identice.
Pentru complexitate logaritmic folosim în loc de sc deri repetate restul împ rµirii (la fel
ca în Algoritmul lui Euclid). La aceast modalitate trebuie s avem grij la situaµia în care
transformarea fracµiei trece dincolo de prima fracµie comun celor dou ³iruri de transform ri
neobµinând astfel num rul minim de segmente. Pentru aceasta la ecare pas veric m dac
fracµiile nu au ajuns cumva pe aceea³i ramur :
p1==p2 ³i (q1-q2)%p1==0 sau q1==q2 ³i (p1-p2)%q1==0.
Dac au ajuns calcul m num rul de segmente dintre cele dou fracµii:
(p1-p2)/q1 sau (q1-q2)/p1
³i ajust m num rul total de segmente.
103
104 fin.close();
105 fout.close();
106
107 return 0;
108 }
67 {
68
69 freopen("numinum.in","r",stdin);
70 freopen("numinum.out","w",stdout);
71
72 scanf("%d",&T);
73
74 for(int k=1;k<=T;k++)
75 {
76
77 scanf("%d%d%d%d",&a,&b,&c,&d);
78
79 getList(1,a,b);
80 getList(2,c,d);
81
82 int lca=0, lim1=mylist[1].size(), lim2=mylist[2].size();
83 while(lca < lim1 && lca < lim2 &&
84 mylist[1][lca] == mylist[2][lca])
85 lca++;
86
87
88 int ans = 0;
89 for(int i = lim1 - 1; i > lca; i--)
90 ans += mylist[1][i].dist;
91
92 for(int i = lim2 - 1; i > lca; i--)
93 ans += mylist[2][i].dist;
94
95 if(lca == lim1)
96 {
97 int A = mylist[2][lca].x;
98 int B = mylist[2][lca].y;
99 int C;
100 if(A < B)
101 {
102 C = mylist[2][lca - 1].x;
103 ans += (B - C) / A;
104 }
105 else
106 {
107 C = mylist[2][lca - 1].y;
108 ans += (A - C) / B;
109 }
110
111 printf("%d\n",ans);
112 clearAll();
113 continue;
114 }
115
116 if(lca == lim2)
117 {
118 int A = mylist[1][lca].x;
119 int B = mylist[1][lca].y;
120 int C;
121
122 if(A < B)
123 {
124 C = mylist[1][lca - 1].x;
125 ans += (B - C) / A;
126 }
127 else
128 {
129 C = mylist[1][lca - 1].y;
130 ans += (A - C) / B;
131 }
132
133 printf("%d\n", ans);
134 clearAll();
135 continue;
136 }
137
138 int A = mylist[1][lca].x;
139 int B = mylist[1][lca].y;
140
141 int C = mylist[2][lca].x;
142 int D = mylist[2][lca].y;
CAPITOLUL 22. ONI 2018 372
143
144 if(A < B)
145 { // C > D || A == C
146 if(A == C)
147 ans += modul(B - D) / A;
148 else
149 ans += (C - A) / D + (B - D) / A;
150 }
151 else
152 {// A > B && C < D || B == D
153 if(B == D)
154 ans += modul(A - C) / B;
155 else
156 ans += (A - C) / B + (D - B) / C;
157 }
158
159 printf("%d\n", ans);
160 clearAll();
161 }
162
163 return 0;
164 }
Cerinµe
S se calculeze aria maxim a unei submatrice care respect specicaµiile din enunµ, pentru
ecare din cele Q sarcini date de c tre bunic.
Date de intrare
Fi³ierul rosiimici.in conµine pe prima linie trei numere naturale N , M ³i Q separate printr-un
spaµiu, având semnicaµia din enunµ.
Pe ecare dintre urm toarele N linii se a câte M numere naturale desp rµite prin câte un
spaµiu, reprezentând valorile matricei.
Pe urm toarele Q linii se a câte un num r natural x, reprezentând dimensiunea unei ro³ii.
Date de ie³ire
Fi³ierul rosiimici.out va conµine pe primele Q linii câte un num r natural, reprezentând aria
maxim cerut pentru ecare sarcin , în ordinea în care acestea apar în ³ierul de intrare.
Restricµii ³i preciz ri
CAPITOLUL 22. ONI 2018 373
Exemple:
Rezolvare 30 de puncte:
Pentru 30 de puncte putem precalcula r spunsul pentru ecare valoare.
Astfel, pentru o valoare x calcul m inaltime[i] = num rul de elemente mai mici sau egale cu
x de pe coloane i. Având vectorul de în lµimi calculat putem folosi o abordare de tip greedy.
În primul rând sortam coloanele dup în lµime. Apoi, pentru o coloan i, aria maxim a unui
dreptunghi este inaltime[i] * num rul de coloane care au în lµimea mai mare sau egal cu în lµimea
coloanei, soluµia ind coloana care maximizeaz expresia de mai sus.
O abordare similar este calcularea vectorului inaltime pentru ecare query în parte.
2 2
Complexit µi : O n m Q sau O Q n m
Rezolvare 50 de puncte:
Pentru aproximativ 50 de puncte ne vom folosi de faptul c ecare coloan este sortat .
Astfel, vom folosi algoritmul descris în problema bsrec pentru calcularea în m*log(n) pa³i a
vectorui inaltime.
CAPITOLUL 22. ONI 2018 374
O alt aborare este parcurgerea matricei în ordinea sortat a elementelor ³i menµinerea vec-
torului inaltime sortat la ecare pas, deoarece ad ugarea elementului duce la modicarea unei
singure poziµii în vector, ³i anume inaltimej .
2 2
Complexit µi : O n logn m Q sau O Q mlogn sau O n m Q
57 fin >> x;
58 assert(1 <= x && x <= n*m);
59 fout << ans[x] << "\n";
60 }
61
62 return 0;
63 }
66 column_height[actual_pos[x.second]]);
67 i++;
68 }
69 else
70 {
71 rasp[y.second] = mx;
72 j++;
73 }
74 }
75
76 while (j < queries.size())
77 {
78 rasp[queries[j].second] = mx;
79 j++;
80 }
81 }
82
83 bool cmp(pair<int, int> A, pair<int, int> B)
84 {
85 return a[A.first][A.second] < a[B.first][B.second];
86 }
87
88 int main()
89 {
90 freopen("rosiimici.in", "r", stdin);
91 freopen("rosiimici.out", "w", stdout);
92 cin.sync_with_stdio(false);
93
94 cin >> n >> m >> q;
95 for (int i = 1; i <= n; i++)
96 for (int j = 1; j <= m; j++)
97 {
98 cin >> a[i][j];
99 pos.push_back(make_pair(i, j));
100 }
101
102 for (int i = 1; i <= q; i++)
103 {
104 int x;
105 cin >> x;
106 queries.push_back(make_pair(x, i));
107 }
108
109 sort(queries.begin(), queries.end());
110 sort(pos.begin(), pos.end(), cmp);
111
112 Prep();
113
114 for (int i = 1; i <= q; i++)
115 cout << rasp[i] << "\n";
116 return 0;
117 }
ONI 2017
23.1 arhipelag
Problema 1 - arhipelag 100 de puncte
În regiunea Ionia a lumii grece³ti antice, regiune ce corespunde teritoriului actual al M rii
Egee, exist mai multe insule. Harta m rii este reprezentat de o matrice de dimenisuni N M ,
având valori de 1 ³i 0, iar ecare element din matrice reprezint o zon de dimensiune 1 1 din
mare. Liniile matricei sunt numerotate de la 1 la N , de sus în jos, iar coloanele de la 1 la M , de
la stânga la dreapta. Astfel, colµul din stânga sus al matricei este asociat zonei (1, 1), iar colµul
din dreapta jos corespunde zonei (N , M ).
Un element care conµine valoarea 0 reprezint faptul c în acea zon se a ap . O insul este
determinat de un dreptunghi format în totalitate din valori de 1. Se garanteaz faptul c toate
zonele care conµin valoarea 1 formeaz dreptunghiuri valide ³i c oricare dou insule sunt separate
de ap . De exemplu, Figura 1 de mai jos reprezint o hart valid , în timp ce Figura 2 ³i Figura
3 NU reprezint o hart valid .
Cerinµe
Ionienii, ind oameni practici, doresc construirea unui far-bibliotec (a³ezat pe o platform 1
1), într-o zon acoperit de ap . Poziµia platformei va aleas într-o celul C astfel încât suma
distanµelor dintre toate insulele ³i C s e minim .
Distanµa dintre o celul C ³i o insul este denit ca ind minimul dintre distanµele Manhattan
dintre C ³i ecare celul care aparµine insulei (distanµa poate trece atât prin alte insule, cât ³i
prin zone acoperite de ap ).
Distanµa Manhattan dintre dou celule aate pe linia x1 ³i coloana y1, respectiv pe linia x2 ³i
coloana y2, este denit ca |x1 - x2| + |y1 - y2|, unde |x| reprezint valoarea absolut a lui x.
Date de intrare
Fi³ierul de intrare arhipelag.in conµine, pe prima linie, valorile N ³i M , având semnicaµia din
enunµ. Urm toarele N linii conµin câte M valori binare, separate de câte un spaµiu, reprezentând
harta m rii.
Date de ie³ire
377
CAPITOLUL 23. ONI 2017 378
Restricµii ³i preciz ri
a Pentru teste în valoare de 15 puncte, 1 & N, M & 50
a Pentru alte teste în valoare de 20 de puncte, 1 & N, M & 300, iar num rul de insule din
arhipelag nu dep ³e³te 300
a Pentru alte teste în valoare de 20 de puncte, 1 & N, M & 300
a Pentru restul de teste, 1 & N, M & 1000
a Se garanteaz c exist cel puµin o zon acoperit de ap
Exemple:
arhipelag.in arhipelag.out Explicaµii
7 7 23
Notând cu D(x1, y1, x2, y2) insula determinat de dreptunghiul
0 1 0 1 0 1 1având colµul stânga sus în (x1, y1) ³i colµul dreapta jos în (x2,
0 1 0 1 0 1 1y2), arhipelagul conµine urm toarele insule: D1(1, 2, 2, 2), D2(1,
0 0 0 1 0 0 04, 7, 4), D3(1, 6, 2, 7), D4(6, 1, 7, 2) ³i D5(6, 6, 7, 7). Notând
0 0 0 1 0 0 0cu dist(D) distanµa dintre celula (2, 3) ³i insula D, distanµele
0 0 0 1 0 0 0sunt urm toarele:
1 1 0 1 0 1 1dist(D1) = min |2 - 1| + |3 - 2|, |2 - 2| + |3 - 2| = 1, dist(D2)
1 1 0 1 0 1 1= 1, dist(D3) = 3, dist(D4) = 5 ³i dist(D5) = 7.
4 4 12 Pentru ecare dintre celulele (1, 2), (2, 2), (3, 2), (4, 3) si (4, 4),
0
11 0 distanµa dintre celul ³i singura insul existent în acest exemplu
0
11 0 este aceea³i. Se va alege cea care are linia minim , iar în caz de
0
11 0 egalitate se va alege cea care are coloana minim . Astfel, celula
0
00 0 (1, 2) reprezint soluµia.
Timp maxim de executare/test: 0.3 secunde
Memorie: total 32 MB din care pentru stiv 8 MB
Dimensiune maxim a sursei: 15 KB
` x1 - x, dac x < x1
` x - x2, dac x > x2
` 0, altfel
a dy =
` y1 - y, dac y < y1
` y - y2, dac y > y2
` 0, altfel
CAPITOLUL 23. ONI 2017 379
Complexitate: O N M N R_IN SU LE
Soluµia 3 (55 de puncte)
Se observ faptul c pentru o celul C x, y , avem dou costuri asociate: costul implicat de
alegerea liniei x ³i costul implicat de alegerea coloanei y ; aceste dou costuri sunt independente (nu
depind unul de cel lalt). Astfel, se precalculeaz 2 vectori total_dxx (1 & x & N ) ³i total_dy y
(1 & y & M ), reprezentând costul asociat cu alegerea liniei x, respectiv a coloanei y , iar apoi se
itereaz toate celulele care conµin ap ³i se alege cea care are total_dx total_dy minim.
Valoarea total_dxx se calculeaz astfel: se itereaza toate insulele, iar pentru ecare insul
D x1, y1, x2, y2, se adaug la total_dxx valoarea dx, denit la fel ca in solutia 2. Analog, se
calculeaz valorile total_dy y .
Complexitate: O N N R_IN SU LE M N R_IN SU LE
Solutia 4 (100 de puncte)
Se procedeaz asem n tor ca în soluµia 3, cu excepµia modalit µii de calculare a vectorilor
total_dxx ³i total_dy y .
Cum se calculeaz total_dxx (total_dy y se calculeaz în mod similar):
a se calculeaz intervalele închise x1i, x2i, liniile pe care se intinde insula i
a total_dx1 se calculeaz ca în soluµia 3, în O N R_IN SU LE
a se itereaz x de la 2 la N , la ecare pas µinând minte 2 variabile:
33 ofstream cout("arhipelag.out");
34
35 cin >> N >> M;
36 for(int i = 1; i <= N; ++i)
37 for(int j = 1; j <= M; ++j)
38 cin >> A[i][j];
39
40 for(int i = 1; i <= N; ++i)
41 {
42 for(int j = 1; j <= M; ++j)
43 {
44 if(A[i][j] == 1)
45 {
46 int xl = i;
47 int xr = i;
48
49 while(A[xr + 1][j])
50 ++xr;
51
52 int yl = j;
53 int yr = j;
54 while(A[i][yr + 1])
55 ++yr;
56
57 for(int k = xl; k <= xr; ++k)
58 for(int h = yl; h <= yr; ++h)
59 A[k][h] = -1;
60
61 ++startX[xl];
62 ++endX[xr];
63
64 ++startY[yl];
65 ++endY[yr];
66 }
67 }
68 }
69
70 computeCostForCoordinate(N, cx, startX, endX);
71 computeCostForCoordinate(M, cy, startY, endY);
72
73 int bestTotalDistance = 0x3f3f3f3f;
74 for(int i = 1; i <= N; ++i)
75 {
76 for(int j = 1; j <= M; ++j)
77 {
78 if(!A[i][j] && cx[i] + cy[j] < bestTotalDistance)
79 {
80 bestTotalDistance = cx[i] + cy[j];
81 xs = i;
82 ys = j;
83 }
84 }
85 }
86
87 cout << xs << " " << ys << "\n";
88 // printf("Best total disance = %d\n", bestTotalDistance);
89
90 return 0;
91 }
23.2 mirror
Problema 2 - mirror 100 de puncte
Numim oglinda num rului natural nenul a, num rul b, obµinut prin modicarea ec rei cifre din
reprezentarea sa binar , de exemplu pentru a 22 10 10110 2 se obµine 01001 2 9 10 b.
Cerinµe
Cunoscându-se numerele naturale N , K ³i cele N numere natural nenule, scrieµi un program
care:
1) Transform în baza doi termenii ³irului dat obµinându-se un nou ³ir format din alipirea
cifrelor binare. Din acest ³ir se vor determina ³i a³a, separate prin câte un spaµiu, toate repre-
zent rile în baza 10 corespunz toare secvenµelor al turate de exact K cifre binare, parcurse de la
stânga la drepta. Dac ultima secvenµ nu are exact K cifre binare, atunci aceasta nu se va mai
lua în considerare.
2) S aplice K transform ri asupra ³irului iniµial, înlocuind la ecare pas orice termen cu
oglinda sa. Asupra termenilor care devin zero nu se vor mai efectua alte operaµii. Dup efec-
tuarea celor K transform ri, s se determine cea mai lung secvenµ de numere care au cifra 1
pe aceea³i poziµie în reprezentarea lor în baza doi. Dac sunt mai multe astfel de secvenµe având
lungimea maxim , se va a³a cea mai din stânga.
Date de intrare
Fi³ierul de intrare mirror.in conµine pe primul rând num rul C , reprezentând cerinµa. Pe al
doilea rând se a scrise numerele naturale N ³i K . Pe rândul al treilea sunt cele N numere ale
³irului separate prin câte un spaµiu.
Date de ie³ire
Dac C 1, atunci în ³ierul de ie³ire mirror.out se vor scrie separate prin câte un spaµiu,
toate numerele cerute în enunµ.
Dac C 2, atunci în ³ierul de ie³ire mirror.out se va scrie pe prima linie lungimea maxim
a secvenµei determinate, iar pe urm toarea linie separate prin spaµiu, poziµia primului ³i ultimului
termen din secvenµ (prima poziµie este 1).
Restricµii ³i preciz ri
a 1 & N &100 000
a 0 & K & 30
a Elementele ³irului sunt mai mici decât 2 000 000 001;
a Pentru 30% din teste cerinµa va C 1.
CAPITOLUL 23. ONI 2017 383
Exemple:
mirror.in mirror.out Explicaµii
1 330111 7 10 111 2 ; 8 10 1000 2 ; 2 10 10 2 ; 11 10 1011 2 ;
42 Sirul format este: 1111000101011 ³i grupate câte 2 avem nume-
7 8 2 11 rele:
11 2 3 10 ; 11 2 3 10 ; 00 2 0 10 ; 01 2 1 10 ; 01 2
1 10 ; 01 2 1 10 ;
2 3 Dup o transformare numerele în baza 2 sunt:
51 13
37 72 101 50
116
24 masca<<=1;
25
26 if(masca>nr)masca>>=1;
27
28 while(masca)
29 {
30 if(masca&nr)
31 x=x+y;
32 y/=2;
33 if(y==0)
34 {
35 fout<<x<<" ";
36 y=1<<k-1;
37 x=0;
38 }
39 masca>>=1;
40 }
41 }
42 fout<<’\n’;
43 }
44
45 int lungime(int &st, int &dr)
46 {
47 int ok,l,lmax=0,masca=1,ddr,i;
48 do
49 {
50 ok=0;//pp ca nu mai sunt cifre binare de 1
51 l=0;
52 for(i=st; i<=dr; i++)
53 {
54 if(masca<v[i])
55 ok=1;
56 if(masca&v[i])
57 l++;
58 else
59 {
60 if(l>lmax)
61 {
62 lmax=l;
63 ddr=i-1;
64 }
65 l=0;
66 }
67 }
68
69 if(l>lmax)
70 {
71 lmax=l;
72 ddr=dr;
73 }
74 masca<<=1;
75 }
76
77 while(ok==1);
78 dr=ddr;
79 st=ddr-lmax+1;
80 return lmax;
81 }
82
83 void secventa()
84 {
85 int st=0,dr,i,lung,lmax=0,sst,ddr;
86 i=1;
87
88 while(v[i]==0&&i<=n)
89 i++;
90
91 if(i<=n)
92 for( ; i<=n; i++)
93 if(v[i]!=0)
94 if(st==0)
95 st=dr=i;
96 else
97 dr++;
98 else
99 {
CAPITOLUL 23. ONI 2017 385
100 if(st)
101 {
102 lung=lungime(st,dr);
103 if(lung>lmax)
104 {
105 lmax=lung;
106 sst=st;
107 ddr=dr;
108 }
109 st=0;
110 }
111 }
112
113 if(st)
114 {
115 lung=lungime(st,dr);
116 if(lung>lmax)
117 {
118 lmax=lung;
119 sst=st;
120 ddr=dr;
121 }
122 }
123
124 fout<<lmax<<’\n’<<sst<<" "<<ddr<<’\n’;
125 }
126
127 int main()
128 {
129 int x=1,i,j,masca;
130 fscanf(fin,"%d%d%d",&ct,&n,&k);
131 for(i=1; i<=n; i++)
132 fscanf(fin,"%d",&v[i]);
133
134 if(ct==1)
135 {
136 rezolva1();
137 return 0;
138 }
139
140 // transformare cautand cifrele care se modifica si tinand cont
141 // de paritatea lui k
142 int u[33],nr,p,l,r;
143 if(k)
144 for(r=1; r<=n; r++)
145 {
146 masca=1;
147 masca<<=30;
148 while((masca&v[r])==0)
149 masca>>=1;
150 nr=0;
151
152 //pun cifrele binare in vector
153 while(masca)
154 {
155 if(masca&v[r])
156 u[++nr]=1;
157 else
158 u[++nr]=0;
159
160 masca>>=1;
161 }
162
163 int cont=0;//numara de cate ori se schimba cifrele binare
164 int cifbin=1;
165 for(j=1; j<=nr; j++)
166 if(u[j]!=cifbin)
167 {
168 cont++;
169 if(cifbin==1)
170 cifbin=0;
171 else
172 cifbin=1;
173 }
174
175 if(cont<k)
CAPITOLUL 23. ONI 2017 386
176 v[r]=0;
177 else
178 {
179 // modific toate cifrele odata daca k impar,
180 // altfel cifrele raman la fel
181 if(k%2==1)
182 for(j=1; j<=nr; j++)
183 if(u[j]==0)
184 u[j]=1;
185 else
186 u[j]=0;
187
188 //elimin cifrele care se pierd la transformare
189 i=1;
190 cont=0;
191 while(cont<k&&i<=nr)
192 {
193 i++;
194 if(u[i]!=u[i-1])
195 cont++;
196 }
197
198 if(i>nr)
199 v[r]=0;
200 else
201 {
202 p=1;
203 x=0;
204 for(j=nr; j>=i; j--)
205 {
206 x=x+p*u[j];
207 p<<=1;
208 }
209
210 v[r]=x;
211 }
212 }
213 }
214
215 secventa();
216 return 0;
217 }
107 if(A[i][j]==1)
108 l++;
109 else
110 {
111 if(l>lmax)
112 {
113 lmax=l;
114 psf=i;
115 psfmin=i;
116 }
117
118 if(l==lmax)
119 psf=i;
120
121 if(psf<psfmin)
122 psfmin=psf;
123
124 l=0;
125 }
126 }
127
128 i=i-1;
129 if(A[i][j]==1 && l>lmax)
130 {
131 lmax=l;
132 psf=i+1;
133 psfmin=psf;
134 }
135 }
136
137 out<<lmax<<’\n’; out<<psfmin+1-lmax<<’ ’<<psfmin<<’\n’;
138 }
139
140 in.close();
141 out.close();
142 return 0;
143 }
36 }
37
38 for(int bit = maxBit; bit >= 0; --bit)
39 {
40 if(v[i] & (1 << bit))
41 currentValue = currentValue * 2 + 1;
42 else
43 currentValue = currentValue * 2;
44
45 ++nrBits;
46
47 if(nrBits == K)
48 {
49 cout << currentValue << " ";
50
51 currentValue = 0;
52 nrBits = 0;
53 }
54 }
55 }
56
57 cout << "\n";
58 }
59 else
60 {
61 for(int i = 1; i <= N; ++i)
62 {
63 for(int j = 1; j <= K; ++j)
64 {
65 if(!v[i])
66 break;
67
68 int maxBit = 0;
69 for(int bit = 31; bit >= 0; --bit)
70 {
71 if(v[i] & (1 << bit))
72 {
73 maxBit = bit;
74 break;
75 }
76 }
77
78 v[i] ^= (1 << (maxBit + 1)) - 1;
79 }
80 }
81
82 int startPos = -1;
83 int endPos = -1;
84 int maxLength = 0;
85
86 for(int bit = 0; bit < 32; ++bit)
87 {
88 int currentLength = 0;
89 for(int i = 1; i <= N; ++i)
90 {
91 if(v[i] & (1 << bit))
92 ++currentLength;
93 else
94 currentLength = 0;
95
96 if(currentLength > maxLength ||
97 (currentLength == maxLength &&
98 i - currentLength + 1 < startPos))
99 {
100 maxLength = currentLength;
101 startPos = i - currentLength + 1;
102 endPos = i;
103 }
104 }
105 }
106
107 cout << maxLength << "\n";
108 cout << startPos << " " << endPos << "\n";
109 }
110
111 return 0;
CAPITOLUL 23. ONI 2017 390
112 }
72 fout<<’\n’;
73 }
74
75 int lungime(int &st, int &dr)
76 {
77 int ok,l,lmax=0,masca=1,ddr,i;
78 do
79 {
80 ok=0;//pp ca nu mai sunt cifre binare de 1
81 l=0;
82 for(i=st; i<=dr; i++)
83 {
84 if(masca<=v[i])
85 ok=1;
86 if(masca&v[i])
87 l++;
88 else
89 {
90 if(l>lmax)
91 {
92 lmax=l;
93 ddr=i-1;
94 }
95 l=0;
96 }
97 }
98 if(l>lmax)
99 {
100 lmax=l;
101 ddr=dr;
102 }
103 masca<<=1;
104 } while(ok==1);
105
106 dr=ddr;
107 st=ddr-lmax+1;
108 return lmax;
109 }
110
111 void secventa()
112 {
113 int st=0,dr=0,i,lung,lmax=0,sst,ddr;
114 i=1;
115 while(v[i]==0&&i<=n)
116 i++;
117
118 if(i<=n)
119 for( ; i<=n; i++)
120 if(v[i]!=0)
121 if(st==0)
122 st=dr=i;
123 else
124 dr++;
125 else
126 {
127 if(st)
128 {
129 lung=lungime(st,dr);
130 if(lung>lmax)
131 {
132 lmax=lung;
133 sst=st;
134 ddr=dr;
135 }
136 st=0;
137 }
138 }
139
140 if(dr)
141 {
142 lung=lungime(st,dr);
143 if(lung>lmax)
144 {
145 lmax=lung;
146 sst=st;
147 ddr=dr;
CAPITOLUL 23. ONI 2017 392
148 }
149 }
150
151 fout<<lmax<<’\n’<<sst<<" "<<ddr<<’\n’;
152 }
153
154 int main()
155 {
156 int x=1,i,j,masca;
157 for(i=1; i<=31; i++)
158 {
159 x=x<<1;
160 w[i]=x-1;
161 }
162 fscanf(fin,"%d%d%d",&ct,&n,&k);
163 for(i=1; i<=n; i++)
164 fscanf(fin,"%d",&v[i]);
165
166 if(ct==1)
167 {
168 rezolva1();
169 return 0;
170 }
171
172 //transformare cu cautare binara- timp mai mare?
173 for(i=1; i<=n; i++)
174 {
175 for(j=1; j<=k&&v[i]; j++)
176 v[i]=transforma(v[i]);
177 // fout<<v[i]<<" ";
178 }
179
180 secventa();
181 return 0;
182 }
38 d[i]=d[i-1]*2;
39 }
40
41 fin=fopen("mirror.in","rt");
42 fscanf(fin,"%d %d %d",&C,&N,&K);
43
44 if(C==1)
45 {
46 fscanf(fin,"%d",&z);
47 x=z;
48 p=posd(x);
49 afisareK(x,p);
50 for(i=2;i<=N;i++)
51 {
52 fscanf(fin,"%d",&z);
53 y=z;
54 q=posd(y);
55 x=x*d[q]+y;
56 p+=q;
57 afisareK(x,p);
58 }
59 }
60 else
61 {
62 for(j=0;j<33;j++)
63 {
64 posL[j]=0;
65 maxL[j]=0;
66 }
67 pmax=0;
68 for(i=1;i<=N;i++)
69 {
70 fscanf(fin,"%d",&z);
71 x=z;
72 for(j=0;j<=31;j++)
73 {
74 v[j]=x%2;
75 x=x/2;
76 if(v[j]==1){
77 p=j;
78 }
79 }
80 if(p>pmax)pmax=p;
81 for(l=1;l<=K && p>=0;l++)
82 {
83 while(p>=0 && v[p]==l%2)
84 {
85 v[p]=0;
86 p--;
87 }
88 }
89 for(j=0;j<=pmax;j++)
90 {
91 q=v[j];
92 if(K%2) q=1-q;
93 if(j>p) q=0;
94
95 if(q==1)
96 {
97 L[j]++;
98 if(L[j]==1)pos[j]=i;
99 if(L[j]>maxL[j])
100 {
101 maxL[j]=L[j];
102 posL[j]=pos[j];
103 }
104 }
105 else
106 {
107 L[j]=0;
108 }
109 }
110 }
111
112 jmax=0;
113 for(j=0;j<=pmax;j++)
CAPITOLUL 23. ONI 2017 394
114 {
115 if((maxL[j]>maxL[jmax])||
116 (maxL[j]==maxL[jmax] && posL[j]<posL[jmax]))
117 {
118 jmax=j;
119 }
120 }
121
122 fout<<maxL[jmax]<<"\n";
123 fout<<posL[jmax]<<" "<<posL[jmax]+maxL[jmax]-1<<"\n";
124 }
125
126 fclose(fin);
127 fout.close();
128 return 0;
129 }
23.3 okcpp
Problema 3 - okcpp 100 de puncte
Despre num rul natural N spunem c are proprietatea okcpp dac oricum alegem K cifre ale
sale vom g si printre ele cel puµin P cifre distincte (oricare k cel puµin p).
Cerinµe
(1) Fiind date numerele naturale K , P , A ³i B s se calculeze ³i s se a³eze num rul de
numere okcpp din intervalul A, B .
(2) Fiind date numerele naturale K , P ³i N s se calculeze ³i s se a³eze cel mai mic num r
okcpp care este mai mare sau egal cu N .
Date de intrare
Fi³ierul de intrare okcpp.in conµine pe primul rând num rul C .
Dac C 1, atunci pe al doilea rând se vor aa scrise, separate prin spaµiu, numerele naturale
K , P , A ³i B .
Dac C 2, atunci pe al doilea rând se vor aa scrise, separate prin spaµiu, numerele naturale
K , P ³i N .
Date de ie³ire
Dac C 1, atunci în ³ierul de ie³ire okcpp.out se va scrie num rul de numere okcpp din
intervalul A; B .
Dac C 2, atunci în ³ierul de ie³ire okcpp.out se va scrie cel mai mic num r natural okcpp
care este mai mare sau egal cu N .
Restricµii ³i preciz ri
a 1 & P & 10
a P & K & num rul de cifre al lui N & 18
a Pentru 20% din teste cerinµa va C 1
Pentru cerinµa C 1 vom avea 0 & A $ B $ 10 ³i B A & 10000
18
a
a Pentru cerinµa C 2 se garanteaz c exist întotdeauna soluµie
Exemple:
okcpp.in okcpp.out Explicaµii
1 3 Avem K 4 ³i P 2. în intervalul [99997;100001] sunt trei
5 2 99997 100001 numere okcpp: 99997, 99998 ³i 100001.
2 100023 Avem K 5, P 3 ³i N 99997. Se observ u³or c
5 3 99997 numerele 99997, 99998 , ..., 100022 nu corespund. Primul
num r care corespunde cerinµelor este 100023.
Timp maxim de executare/test: 0.1 secunde
Memorie: total 32 MB din care pentru stiv 8 MB
Dimensiune maxim a sursei: 10 KB
37 for(i=P;i<=9;i++) s2=s2+w[i];
38
39 w[0]=1000;
40 s3=s1;
41 i=min(nw+1,P-1);
42 h=w[i];
43 while(i>=1 && (K-1-s3)/(P-i)+h>=w[i-1])
44 {
45 r=(K-1-s3)/(P-i);
46 if(r+h>w[i-1]) r=w[i-1]-h;
47 s3=s3+r*(P-i);
48 i--;
49 h=w[i];
50 }
51
52 r=(K-1-s3)/(P-i);
53 if(r+h>w[i-1]) r=w[i-1]-h;
54 h=h+r;
55 s3=s3+r*(P-i);
56 z=(K-1-s3)%(P-i)+s3+h*(10-(P-1));
57 if(z<nv) return 0;
58 return 1;
59 }
60 else
61 return 0;
62 }
63
64 int main()
65 {
66 int i,j,l,ok,r,i1,i2,ok1,aux,c;
67 fin>>C;
68
69 if(C==1)
70 {
71 fin>>K>>P>>A>>B;
72 c=0;
73 for(N=A;N<=B;N++)
74 {
75 X=N;
76 nv=0;
77 do
78 {
79 v[++nv]=X%10;
80 X=X/10;
81 } while(X);
82
83 for(i=1;i<=nv/2;i++)
84 {
85 aux=v[i];
86 v[i]=v[nv+1-i];
87 v[nv+1-i]=aux;
88 }
89
90 if(P==1 || verificare(v,nv)==1)
91 c++;
92 }
93
94 fout<<c;
95 }
96
97 if(C==2)
98 {
99 fin>>K>>P>>N;
100 X=N;
101 nv=0;
102 do
103 {
104 v[++nv]=X%10;
105 X=X/10;
106 } while(X);
107
108 for(i=1;i<=nv/2;i++)
109 {
110 aux=v[i];
111 v[i]=v[nv+1-i];
112 v[nv+1-i]=aux;
CAPITOLUL 23. ONI 2017 399
113 }
114
115 ok=0;
116 if(P==1 || verificare(v,nv)==1)
117 {
118 fout<<N<<"\n";
119 ok=1;
120 }
121
122 if(ok==0)
123 {
124 nx=0;
125 for(i=1;i<=nv;i++)
126 if(v[i]<9)
127 nx++;x[nx]=i;
128
129 i1=1; i2=nx;
130 while(i1<=i2)
131 {
132 i=(i1+i2)/2;
133 ///pastrez prefix de lungime i, crescand a i-a cifra
134 ok1=0;
135 aux=v[x[i]];
136 for(l=v[x[i]]+1;l<=9 && 0==ok1;l++)
137 {
138 v[x[i]]=l;
139 if(verificare(v,x[i])==1)
140 ok1=1;
141 }
142
143 v[x[i]]=aux;
144 if(ok1==1)
145 i1=i+1;
146 else
147 i2=i-1;
148 }
149
150 i=x[i2];
151 for(l=v[i]+1;l<=9 && i>=1 && 0==ok;l++)
152 {
153 v[i]=l;
154 if(verificare(v,i)==1)
155 {
156 for(r=i+1;r<=nv;r++)
157 {
158 v[r]=0;
159 while(verificare(v,r)==0)
160 v[r]++;
161 }
162
163 ok=1;
164 for(j=1;j<=nv;j++)
165 fout<<v[j];
166
167 fout<<"\n";
168 }
169 }
170 }
171
172 if(ok==0)
173 {
174 v[1]=1;
175 if(verificare(v,1)==1)
176 {
177 nv++;
178 for(r=2;r<=nv;r++)
179 {
180 v[r]=0;
181 while(verificare(v,r)==0)
182 v[r]++;
183 }
184 ok=1;
185 for(j=1;j<=nv;j++)
186 fout<<v[j];
187
188 fout<<"\n";
CAPITOLUL 23. ONI 2017 400
189 }
190 }
191 ///if(ok==0) fout<<-1<<"\n";
192 }
193
194 fout.close();
195 fin.close();
196 return 0;
197 }
64 }
65
66 for (i++; i < S.length(); i++)
67 for (char d = ’0’; d <= ’9’; d++)
68 {
69 C[d - ’0’]++;
70 if (canFill(C, K, P, S.length() - i - 1))
71 {
72 S[i] = d;
73 break;
74 }
75 C[d - ’0’]--;
76 }
77
78 return S;
79 }
80
81 int main()
82 {
83 ifstream f("okcpp.in");
84 ofstream g("okcpp.out");
85
86 int C, K, P, ns;
87 long long A, B, X;
88 string S;
89
90 f >> C ;
91 if(C == 1)
92 {
93 f >> K >> P >> A >> B;
94 ns = 0;
95 for( X = A; X <= B ; X ++)
96 {
97 S = to_string(X);
98 if(isGood(S, K, P))
99 {
100 ns ++;
101 }
102 g << ns << endl;
103 }
104 }
105 else
106 {
107 f >> K >> P >> S;
108 g << findNext(S, K, P) << endl;
109 }
110
111 return 0;
112 }
24
25 vector<int> ans;
26
27 bool IsOk(vector<int> digits, int k, int p)
28 {
29 sort(digits.begin(), digits.end());
30 reverse(digits.begin(), digits.end());
31
32 for (int i = 0; i + 1 < p; i += 1)
33 k -= digits[i];
34
35 if (k > 0)
36 return true;
37 else
38 return false;
39 }
40
41 bool Possible(vector<int> digits, int k, int p, int remaining)
42 {
43 for (int i = 0; i < remaining; i += 1)
44 ( *(min_element(digits.begin(), digits.end())))++;
45
46 return IsOk(digits, k, p);
47 }
48
49 void SolveThis(vector<int> digits, int digit, int k, int p,
50 int remaining, bool& ok)
51 {
52 if (digit == 10)
53 {
54 if (remaining != 0)
55 return;
56
57 ok = true;
58 ans = digits;
59 return ;
60 }
61
62 for (int current = remaining; current >= 0; current -= 1)
63 {
64 digits[digit] += current;
65 if (Possible(digits, k, p, remaining - current))
66 {
67 SolveThis(digits, digit + 1, k, p, remaining - current, ok);
68 auto d = digits;
69 if (ok)
70 return;
71 }
72 digits[digit] -= current;
73 }
74
75 return;
76 }
77
78 void SolveFixed(vector<int> digits, int last_digit, int k, int p,
79 int remaining, bool& ok, int& digit)
80 {
81 for (int current_digit = last_digit + 1;
82 current_digit < 10;
83 current_digit += 1)
84 {
85 digits[current_digit] += 1;
86 SolveThis(digits, 0, k, p, remaining - 1, ok);
87 digits[current_digit] -= 1;
88
89 if (ok)
90 {
91 digit = current_digit;
92 return;
93 }
94 }
95
96 return;
97 }
98
99 string Solve(int k, int p, string n)
CAPITOLUL 23. ONI 2017 403
100 {
101 vector<int> digits(10, 0);
102 for (char itr : n)
103 digits[itr - ’0’] += 1;
104
105 if (IsOk(digits, k, p))
106 return n;
107
108 int to_match = 0;
109 while (n.size())
110 {
111 to_match += 1;
112 digits[n.back() - ’0’] -= 1;
113
114 bool ok = false;
115 int digit = 0;
116 SolveFixed(digits, n.back() - ’0’, k, p, to_match, ok, digit);
117 n.pop_back();
118
119 if (ok)
120 {
121 digits[digit] += 1;
122 n += char(’0’ + digit);
123 return AddStuffAtEnd(n, digits, ans);
124 }
125 }
126
127 digits = vector<int>(10, 0);
128 digits[1] += 1;
129
130 bool ok = false;
131 int digit = 0;
132 SolveFixed(digits, -1, k, p, to_match, ok, digit);
133
134 if (ok)
135 {
136 digits[digit] += 1;
137 n = "1";
138 n += char(’0’ + digit);
139 return AddStuffAtEnd(n, digits, ans);
140 }
141 else
142 return "-1";
143 }
144
145 bool IsOk(int64 n, int k, int p)
146 {
147 vector<int> digits(10, 0);
148 do
149 {
150 digits[n % 10]++;
151 n /= 10;
152 } while (n);
153
154 return IsOk(digits, k, p);
155 }
156
157 int Solve1(int k, int p, int64 left, int64 right)
158 {
159 int a = 0;
160 for (int64 i = left; i <= right; i += 1)
161 a += IsOk(i, k, p);
162
163 return a;
164 }
165
166 int main()
167 {
168 freopen("okcpp.in", "r", stdin);
169 freopen("okcpp.out", "w", stdout);
170
171 int c;
172 cin >> c;
173
174 if (c == 2)
175 {
CAPITOLUL 23. ONI 2017 404
176 int k, p;
177 string n;
178 cin >> k >> p >> n;
179 cout << Solve(k, p, n) << ’\n’;
180 }
181 else
182 {
183 int k, p;
184 int64 left, right;
185 cin >> k >> p >> left >> right;
186 cout << Solve1(k, p, left, right) << ’\n’;
187 }
188
189 return 0;
190 }
23.4 adlic
Problema 4 - adlic 100 de puncte
Pentru urm torul an ³colar admiterea celor N elevi în liceu se va face pe baza unor evalu ri
complexe.
Fiecare dintre viitorii elevi ai clasei a IX-a va primi, în urma testelor ³i probelor pe care le va
sus µine, un punctaj (num r natural nenul) cu care va participa la admiterea electronic .
Repartizarea ec rui elev în clase se face în ordinea înscrierii respectând criteriile:
a Primul elev se repartizeaz în clasa cu num rul de ordine 1.
a în clasa în care este repartizat un elev nu exist , pân la momentul repartiz rii sale, nici un
punctaj mai mare decât al s u.
a Num rul claselor s e cât mai mic posibil.
Cerinµe
Determinaµi:
1. Punctajul primului elev care nu ar mai putea repartizat în prima clas în condiµiile în
care toµi elevii î³i doresc s e repartizaµi în prima clas (se aplic doar la cerinµa 1).
2. Num rul claselor ce se vor forma respectând criteriile.
Date de intrare
Fi³ierul de intrare adlic.in conµine pe primul rând num rul C a c rui valoare poate 1 sau
2, apoi separat de un spaµiu num rul natural N .
Pe liniile urm toare se g sesc cele N punctaje ale elevilor în ordinea înscrierii, numere naturale
nenule desp rµite prin câte un spaµiu.
Date de ie³ire
Dac C 1, atunci în ³ierul de ie³ire adlic.out se va scrie soluµia cerinµei 1.
Dac C 2, atunci în ³ierul de ie³ire adlic.out se va scrie soluµia cerinµei 2.
Restricµii ³i preciz ri
a Punctajele elevilor vor avea cel mult ³ase cifre
a 1 & N & 1 000 000
a Pentru cerinµa 1 se garanteaz existenµa soluµiei
a Pentru 20% din punctaj cerinµa va C 1
a Pentru alte 20% din punctaj cerinµa va C 2 ³i N & 1000
a Pentru restul testelor C 2 ³i N & 1000 000
Exemple:
CAPITOLUL 23. ONI 2017 405
1. Se parcurge ³ierul adlic.in determinându-se primul termen mai mic decât predecesorul
s u - complexitate O n
2. Se formeaz vectorul v în care se reµine ultimul element al sub³irurilor cresc toate. V este
creat descresc tor. La citirea din ³ier elementul curent actualizeaz v înlocuind primul element
mai mic decât el. Dac un asemenea element nu exist se creaz o nou poziµie în v . C utarea în
2
v se face binar. Complexitate nlog n. În cazul c ut rii în n se obµine punctaj parµial.
44 f>>w;
45 k=Bins(1,n,w);
46
47 if(k==n+1)
48 v[++n]= w;
49 else
50 v[k]=w;
51
52 g<<n;
53 }
54
55 return 0;
56 }
60 }
61 }
62
63 g << nrClase << "\n";
64 }
65
66 f.close();
67 g.close();
68
69 return 0;
70 }
62
63 in.close();
64 out.close();
65 return 0;
66 }
23.5 bomboane
Problema 5 - bomboane 100 de puncte
Zeno are n cutii cu bomboane, iar în ecare cutie se g se³te un num r natural nenul de
bomboane. Zeno poate împ rµi bomboanele din toate cutiile colegilor în dou moduri: fr µe³te
sau diferenµiat. împ rµirea fr µeasc se realizeaz astfel:
- num rul de colegi care primesc bomboane din ecare cutie este acela³i (dac din prima cutie
primesc bomboane k colegi ³i din cutia 2 vor primi tot k colegi, ³i din cutia 3 tot k colegi etc).
- bomboanele din ecare cutie se împart în mod egal între cei k colegi, ace³tia primind un
num r nenul de bomboane;
- în nal în ecare cutie trebuie s r mân un num r identic de bomboane (posibil zero) care
îi revin lui Zeno. De exemplu dac n 3, iar în cutii se g sesc 14, 23 respectiv 17 bomboane, din
prima cutie ofer câte 4 bomboane pentru 3 colegi, din a doua cutie câte 7 bomboane pentru 3
colegi, iar din ultima cutie câte 5 bomboane pentru 3 colegi, iar în ecare cutie r mân 2 bomboane.
împ rµirea diferenµiat se realizeaz în felul urm tor:
- dintre colegii care primesc bomboane din aceea³i cutie ecare coleg prime³te un num r diferit
de bomboane (num r nenul), neexistând doi colegi care primesc num r identic de bomboane din
aceea³i cutie;
- din ecare cutie Zeno ofer bomboane unui num r cât mai mare de colegi.
- diferenµele în modul dintre num rul de bomboane primite consecutiv de doi colegi sunt
distincte dou câte dou . De exemplu dac n 3, iar în cutii se g sesc 14, 23 respectiv 17
bomboane, bomboanele din prima cutie se pot împ rµi astfel (3, 4, 6, 1), bomboanele din a doua
cutie (6, 2, 7, 1, 3, 4), iar bomboanele din a treia cutie se pot împ rµi astfel (2, 1, 3, 7, 4).
Cerinµe
Cunoscând n num rul de cutii ³i num rul de bomboane din ecare cutie s se scrie un program
care determin :
a) Num rul maxim de colegi care pot primi bomboane, dac Zeno alege împ rµirea fr µeasc .
b) O modalitate de împ rµire a bomboanelor din ecare cutie, dac se face împ rµirea diferen-
µiat .
Date de intrare
Fi³ierul de intrare bomboane.in conµine pe prima linie dou numere naturale p (num rul
cerinµei de rezolvat), ³i n (num rul de cutii), desp rµite printr-un spaµiu. Pe urm toarea linie se
g sesc n valori naturale, separate prin câte un spaµiu, reprezentând num rul de bomboane din
ecare cutie.
Date de ie³ire
Dac p 1 se va rezolva numai punctul a) din cerinµ . În acest caz ³ierul de ie³ire bom-
boane.out va conµine o valoare natural reprezentând num rul maxim de colegi care pot primi
bomboane, dac Zeno alege împ rµirea fr µeasc .
Dac p 2 se rezolv numai punctul b). Fi³ierul de ie³ire bomboane.out va conµine n linii. Pe
ecare linie i, prima valoare nri reprezint num rul maxim de colegi care pot primi bomboane din
cutia i, urmat de nri valori separate prin câte un spaµiu reprezentând o modalitate de împ rµire
a bomboanelor din cutia i, dac Zeno alege împ rµirea diferenµiat .
Restricµii ³i preciz ri
CAPITOLUL 23. ONI 2017 409
a 1 & p & 2;
Dac p 1 atunci 1 & n & 10 000 ³i 1 & num rul de bomboane din cutii & 10 .
6
a
a Dac p 2 atunci 1 & n & 200 ³i 1 & num rul de bomboane din cutii & 100 000.
a Dac exist mai multe soluµii se poate a³a oricare.
a Pentru rezolvarea ec rei cerinµe se acord 50% din punctaj.
Exemple:
bomboane.in bomboane.outExplicaµii
13 3 Se rezolv numai punctul a). Num rul maxim de colegi care pot
14 23 17 primi bomboane dac Zeno alege împ rµirea fr µeasc e 3.
2 3 14 23 17
43461 Se rezolv numai punctul b). Din prima cutie pot primi bom-
6 6 2 7 1 3 4 boane maxim 4 colegi. O modalitate de împ rµire astfel încât
521374 ecare coleg s primeasc un num r diferit de bomboane, iar
diferenµele dintre bomboanele primite de doi colegi consecutivi
s e distincte dou câte dou este (3,4,6,1). Este corect ³i
soluµia (1, 2, 7, 4).
Timp maxim de executare/test: 0.2 secunde
Memorie: total 16 MB din care pentru stiv 8 MB
Dimensiune maxim a sursei: 10 KB
a) împ rµirea fr µeasc
e a[i] - numarul de bomboane din cutia i
Metoda 1 - 10% din punctajul cerinµei
Se genereaz toate valorile pentru num rul de colegi ³i se veric dac num rul de bomboane
din ecare cutie împ rµit la num rul de colegi d acela³i rest.
Complexitate O(N*max(a[i])
Metoda 2 - 30% din punctajul cerinµei
Se observ c num rul de bomoane care pot r mâne în ecare cutie este cuprins între 0 ³i
min(a[i]).
Complexitate O(N*min(a[i])
Metoda 3 - 100% din punctaj
e a[i] - numarul de bomboane din cutia i
Trebuie determinat un numar k astfel incat ecare a[i] sa dea acelasi rest la impartirea la k.
a[1] = x1 * k + r
a[2] = x2 * k + r
......
a[n] = x3 * k + r
Daca facem diferenta intre oricare doua elemente ale vectorului a[i] si a[j] obtinem:
a[i] - a[j] = xi * k + r - (xj * k + r) = (xi - xj) * k
Prin urmare diferenta intre doua elemente ale vectorului este multiplu de k.
Pentru k maxim acesta va cmmdc(a[1] - a[2], a[2] - a[3], a[3] - a[4] ... a[n-1] - a[n]).
Un algoritmul de rezolvare:
- pentru a evita valori negative se determina min = min(a[1], a[2] ... a[n])
- se scade min din elementele vectorului a[1] = a[1] - min, a[2] = a[2] - min ... a[n] = a[n] - min
- se determina k = cmmdc(a[1], a[2] ... a[n]).
b) împ rµirea diferenµiat
Fie ci numarul maxim de colegi care pot primi bomboane din cutia i
Pentru a determina ci se determina cea mai mare valoare pentru care
ci * (ci + 1) / 2 <= a[i]
Metoda 1 - 30% din punctaj
Se calculeaz num rul maxim de elevi care pot primi bomboane dintr-o cutie. Se observ c
pentru ca acest num r s e maxim trebuie g siµi cei mai mici termeni, respectiv 1, 2, 3 ... Se
încearc formarea unui vector cu num rul de bomboane distribuit. Se procedeaz asem n tor
CAPITOLUL 23. ONI 2017 410
sort rii prin inserµie. Se adaug ultimul termen la sfâr³itul vectorului. Dac se obµine o diferenµ
deja creat , acesta se deplaseaz spre începutul vectorului pân când diferenµele sunt distincte.
Metoda 2
Cea mai simpl modalitate de a a³a o împ rtire este
1 ci 2 ci-1 3 ci-2 .... (de exemplu pt 10 bomboane 1, 4, 2, 3)
La a³area primei perechi trebuie avut în vedere faptul c dac ci * (ci + 1) < a[i] atunci se
a³eaz 1 ³i ci + diferenµa (a[i] - ci * (ci+1) / 2
De exemplu pentru a[i] = 10 se determin ci = 4.
Împ rµirea diferenµiat 1 4 2 3
Pentru a[i] = 12 împ rµirea diferenµiat 1 6 2 3 (prima pereche 1 ³i 4 + 12 - 10)
Algoritmul
Datorit faptului c la ecare pas diferenµa între 2 elemente consecutive scade, se respect
cerinµa ca elementele consecutive s aib diferenµa distinct .
14 return a;
15 }
16
17 int main()
18 {
19 ifstream in("bomboane.in");
20 ofstream out("bomboane.out");
21
22 int p,n,i,k=0,j,nb;
23 long b[10001], c[10001], min, s, r, st, dr;
24 in>>p>>n;
25 // cout<<n<<endl;
26 if(p==1) //cerinta 1
27 {
28 in>>b[1]; min=b[1];
29 for(i=2;i<=n;i++)
30 {
31 in>>b[i];
32 if(b[i]<min)
33 min=b[i];
34 }
35
36 for(i=1;i<=n;i++)
37 b[i]=b[i]-min;
38 i=1;
39 while(b[i]==0)
40 i++;
41 k=b[i];
42 for(i=2;i<=n;i++)
43 if(b[i]!=0)
44 k=cmmdc(k,b[i]);
45 out<<k;
46 }
47 else //cerinta 2
48 {
49 for(i=1;i<=n;i++)
50 {
51 in>>b[i];
52 c[i]=sqrt(2*b[i]);
53 if(c[i]*(c[1]+1)>2*b[i])
54 c[i]--;
55
56 s=0;
57 j=0;
58 do
59 {
60 j++;
61 s=s+j;
62 } while(s<=b[i]);
63
64 if(s==b[i])
65 r=j;
66 else
67 {
68 s=s-j;
69 j--;
70 r=j+b[i]-s;
71 }
72
73 st=1;
74 dr=j;
75 p=1;
76 out<<j<<’ ’;
77 while(st<=dr)
78 {
79 if(p==1)
80 out<<1<<’ ’<<r<<’ ’;
81 else
82 if(st==dr)
83 out<<st<<’ ’;
84 else
85 out<<st<<’ ’<<dr<<’ ’;
86
87 st++;
88 dr--;
89 p++;
CAPITOLUL 23. ONI 2017 413
90 }
91
92 out<<endl;
93 }
94 }
95
96 in.close();
97 out.close();
98 return 0;
99 }
63 return 0;
64 }
23.6 orase
Problema 6 - orase 100 de puncte
În t râmul Jupânului exist N + 1 ora³e. Acestea au fost construite în linie dreapt , începând
cu cel în care este casa Jupânului. Între oricare 2 ora³e consecutive s-a construit câte un drum.
Pentru ecare drum, se cunoa³te lungimea lui, exprimat în metri ³i viteza cu care se poate
parcurge, exprimat în metri pe secund .
Cerinµe
Jupânul trebuie s ajung din ora³ul 0 în ora³ul N .
Acesta ³tie c poate îmbun t µi un drum, m rindu-i viteza de la V metri pe secund la V +
1 metri pe secund , cu costul de 1 dolar. Acesta poate îmbun t µi un drum de mai multe ori.
Jupânul are un buget de X dolari ³i ar vrea s -i foloseasc pentru a mic³ora timpul în care
ajunge din ora³ul 0 în ora³ul N .
Date de intrare
Fi³ierul de intrare orase.in are urm toarea structur :
a Pe prima linie se a num rul T , reprezentând tipul de restricµii pe care îl respect testul.
a Pe a doua linie, se a 2 numere naturale N ³i X .
a Pe a treia linie se a N numere naturale, al i-lea num r reprezentând distanµa între ora³ele
i 1 ³i i.
a Pe a patra linie se a N numere naturale, al i-lea num r reprezentând viteza între ora³ele
i 1 ³i i.
Date de ie³ire
Fi³ierul de ie³ire orase.out va conµine pe prima linie un num r natural R ce reprezint partea
întreag a timpului minim de parcurgere a distanµei dintre ora³ul 0 ³i ora³ul N .
Restricµii ³i preciz ri
1 & N & 5 10
4
a
a 1 & X & 10
7
4
a lungimea drumului dintre oricare 2 ora³e este un num r natural din intervalul 1, 10
4
a viteza iniµial dintre oricare 2 ora³e consecutive este un num r natural din intervalul 1, 10
Tipul 1: pentru 5% din punctaj N & 10 ³i X & 10
Tipul 2: pentru alte 10% din punctaj N & 10 ³i X & 10
3 3
Tipul 3: pentru alte 15% din punctaj 1 & N & 5 10 , 1 & X & 10 , distanµele sunt mai mici
4 4
decât 200 ³i se garanteaz c vitezele nale vor mai mici sau egale decât 1000
Tipul 4: pentru alte 20% din punctaj 1 & N & 5 10 , 1 & X & 10 ³i toate distanµele sunt
4 7
egale
Tipul 5: pentru restul de 50% din punctaj 1 & N & 5 10 ³i 1 & X & 10
4 7
Exemple:
CAPITOLUL 23. ONI 2017 415
Velea Alexandru
Structura solutiei
1) Observaµii generale
2) Soluµie în O N X - 15 puncte
3) Soluµie restricµii de tipul 3 - 15 puncte
4) Soluµie restricµii de tipul 4 - 20 puncte
5) Soluµia ocial - 100 puncte
Pentru un drum care are lungime D ³i viteza V, timpul de deplasare este de D/V
Dac m rim viteza drumului de la V la (V+1), timpul de deplasare devine D/(V+1)
Astfel, timpul salvat în urma m ririi vitezei este de (D/V) - (D/(V+1)) = D/(V*(V+1))
Se observ c prima îmbun t µire salveaz D/(V*(V+1)) secunde, a doua îmbun t µire
D/((V+1)*(V+2)), etc
Astfel, ecare îmbun t µire salveaz din ce în ce mai puµin timp.
2) Soluµie în O N X
Folosind observaµiile de la punctul 1, putem alege o strategie greedy de îmbun t µire a drumu-
rilor.
Dac am avea de f cut o singur îmbun t µire, am alege s o facem pe drumulul unde aceasta
ar salva cât mai mult timp.
Acesta ind drumul cu D/(V*(V+1)) maxim.
Astfel, putem demonstra c tot timpul este bine s alegem s îmbun t µim drumul care ne
salveaz cât mai mult timp.
Dac am avea de f cut doar o îmbun t µire, e bine s alegem acel drum. Dup ce l-am ales,
urm toarea îmbun t µire va mai mic decât cea precedent , iar acest lucru ne garanteaz faptul
c dac am putea s facem acest lucru acum, nu am avea niciun motiv s facem îmbun t µirea pe
drumul respectiv mai tarziu.
Iteram de X ori peste toate drumurile, la ecare pas alegem drumul care salveaz cel mai mult
timp ³i îl îmbun t µim.
3) Soluµia pentru tipul 3
Observ m c dac am vrea s îmbun t µim un drum care are distanµa D, este cel mai bine s
îmbun t µim drumul care are viteza minim , pentru a maximiza timpul câ³tigat.
Astfel, faptul c distanµele sunt mai mici decât 200, permite o optimizare a algoritmului de la
pasul 2.
În loc s iter m la ecare pas prin toate drumurile ³i s îl alegem pe cel care salveaz cât mai
mult timp, putem itera prin distanµele drumurilor, a m care este viteza minim a unui drum
cu distanµa respectiv , iar mai apoi îmbun t µim unul dintre drumurile care aveau viteza minim
pentru distanµa xat (este posibil s e mai multe astfel de drumuri)
Astfel, ecare îmbun t µire se poate realiza în 200 de iteraµii, nu în N (50 000).
CAPITOLUL 23. ONI 2017 416
Pentru a aa drumul de vitez minim pentru o distanµ xat , putem s reµinem drumurile
într-o matrice de frecvenµe
drumuri[d][v] reprezentând câte drumuri au distanµa d ³i viteza v
mai µinem un ³ir viteza_minima[d] reprezentând cea mai mic vitez a unui drum cu distanµa
d
- echivalent cu prima valoare v pentru care drumuri[d][v] are o valoare nenul .
Dac la un pas am ales s îmbun t µim un drum care are distanµa d ³i viteza v, trebuie s
mic³or m num rul de drumuri cu viteza v: drumuri[d][v] -= 1
M rim num rul de drumuri cu viteza (v + 1): drumuri[d][v + 1] += 1
* dac nu mai avem drumuri cu viteza v, m rim viteza_minima[d]:
if (drumuri[d][v] == 0) { viteza\_minima[d] += 1; }
4) Soluµia pentru tipul 4
Asem n tor cu tipul 3, doar c aici distanµele nu sunt pân în 200, ci toate distanµele sunt
egale.
Astfel, ne intereseaz doar vitezele, distanµa ind necesar doar la calcularea rezultatului.
O soluµie ar s µinem un ³ir de frecvenµe pentru ecare vitez , ³i s aplic m urm torul
algoritm:
int i = 1;
while (x)
{
if (frecventa[i] > x)
{
frecventa[i + 1] += frecventa[i];
x -= frecventa[i];
frecventa[i] = 0;
}
else
{
frecventa[i] -= x;
frecventa[i + 1] += x;
x = 0;
}
i += 1;
}
O astfel de soluµie se comport foarte bine când valoarea lui N este mare, dar dac N = 1, de
exemplu, ar face X pa³i.
Ca s sc p m de cazul acesta, am putea c uta binar cea mai mic vitez .
Astfel putem aa câte îmbun t µiri trebuie s facem: suma_din(max(0, viteza_cautata_binar
- viteza[i]))
Dac num rul de îmbun t µiri dep ³e³te X, reducem viteza, altfel o m rim.
La nal, îmbun t µim toate drumurile <= viteza c utat pâna la ea, ³i mai îmbun t µim unele
drumuri cu acea vitez (nu le putem îmbun t µi pe toate) dac mai avem îmbun t µiri r mase.
5) Soluµia ocial
Privind ideile de la punctul 1, am putea încerca s c utam binar valoarea ultimului timp salvat.
Not m ultimul timp salvat cu T
Astfel, am putea calcula pentru un drum de câte ori trebuie s îl îmbun t µim, ajungând la
viteza V, astfel încât îmbun t µirea de la V la V+1 s e < T
Acest lucru se poate rezolva tot cu o c utare binar a num rului vitezei, sau folosind o ecuaµie
de gradul 2
Not m cu D distanµa drumului; trebuie s îi g sim viteza V
D / (V * (V + 1)) < T
D / T < V * (V + 1))
0 < V * V + V - D / T
0 = V * V + V - D / T
delta = 1 + 4 * D / T
V1,2 = (-1 +- sqrt(1 + 4 * D / T)) / 2
39 }
40 };
41
42 int64 x;
43 vector<Road> roads;
44
45 int Read()
46 {
47 ifstream cin("orase.in");
48 int test_type;
49 cin >> test_type;
50
51 int n;
52 cin >> n >> x;
53
54 roads.resize(n);
55
56 for (int i = 0; i < n; i += 1)
57 roads[i].id = i;
58
59 for (auto& itr : roads)
60 cin >> itr.distance;
61
62 for (auto& itr : roads)
63 cin >> itr.speed;
64
65 return 1;
66 }
67
68 int is_read = Read();
69
70 int64 UpgradeRoad(int index, long double saved_time)
71 {
72 return max(0LL,
73 int64(1.0 + -0.5 +
74 sqrt(1.0+4.0*roads[index].distance / saved_time) / 2.0 +
75 1e-10) -
76 roads[index].speed);
77 }
78
79 vector<int64> GetUpgrades(long double saved_time)
80 {
81 vector<int64> answer(roads.size(), 0);
82
83 for (int i = 0; i < (int)roads.size(); i += 1)
84 answer[i] = UpgradeRoad(i, saved_time);
85
86 return answer;
87 }
88
89 int64 GetNumOperations(long double saved_time)
90 {
91 auto upgrades = GetUpgrades(saved_time);
92
93 int64 answer = 0;
94 for (auto itr : upgrades)
95 answer += itr;
96
97 return answer;
98 }
99
100 long double EstimateSolution()
101 {
102 long double mx_save = 0;
103 for (auto& itr : roads)
104 mx_save = max(mx_save, itr.SavedTime());
105
106 long double left = 0, right = mx_save;
107
108 int64 mx_upgrades = 0;
109 long double mx_where = 0;
110
111 int64 mn_upgrades = 1e9;
112 long double mn_where = 0;
113
114 for (int i = 0; i < 100; i += 1)
CAPITOLUL 23. ONI 2017 419
115 {
116 long double mid = (right + left) / 2;
117 int64 num_operations = GetNumOperations(mid);
118
119 if (num_operations == x)
120 {
121 mx_upgrades = num_operations;
122 mx_where = mid;
123 break;
124 }
125
126 if (num_operations > x)
127 {
128 left = mid;
129
130 if (mn_upgrades >= num_operations)
131 {
132 mn_upgrades = num_operations;
133 mn_where = mid;
134 }
135 }
136 else
137 {
138 right = mid;
139
140 if (mx_upgrades <= num_operations)
141 {
142 mx_upgrades = num_operations;
143 mx_where = mid;
144 }
145 }
146 }
147
148 auto upgrades = GetUpgrades(mx_where);
149
150 int64 sum = 0;
151 for (int i = 0; i < (int)roads.size(); i += 1)
152 {
153 roads[i].speed += upgrades[i];
154 sum += upgrades[i];
155 }
156
157 x -= sum;
158
159 double answer = 0;
160 for (auto& itr : roads)
161 answer += itr.Time();
162
163 answer -= 1.0 * mx_where * x;
164
165 return answer;
166 }
167
168 long double Solve()
169 {
170 return EstimateSolution();
171 }
172
173 int main()
174 {
175 long double answer = Solve();
176
177 ofstream cout("orase.out");
178 cout << int64(answer) << ’\n’;
179
180 return 0;
181 }
ONI 2016
24.1 civilizatie
Problema 1 - civilizatie 100 de puncte
În vremuri str vechi P mântul era locuit de c tre o civilizaµie neobi³nuit condus dup reguli
matematice foarte riguroase. Aceast civilizaµie era format din mai multe ora³e-stat asemeni
ora³elor antice. Fiecare ora³ s-a dezvoltat treptat pornind de la un singur cartier de form p trat
cu suprafaµa de un hectar, în jurul c ruia se ad ugau în ecare an cartiere de câte un hectar
ecare în felul urm tor: în primul an s-a format cartierul iniµial, în al doilea an ora³ul s-a extins
formând patru noi cartiere în toate cele patru puncte cardinale, în anul urm tor ora³ul s-a extins
cu 8 noi cartiere dispuse în jurul cartierelor deja formate, ³i a³a mai departe, în ecare an ora³ul
extinzându-se cu înc un rând de cartiere.
Extinderea unui ora³ se opre³te când întâlne³te un alt ora³ sau dac , de³i nu a întâlnit înc
un alt ora³, ajunge la marginea h rµii pe oricare dintre cele patru puncte cardinale. Dou ora³e
se întâlnesc când suprafeµele ocupate de ele ajung s se ating sau între cartierele marginale ale
celor dou ora³e se mai a doar un hectar.
Cerinµe
1. Dimensiunea suprafeµei (în hectare) pe care ar ocupa-o dup t ani, dac nu ar întâlni nici
un alt ora³ ³i nici nu ar ajunge la marginea h rµii.
420
CAPITOLUL 24. ONI 2016 421
2. Timpul scurs pân când toate cele N ora³e ³i-au încetat extinderea, început din cartierele
iniµiale ale c ror coordonate se citesc din ³ier, ³i aria suprafeµei din hart r mas neocupat ,
exprimat în hectare.
Date de intrare
Fi³ierul de intrare civilizatie.in conµine pe prima linie un num r natural p. Pentru toate
testele de intrare, p poate avea doar valoarea 1 sau valoarea 2.
A doua linie a ³ierului conµine dou numere naturale x ³i y reprezentând dimensiunile h rµii.
A treia linie a ³ierului conµine num rul natural t.
A patra linie a ³ierului conµine num rul natural N .
Pe urm toarele N linii se g sesc câte dou numere i ³i j reprezentând coordonatele iniµiale ale
celor N ora³e.
Date de ie³ire
Dac valoarea lui p este 1, atunci se va rezolva numai prima cerinµ .
În acest caz, în ³ierul de ie³ire civilizatie.out se va scrie un singur num r natural, reprezen-
tând aria suprafeµei (în hectare) unui ora³ dup t ani, dac nu ar întâlni nici un alt ora³ ³i nici nu
ar ajunge la marginea h rµii.
Dac valoarea lui p este 2 atunci, se va rezolva numai a doua cerinµ .
În acest caz, ³ierul de ie³ire va conµine pe prima linie un num r natural reprezentând aria
suprafeµei din hart r mas neocupat dup ce toate cele N ora³e ³i-au încetat expansiunea, iar
pe a doua linie un num r natural reprezentând timpul scurs pân când ultimul ora³ s-a oprit din
expansiune.
Restricµii ³i preciz ri
a 1 & N & 2000
a 1 & x, y, t & 100 000
a Pentru 30% din teste se garanteaz faptul c x, y & 500
a Pentru rezolvarea corect a primei cerinµe se acord 20 de puncte, iar pentru rezolvarea
corect a celei de-a doua cerinµe se acord 80 de puncte.
Exemple:
civilizatie.in civilizatie.out Explicaµii
1 145 p = 1, în ³ier se va scrie aria suprafeµei ce ar putea ocupat
79 de un ora³ în timp de 9 ani.
9 Atenµie! Pentru acest test se rezolv doar cerinµa 1).
2
32
46
2 33
79 4
5
2
32
46
2 97 p=2, deci se rezolv doar cerinµa 2
10 10 1 în acest caz, cele 3 civilizaµii nu se vor putea extinde deloc, deci
5 celelalte 97 de hectare r mân neocupate.
3
22
24
32
Timp maxim de executare/test: 3.0 secunde
Memorie: total 128 MB
Dimensiune maxim a sursei: 15 KB
CAPITOLUL 24. ONI 2016 422
Cerinµa 1 - Soluµia 1
Consider m un tablou bidimensional, în care ecare hectar este un element al tabloului.
În acest tablou consider m coordonatele de origine ale ora³ului în mijlocul tabloului.
pentru t=1 coordonatele noilor cartiere sunt chiar coordonatele iniµiale;
pentru t=2 coordonatele noilor cartiere sunt date de: |x-x0|+|y-y0|=1;
pentru t=3 coordonatele noilor cartiere sunt date de: |x-x0|+|y-y0|=2;
...
pentru cazul general |x-x0|+|y-y0|=t-1;
În concluzie num rul de cuburi din ecare romb se poate calcula dup formula:
1+4+8+12+16+...+4(k-1)=
1+4(1+2+3+4+...+k-1)=
1+4k(k-1)/2=
1+2k(k-1)
Cerinµa 2 - Soluµia 1
Folosim un tablou bidimensional de dimensiune N N în care reµinem dup câµi ani s-ar
întâlnii ora³ele dou câte dou ignorându-le pe toate celelalte (îniµial punctul de întâlnire va la
jum tatea drumului).
Folosim un tablou unidimensional de dimensiune N în care reµinem cel mai mic num r de ani
dup care un ora³ ar ajunge la una dintre margini.
Alegem pe baza acestor dou tablouri ora³ele care se opresc primele ³i recalcul m momentele
de întânire ale acestor ora³e cu toate celelalte (întâlnirea nu va mai pentru toate la jum tatea
drumului).
Relu m acest procedeu cu cele r mase pân când alegem toate civilizaµiile.
3
Complexitate O N
Cerinµa 2 - Soluµia 2
Pentru a reduce timpul de execuµie folosim un tablou unidimensional în care reµinem minimele
pe linii. Aceste minime le actualiz m atunci când recalcul m momentele de întalnire dintre ora³ele
alese ³i celelalte ora³e.
6
7 #define cin fin
8
9 using namespace std;
10
11 typedef pair<int, int> Pair;
12
13 const int MAXN = 2005;
14 const int MAXD = 1e6 + 1;
15
16 int Stopped[MAXN], X[MAXN], Y[MAXN], T[MAXN][MAXN];
17 vector<Pair> Meets[MAXD];
18
19 int maxx, maxy, n, now;
20 long long Extend[MAXD];
21 vector<int> ToStop;
22
23 int getTime(int i, int j)
24 {
25 if(j == 0)
26 return min(min(X[i], Y[i]), min(maxx - X[i] + 1, maxy - Y[i] + 1));
27
28 int d = abs(X[i] - X[j]) + abs(Y[i] - Y[j]);
29 if(Stopped[j] >= 0)
30 return d - Stopped[j] + 1;
31 return (1 + d) / 2;
32 }
33
34 void addEvent(int i, int j)
35 {
36 int t = getTime(i, j);
37 Meets[t].push_back(make_pair(i, j));
38 }
39
40 int main()
41 {
42 int p, t;
43
44 ifstream cin("civilizatie.in");
45 ofstream cout("civilizatie.out");
46
47 cin >> p;
48 cin >> maxx >> maxy;
49 Extend[1] = 1;
50 for(int i = 2; i < MAXD; ++i)
51 Extend[i] = Extend[i - 1] + 4 * i - 4;
52
53 cin >> t;
54 if(p == 1)
55 {
56 cout << Extend[t];
57 return 0;
58 }
59 else
60 {
61 cin >> n;
62
63 for(int i = 1; i <= n; ++i)
64 {
65 cin >> X[i] >> Y[i];
66 Stopped[i] = -1;
67 }
68
69 for(int i = 1; i <= n; ++i)
70 for(int j = n; j >= 0; --j)
71 if(i != j)
72 addEvent(i, j);
73
74 int cnt = n;
75 for(now = 1; cnt; ++now)
76 {
77 for(int z = 0; z < Meets[now].size(); ++z)
78 {
79 Pair p = Meets[now][z];
80 if(Stopped[p.first] == -1 &&
81 now == getTime(p.first, p.second))
CAPITOLUL 24. ONI 2016 424
82 {
83 ToStop.push_back(p.first);
84 }
85 }
86
87 for(int i = 0; i < ToStop.size(); ++i)
88 {
89 int no = ToStop[i];
90 if(Stopped[no] >= 0) continue;
91
92 Stopped[no] = now;
93 --cnt;
94
95 for(int j = 1; j <= n; ++j)
96 if(Stopped[j] == -1)
97 addEvent(j, no);
98 }
99
100 ToStop.clear();
101 }
102
103 long long ans = 1LL * maxx * maxy;
104 for(int i = 1; i <= n; ++i)
105 ans -= Extend[Stopped[i]];
106 }
107
108 return 0;
109 }
45 for(int i=1;i<=n;i++)
46 {
47 lMin[i]=nx+ny;
48 for(int j=1;j<=n;j++)
49 {
50 difMin[i][j]=abs(x[i]-x[j])+abs(y[i]-y[j])+1;
51 difMin2[i][j]=difMin[i][j]/2;
52 if(difMin2[i][j]<lMin[i] && i!=j)
53 {
54 lMin[i]=difMin2[i][j];jlMin[i]=j;
55 }
56 }
57 }
58
59 // selectare orase in ordinea opriri expansiunii
60 int nr=0;
61 while(nr<n)
62 {
63 // cautare minim
64 int mMin=nx+ny,iMin,jMin,im=0;
65 for(int i=1;i<=n;i++)
66 {
67 if(mMin>lMin[i] && !dMin[i])
68 {
69 mMin=lMin[i];iMin=i;jMin=jlMin[i];im=0;
70 }
71 if(mMin>dxyMin[i] && !dMin[i])
72 {
73 mMin=dxyMin[i];im=i;
74 }
75 }
76
77 // calcul timp de oprire oras selectat si ajustare timpi
78 // pentru celelalte
79 int i=iMin,j=jMin;
80 if(im!=0)
81 {
82 i=im;dMin[i]=dxyMin[i];
83 }
84 else
85 {
86 if(dMin[i])
87 { // civilizatia i verificata deja
88 i=jMin;j=iMin;
89 }
90
91 dMin[i]=difMin2[i][j];
92 }
93
94 nr++;
95 lMin[i]=nx+ny;
96 for(int k=1;k<=n;k++) // pt toate elementele de pe col i
97 if(!dMin[k] || !dMin[i])
98 if(difMin2[k][i]!=dMin[i])
99 {
100 difMin2[k][i]=difMin2[i][k]=difMin[k][i]-dMin[i];
101 if(difMin2[k][i]<lMin[i] &&
102 k!=i &&
103 (!dMin[k] || !dMin[i]))
104 {
105 lMin[i]=difMin2[k][i];jlMin[i]=k;
106 }
107 if(jlMin[k]==i)
108 {
109 lMin[k]=nx+ny;
110 for(int ik=1;ik<=n;ik++) // pt toate elementele
111 // de pe linia k
112 if(difMin2[k][ik]<lMin[k] && k!=ik )
113 {
114 lMin[k]=difMin2[k][ik];jlMin[k]=ik;
115 }
116 }
117 }
118 }
119
120 // calcul suprafete
CAPITOLUL 24. ONI 2016 426
24.2 cmmdc
Problema 2 - cmmdc 100 de puncte
Fie un ³ir de numere naturale nenule a1 , a2 , ..., an ³i un num r natural k .
Cerinµe
S se determine un grup de k numere din ³ir care au proprietatea ca cel mai mare divizor
comun al lor este maxim. Dac exist mai multe astfel de grupuri, se cere acel grup pentru care
suma elementelor este maxim .
Date de intrare
Fi³ierul cmmdc.in conµine pe prima linie numerele naturale n ³i k separate prin spaµiu. Pe
linia a doua se g sesc numerele naturale a1 , a2 , ..., an separate prin câte un spaµiu.
Date de ie³ire
Fi³ierul cmmdc.out conµine pe prima linie un num r natural reprezentând cel mai mare
divizor comun a exact k numere din ³ir, maxim posibil. Pe linia a doua, separate prin câte un
spaµiu ³i ordonate descresc tor, se a cele k numere din ³ir care dau cel mai mare divizor comun
maxim.
Restricµii ³i preciz ri
a 1 & n & 1 000 000
a 2 & k & 100 000
a k&n
a 1 & ai & 1 000 000, i 1..n
a Valorile din ³ir se pot repeta.
Exemple:
cmmdc.in cmmdc.out Explicaµii
63 3 Cel mai mare divizor comun care se poate obµine dintr-un grup
6 9 8 10 15 3 15 9 6 de 3 numere este 3, iar cele 3 numere care dau suma maxim ,
ordonate descresc tor, sunt 15, 9 ³i 6.
Timp maxim de executare/test: 1.0 secunde
Memorie: total 64 MB
Dimensiune maxim a sursei: 15 KB
CAPITOLUL 24. ONI 2016 427
Se construie³te un vector de frecvenµe (v i = de câte ori apare i în sirul de numere dat);
Se face rationamentul urmator: dac k numere au cmmdc-ul egal cu x, atunci ele sunt e egale
cu x, e sunt multiplii ai numarului x.
Astefel se parcurge cu o variabila x descrescator intervalul 1 000 000 2 si pentru ecare
valoare a lui x se determina daca exista cel putin k numere egale cu x sau multiplii de-i lui x, cu
un algoritm asemanator cu Ciurul lui Eratostene.
Aceasta determinare se face parcurgand multiplii lui x descrescator, astfel prima submultime
determinata este solutia ceruta. Cel mai mare multiplu a lui x care teoretic poate sa apara printre
cele n numere se poate calcula in functie de valoarea maxima din sirul a (notata max a si care
oricum nu depaseste 1 000 000).
Complexitate:
O n pentru constructia vectorului v .
O max a log max a pentru determinarea rezultatului (unde max a e maximul din sirul
a)
Expresia de mai sus e aproximarea pentru:
30 if(FreqFact[i] >= k)
31 {
32 fout << i << endl;
33 for(int j = maxx / i * i; j; j -= i)
34 while(Freq[j] > 0)
35 {
36 fout << j << " ";
37 if(--k == 0)
38 return 0;
39 --Freq[j];
40 }
41 }
42
43 return 0;
44 }
24.3 livada
Problema 3 - livada 100 de puncte
Fermierul Quinto are o livad plin cu pomi fructiferi. Livada are N rânduri, numerotate de
la 1 la N , pe ecare rând aându-se câte M pomi fructiferi, numerotaµi de la 1 la M . Livada lui
Quinto este una special , a³a c pentru unii pomi se cunoa³te cantitatea de fructe (exprimat în
kg) care poate culeas , iar pentru alµii aceasta poate determinat pe baza unei formule.
Quinto ³i-a propus s recolteze C kg de fructe din pomii aaµi în livada lui. Acesta folose³te un
utilaj modern pentru culesul fructelor. Utilajul poate folosit pe oricare din rândurile livezii, dar
poate aduna doar fructele dintr-un ³ir consecutiv de pomi, începând cu primul pom de pe rândul
respectiv, neavând posibilitatea de a culege parµial fructele dintr-un pom.
Preocupat de frumuseµea livezii sale, Quinto s-a gândit la restricµii suplimentare pentru re-
coltarea cantit µii C de fructe. Astfel, el dore³te s adune fructele din pomi de pe maximum R
rânduri diferite, pentru ca N R rânduri s r mân complete.
Deasemenea, el dore³te s culeag cu prioritate pomii care au o cantitate cât mai mic de
fructe, pentru ca în livad s r mân cei mai roditori pomi. Quinto ³i-a dat seama c este dicil
s culeag x C kg de fructe, prin urmare este mulµumit ³i cu o cantitate mai mare, care respect
celelalte condiµii impuse de el.
Cerinµe
Determinaµi cea mai mic valoare X posibil astfel încât s se poat culege, în condiµiile de
mai sus, o cantitate de cel puµin C kg de fructe ³i orice pom din care se culeg fructe s conµin
cel mult X kg de fructe.
Date de intrare
Pe prima linie a ³ierului livada.in se a 4 numere naturale N , M , C , R cu semnicaµia din
enunµ.
Pe a doua linie din ³ierul de intrare se a 5 numere naturale x, y , z , w, u, separate printr-un
spaµiu.
Dac not m cu Aij cantitatea de fructe (exprimat în kg) din cel de-al j -lea pom de pe
linia i, atunci:
Linia a treia din ³ierul de intrare conµine M valori A1i, 1 & i & M , separate printr-un
spaµiu
Linia a patra din ³ierul de intrare conµine N 1 valori Ai1, 2 & i & N , separate printr-un
spaµiu
Celelalte valori Aij , 2 & i & N , 2 & j & M , se calculeaz conform formulei:
Date de ie³ire
CAPITOLUL 24. ONI 2016 429
Fi³ierul de ie³ire livada.out va conµine o singur valoare scris pe prima linie, care reprezint
cea mai mic valoare a cantit µii de fructe (exprimat în kg) dintr-un pom cules, astfel încât s
e respectate toate restricµiile problemei.
Restricµii ³i preciz ri
a 1 & R & N & 100
a 1 & M & 25 000
a 0 & x, y, z, w, u & 10
9
a Atenµie la determinarea ec rei valori Aij pentru c în formul sunt produse care pot
32
s furnizeze valori mai mari decât 2 1.
a 1 & C & 10
18
Exemple:
livada.in livada.out Explicaµii
5 6 18 4 3 6 5 4 Sunt 5 rânduri cu câte 6 pomi pe ecare rând. Figura al turat
2741351 arat matricea care se obµine conform formulelor precizate.
25263 Se dore³te culegerea a cel puµin 18 de kg de fructe de pe maxim
4 rânduri din cele 5.
în gura al turat , este prezentat o soluµie
posibil în care cantitatea maxim culeas
dintr-un pom este de 4 kg.
Nu se pot culege 18 de kg de fructe de pe
maxim 4 rânduri astfel încât s e cule³i doar pomi cu cantitate
de fructe 3kg (în acest caz se pot culege cel mult 8 kg).
Timp maxim de executare/test: 0.5 secunde
Memorie: total 64 MB
Dimensiune maxim a sursei: 15 KB
Problema se rezolv prin c utarea soluµiei (c utare binar sau secvenµial ). Se caut cantitatea
minim de fructe culeas dintr-un singur pom fructifer (se veric pe rând valori posibile ³i se
alege valoarea minim care respect restricµiile problemei).
Soluµii parµiale 30 / 70 puncte
Odat xat valoarea pentru cantitatea maxim de kg de fructe culese dintr-un singur pom,
se determin cantitatea maxim de fructe care poate culeas din întreaga livad astfel încât s
e respectate restricµiile problemei.
Aceast valoare poate aat dac se determin pentru ecare rând cantitatea maxim de
fructe care poate culeas din pomii de pe acel rând, însumând pe rând valorile de pe acest rând
pân la prima valoare mai mare decât valoarea xat , ³i se memoreaz aceste valori într-un vector,
2
care este apoi sortat descresc tor. Este sucient un algoritm de sortare de complexitate O N .
Se însumeaz apoi primele R valori din vectorul sortat, aceast sum reprezentând cantitatea
maxim de fructe care pot adunate din livad .
Dup determinarea cantit µii maxime care poate culeas din întreaga livad , se veric dac
aceasta este cel puµin egal cu cantitatea C cerut în enunµ.
O implementare a ideii de mai sus care folose³te c utarea secvenµial a soluµiei obµine 30
puncte, complexitatea algoritmului ind O N M M axV al, unde N e num rul de rânduri,
M e num rul de pomi de pe ecare rând, iar M axV al e cea mai mare cantitate de fructe dintr-un
singur pom.
O implementare a ideii de mai sus care folose³te c utarea binar a soluµiei obµine 70 puncte,
complexitatea algoritmului ind O N M log M axV al.
CAPITOLUL 24. ONI 2016 430
19 {
20 long long x,y,z,w,u;
21
22 fin>>N>>M>>C>>R;
23 fin>>x>>y>>z>>w>>u;
24
25 for(int i = 1; i<=M; i++)
26 fin>>A[1][i];
27
28 for(int i = 2; i<=N; i++)
29 fin>>A[i][1];
30
31 for(int i = 2; i <= N; ++i)
32 for(int j = 2; j <= M; ++j)
33 A[i][j] = (x * A[i - 1][j] +
34 y * A[i][j - 1] +
35 z * A[i - 1][j - 1] +
36 w) % u;
37
38 }
39
40 void Precalculate()
41 {
42 for(int i = 1; i <= N; ++i)
43 for(int j = 1; j <= M; ++j)
44 {
45 Sum[i][j] = A[i][j] + Sum[i][j-1];
46 Max[i][j] = max(Max[i][j-1],A[i][j]);
47 }
48 }
49
50 long long Find(int i, int Value)
51 {
52 long long Crop = 0;
53
54 int Left = 1, Right = M;
55
56 while(Left <= Right)
57 {
58 int Mid = (Left+Right) / 2;
59 if(Max[i][Mid] <= Value)
60 {
61 Crop = Sum[i][Mid];
62 Left = Mid + 1;
63 }
64 else
65 Right = Mid - 1;
66 }
67 return Crop;
68 }
69
70 bool Check(int Value)
71 {
72 long long V[NMax],k = 0;
73
74 for(int i = 1; i <= N; i++)
75 V[++k] = Find(i,Value);
76
77 sort(V+1,V+k+1,greater<long long>());
78
79 long long Total = 0;
80
81 for(int i = 1; i<=R && i<=k; i++)
82 Total+=V[i];
83
84 return (Total >= C);
85 }
86
87 void Solve()
88 {
89 int Left = 1, Right = MaxVal;
90 while(Left <= Right)
91 {
92 int Mid = (Left + Right) / 2;
93
94 if(Check(Mid))
CAPITOLUL 24. ONI 2016 433
95 {
96 Sol = Mid;
97 Right = Mid - 1;
98 }
99 else
100 Left = Mid + 1;
101 }
102 }
103
104 void Print()
105 {
106 fout<<Sol<<"\n";
107 }
108
109 int main()
110 {
111 Read();
112 Precalculate();
113 Solve();
114 Print();
115 return 0;
116 }
24.4 dif2
Problema 4 - dif2 100 de puncte
Sandu a studiat la ora de informatic mai multe aplicaµii cu vectori de numere naturale, iar
acum are de rezolvat o problem interesant . Se d un ³ir X X1 , X2 , ..., Xn de numere naturale
nenule ³i dou numere naturale p1 ³i p2 , unde p1 $ p2 . Sandu trebuie s construiasc un nou ³ir
Y Y1 , Y2 , ..., Ynn cu n n elemente obµinute din toate produsele de câte dou elemente din
³irul X (ecare element din ³irul Y este de forma Xi Xj , 1 & i,j & n). Sandu are de calculat dou
valori naturale d1 ³i d2 obµinute din ³irul Y . Valoarea d1 este egal cu diferenµa maxim posibil
dintre dou valori ale ³irului Y . Pentru a obµine valoarea d2 , Sandu trebuie s considere c ³irul
Y are elementele ordonate descresc tor iar d2 va diferenµa dintre valorile aate pe poziµiile p1
³i p2 în ³irul ordonat descresc tor. Sandu a g sit rapid valorile d1 ³i d2 ³i, pentru a le verica, v
roag s le determinaµi ³i voi.
Cerinµe
Dându-se ³irul X cu n elemente ³i valorile p1 ³i p2 , determinaµi valorile d1 ³i d2 .
Date de intrare
Fi³ierul de intrare dif2.in va conµine pe prima linie un num r natural C care poate doar
1 sau 2. Dac C 1, atunci pe linia a doua se va aa num rul natural n. Dac C 2, atunci
pe linia a doua se vor aa numerele naturale n, p1 ³i p2 separate prin câte un spaµiu. în ambele
cazuri, pe urm toarele n linii se vor aa elementele ³irului X , câte un num r natural pe ecare
linie a ³ierului.
Date de ie³ire
În cazul C 1, ³ierul de ie³ire dif2.out va conµine pe prima linie valoarea d1 egal cu
diferenµa maxim dintre oricare dou valori din ³irul Y . în cazul C 2 ³ierul de ie³ire va conµine
pe prima linie un num r natural d2 reprezentând diferenµa dintre valorile aate pe poziµiile p1 ³i
p2 din ³irul Y , presupunând c ar ordonat descresc tor.
Restricµii ³i preciz ri
a 3 $ n $ 300 000
a 1 & p1 $ p2 & n2
a 1 & Xi $ 300 000, i 1..n
CAPITOLUL 24. ONI 2016 434
a Pentru teste valorând 30 de puncte vom avea C 1, iar pentru teste valorând 70 de puncte
vom avea C 2.
a Pentru teste valorând 10 puncte vom avea C 2 ³i n & 100
Exemple:
dif2.in dif2.out Explicaµii
1 32 Atenµie, C 1, deci se rezolv doar cerinµa 1!
4 Valoarea maxim d1 va 32 ³i se obµine efectuând diferenµa
3 dintre 6*6 ³i 2*2.
5
2
6
2 8 Atenµie, C 2, deci se rezolv doar cerinµa 2!
4 5 11 Se obµin în Y urm toarele 16 valori: 3*3, 3*5, 3*2, 3*6, 5*3,
3 5*5, 5*2, 5*6, 2*3, 2*5, 2*2, 2*6, 6*3, 6*5, 6*2, 6*6.
5 Valoarea d2 va 8, deoarece dac vom considera ³irul Y ordonat
2 descresc tor (36, 30, 30, 25, 18, 18, 15, 15, 12, 12, 10, 10, 9, 6,
6 6, 4), atunci Y[5]-Y[11]=18-10=8
Timp maxim de executare/test: 2.0 secunde
Memorie: total 16 MB
Dimensiune maxim a sursei: 15 KB
Se observ c valoarea d1 este egal cu diferenµa dintre valoarea maxim ³i valoarea minim a
elementelor din ³irul Y . Se pot calcula valorile extreme ale elementelor lui X iar d1 va diferenµa
p tratelor lor.
Pentru d2 nu se poate construi ³irul Y ³i apoi s se ordoneze descresc tor deoarece exist o
2
limitare a memoriei disponibile ³i algoritmi k log k pentru sortare (k n ).
2
Voi prezenta un algoritm de complexitate O DIMn n log DIMV , unde DIMV este valoarea
maxima din X .
Se vor num ra câte perechi de elemente din X au valoarea mai mic sau egal decât i. Se
poate face num rarea în O n dac vom precalcula un sir ci cu num rul de valori din X mai
mici sau egale cu i.
Pentru a aa pe ce poziµie va un produs p, vom utiliza ³irul c precalculat ³i vom num r
pentru ecare element din ³ir câte elemente contribuie la construirea unei valori ce nu dep ³e³te
p.
Vom utiliza c utarea binar pentru determinarea celor dou valori. Nu e necesar s facem
sort ri descresc toare, se deduce u³or poziµia necesar dac vom face calculul în cazul ordon rii
cresc toare.
Soluµia comisiei (studenµi LUCIAN BICSI ³i PETRU-ERIC STAVARACHE)
Soluµie O(V logV):
inem un vector de frecvenµ f req i pentru valorile elementelor împreun cu sume parµiale
pe pe acest vector Sumi.
prexe
Pentru a aa produsul aat pe o poziµie Z , c ut m binar produsul, iar pentru un produs P
xat trebuie sa vedem câte perechi (a, b) exista cu a b & P .
Pentru asta vom parcurge ecare valoare posibila, iar pentru o valoare A xata deducem ca
B & P ©A. A³adar toate elementele cu valoarea cel mult B vor forma perechi posibile împreun
cu A. Vor exista f A SumB astfel de perechi.
Dac num rul total de perechi de acest fel este & Z , atunci soluµia ' P .
Solutie O N log2 V :
Similar cu soluµia anterioara, doar ca in loc sa µinem un vector de frecventa, sortam vectorul
iniµial.
CAPITOLUL 24. ONI 2016 435
48
49 int t;
50 long long a, b;
51
52 Read(t);
53 Read(n);
54
55 if(t == 2)
56 {
57 Read(a);
58 Read(b);
59 }
60
61 for(int i = 1; i <= n; ++i)
62 Read(V[i]);
63
64 sort(V + 1, V + n + 1);
65
66 if(t == 1)
67 cout << 1LL * V[n] * V[n] - 1LL * V[1] * V[1] << endl;
68 else
69 cout << kth(1LL * n * n - a + 1) - kth(1LL * n * n - b + 1) << endl;
70
71 return 0;
72 }
24.5 leduri
Problema 5 - leduri 100 de puncte
Am un cablu cu N leduri (numerotate de la 1 la N ) a³ezate echidistant. Iniµial, unele leduri
sunt aprinse, iar altele sunt stinse. Ledurile sunt legate între ele astfel încât atingerea ec rui
led produce modicarea atât a st rii lui, cât ³i a ledurilor vecine lui. Deci, dac se atinge ledul i
(2 & i & N 1) atunci se modic st rile ledurilor i 1, i ³i i 1. Dac se atinge ledul 1, atunci
se modic st rile ledurilor 1 ³i 2, iar dac se atinge ledul N , atunci se modic st rile ledurilor
N 1 ³i N . Vreau s modic starea ledurilor astfel încât s semene cu cablul cu N leduri pe care
îl are Ionuµ, prietenul meu (dou cabluri seam n dac pentru orice i 1..N st rile ledurilor de
pe poziµia i sunt identice).
Cerinµe
Cunoscând cum arat cablul lui Ionuµ, ajutaµi-m s determin num rul minim de atingeri ale
unor leduri astfel încât cablul meu s arate ca ³i cablul lui Ionuµ.
Date de intrare
Fi³ierul de intrare leduri.in conµine pe prima linie num rul natural N . Pe a doua linie sunt
N cifre binare separate prin câte un spaµiu reprezentând st rile ledurilor de pe cablul meu. Cifra
de pe poziµia i este 0 dac ledul i este stins, respectiv este 1 dac ledul i este aprins (i 1..N ).
Pe a treia linie sunt N cifre binare separate prin câte un spaµiu, reprezentând st rile ledurilor de
pe cablul lui Ionuµ.
Date de ie³ire
Fi³ierul de ie³ire leduri.out va conµine pe prima linie un singur num r natural reprezentând
num rul minim de atingeri ale unor leduri astfel încât cablul meu s arate ca ³i cablul lui Ionuµ.
Restricµii ³i preciz ri
a 1 & N & 100 000
a Se garanteaz c pentru toate testele exist soluµie.
a Pentru teste valorând 30 de puncte, N va cel mult 20
CAPITOLUL 24. ONI 2016 439
Exemple:
leduri.in leduri.out Explicaµii
4 2 O soluµie posibil este:
1010 Se apas mai întâi al doilea led: 1 0 1 0 0100
0111 Se apas ultimul led: 0 1 0 0 0111
Timp maxim de executare/test: 0.5 secunde
Memorie: total 64 MB
Dimensiune maxim a sursei: 15 KB
În primul rând, se observa becurile pot atinse in orice ordine, f r a produce schimb ri de
efect în nal. O a doua observaµie util în rezolvarea problemei este c , pentru a transforma
conguraµia iniµial în cea nala, orice bec ajunge sa e atins maximum o data.
Acest lucru rezult din faptul c atingerea unui bec pentru a doua oara produce neutralizarea
primei operaµii.
n
Din cele doua observaµii se deduce c num rul de seturi de operaµii diferite posibile este 2
(orice set de operaµii se poate vedea ca atingerea unei submulµimi de becuri din cele n).
Soluµia pentru 20p:
Pentru 20% din teste, n & 20, deci se poate simula orice set de operaµii ³i, pentru cele care
produc efectul dorit, s se calculeze num rul de operaµii ³i s se compare cu minimul obµinut de
pân atunci.
n
Complexitatea acestei soluµii este O 2 .
Soluµia pentru 100p:
La o analiz mai atent a conguraµiilor posibile ³i a modurilor din care se poate ajunge la
acestea, se observ c exist maximum dou soluµii de transformare valide. Mai exact, aplicând
o strategie tip Greedy pentru a transforma ³irul iniµial în cel nal, se observ c setul de operaµii
este unic determinat de atingerea sau nu a primului element. Mai exact:
S presupunem c am ales s atingem primul element (cazul în care nu îl atingem se va trata
în mod analog). Se disting dou cazuri:
1) Becul 1 din starea actual e diferit de becul 1 în starea nal , unde singura variant posibil
de a rezolva aceast problem este s atingem becul 2 (deoarece becul 1 nu mai poate schimbat,
din observaµiile de mai sus)
2) St rile celor doua becuri coincid, caz în care nu avem voie sa atingem becul 2 (dac l-am
atinge, nu am mai putea modica înapoi starea becului 1)
Inductiv, se demonstreaz c atingerile tuturor celor n becuri sunt unic determinate.
În nal, se poate s obµinem o stare diferit pentru ultimul bec, caz in care soluµia obtinut
nu este corect .
Soluµia de 100p trateaz cele dou cazuri (atingerea sau nu a primului bec), dup care simuleaz
strategia descris mai sus pentru a obµine o conguraµie care difer de cea nal la cel mult ultima
poziµie. Dac cele doua valori coincid, se actualizeaz eventualul num r minim de operaµii. Dac
acest minim nu a fost actualizat, nu vor exista soluµii (în cadrul problemei, îns , orice test admite
soluµie valid ).
Extra:
Pentru o mai bun înµelegere a corectitudinii problemei, propunem înc o demonstraµie, mai
formal :
Datorita comutativit µii setului de operaµii, este sucient ³i necesar s aducem ambele con-
guraµii la o stare intermediar .
S consider m (S0) = 000 ... 000 ³i (S1) = 000 ... 001.
Lem : Din orice stare iniµial se poate ajunge în S0 sau S1
Demonstraµie: Rezult din algoritmul descris mai sus (de ecare dat când g sim un bec
aprins, atingem becul imediat urm tor ³i repet m).
În continuare, dac se poate ajunge din S0 în S1 sau invers, atunci se poate ajunge din orice
stare în orice stare. Ne intereseaz acum s analiz m când se întâmpl acest lucru.
CAPITOLUL 24. ONI 2016 440
25
26 int main()
27 {
28 freopen("leduri.in", "r", stdin);
29 freopen("leduri.out", "w", stdout);
30
31 cin >> n;
32
33 for(int i = 1; i <= n; ++i)
34 {
35 cin >> A0[i];
36 A1[i] = A0[i];
37 }
38
39 for(int i = 1; i <= n; ++i)
40 cin >> B[i];
41
42 A1[1] ^= 1;
43 A1[2] ^= 1;
44
45 int a = transform(A0);
46 int b = transform(A1);
47
48 int ans = 1000000;
49 if(A0[n] == B[n]) ans = min(ans, a);
50 if(A1[n] == B[n]) ans = min(ans, b + 1);
51
52 if(ans == 1000000)
53 ans = -1;
54
55 cout << ans << endl;
56
57 return 0;
58 }
39
40 return cnt;
41 }
42
43 ofstream out("leduri.out");
44
45 int main()
46 {
47 ifstream in("leduri.in");
48 in >> n;
49 assert(1 <= n && n <= 100000);
50
51 for(int i = 1; i <= n; ++i)
52 {
53 in >> v[i];
54 init[i] = v[i];
55 assert(v[i] == 0 || v[i] == 1);
56 }
57
58 for(int i = 1; i <= n; ++i)
59 {
60 in >> fin[i];
61 assert(fin[i] == 0 || fin[i] == 1);
62 }
63
64 int s1 = go();
65
66 for(int i = 1; i <= n; ++i)
67 v[i] = init[i];
68
69 v[1] ^= 1;
70 v[2] ^= 1;
71
72 int s2 = go() + 1;
73
74 if(s1 >= INF && s2 >= INF)
75 {
76 out << "-1\n";
77 return 0;
78 }
79 else
80 out << min(s1, s2) << "\n";
81
82 return 0;
83 }
24.6 omogene
Problema 6 - omogene 100 de puncte
Se consider o matrice cu L linii ³i C coloane care memoreaz doar valori din mulµimea 0,1,2. O
submatrice nevid (format din cel puµin o linie ³i cel puµin o coloan ) a acestei matrice o numim
omogen dac num rul valorilor de 0 este egal cu num rul de valori de 1 ³i egal cu num rul
valorilor de 2.
De exemplu, în matricea
0 1 2 0
1 2 0 1
sunt ³ase submatrice omogene, acestea ind:
012 120 012 120 120 201
120 201
Submatricele a treia ³i a patra sunt formate din prima linie a matricei iniµial , iar submatricele
a cincea ³i a ³asea sunt formate din a doua linie.
Cerinµe
S se determine câte submatrice nevide omogene exist .
CAPITOLUL 24. ONI 2016 443
Date de intrare
Fi³ierul omogene.in conµine pe prima linie numerele naturale L ³i C . Pe urm toarele L linii
se a câte C numere naturale separate prin spaµii reprezentând câte o linie din matrice.
Date de ie³ire
Fi³ierul omogene.out va conµine pe prima linie un singur num r natural reprezentând num rul
submatricelor nevide omogene.
Restricµii ³i preciz ri
a 2 & L & C & 5 000
a 4 & L C & 65 536
a Atenµie, o submatrice este format dintr-o secvenµ continu de linii ³i coloane, deci, de
exemplu, dac se aleg dintr-o matrice liniile 1, 2 ³i 5, atunci acestea nu formeaz o submatrice.
9
a Num rul submatricelor omogene va mai mic decât 2 10
a întreaga matrice poate submatrice omogen
Exemple:
omogene.in omogene.out Explicaµii
2 4 6 Cele ³ase submatrice au fost menµionate în enunµ.
0 1 20
1 2 01
3 3 3
0 1 2
0 2 2
0 1 1
Timp maxim de executare/test: 3.0 secunde
Memorie: total 64 MB
Dimensiune maxim a sursei: 15 KB
Rezolv m mai întâi problema liniar . Se consider un vector t de lungime n care memoreaz
doar valori din mulµimea {1,2,3}. S se determine num rul secvenµelor omogene (adic în care
num rul valorilor de 0 este egal cu num rul valorilor de 1 ³i egal cu num rul valorilor de 2).
Construim sirul sumelor partiale:
s0[i]= num rul valorilor de 0 din t[1..i]
s1[i]= num rul valorilor de 1 din t[1..i]
s2[i]= num rul valorilor de 2 din t[1..i]
Apoi construim ³irurile
d01[0] = d12[0] = d20[0] = 0 ³i
d01[i] = s0[i] - s1[i], i=1..n
d12[i] = s1[i] - s2[i] , i=1..n
d20[i] = s2[i] - s0[i], i=1..n
Vom determina apoi câte perechi de triplete { d01[i], d12[i], d20[i] } egale sunt în acest ³ir de
lungime n+1 (i=0..n). Dac dou triplete { d01[i],d12[i], d20[i] } ³i { d01[k],d12[k], d20[k] } (i <
j) sunt identice, atunci secvenµa t[i+1], t[i+2],â¦t[j] este o secvenµ omogen .
Pentru a aa num rul perechilor de triplete egale, se poate sorta ³irul tripletelor. în ³irul
sortat, tripletele identice sunt al turate. Dac identic m X triplete identice, atunci num rul
perechilor de triplete identice este X(X-1)/2 (oricare dou ).
Deci complexitatea determin rii num rului de secvenµe omogene din vectorul t este dat se
sortarea tripletelor, deci O n log n.
CAPITOLUL 24. ONI 2016 444
Revenind la problema bidimensional : Din restricµii, L & C ³i L C &65 536. De unde rezult
c
L & sqrt 65536 256.
Deci num rul de linii din matrice nu poate mai mare de 256.
Construim dou matrice de sume parµiale:
z[i][j] = num rul de valori de 0 aate pe coloana j, începând de la poziµia (i,j) în sus.
u[i][j] = num rul de valori de 1 aate pe coloana j, începând de la poziµia (i,j) în sus.
Pentru orice dou linii k ³i p (unde k<=p), dorim s a m câte submatrice omogene de în lµime
H=p-k+1 exist între cele dou linii. Vom construi deci vectorul t0[j] = z[p][j]-z[k-1][j], j=1..C,
deci în care t[j] memoreaz num rul valorilor de 0 aate pe coloana j între liniile k ³i p. Similar,
se construie³te t1[j]=u[p][j]-u[k-1][j], j=1..C, deci în care t1[j] memoreaz num rul valorilor de 1
aate pe coloana j între liniile k ³i p. Atunci t2[j]=H-t0[j]-t1[j], pentru j=1..C.
Apoi problema se rezolv ca în cazul unidimensional.
Complexitatea va deci O L L C logC
51 state getState(int i)
52 {
53 state ret;
54 ret.v[0] = vect[i][0] - vect[i][1];
55 ret.v[1] = vect[i][0] - vect[i][2];
56 ret.v[2] = vect[i][1] - vect[i][2];
57 return ret;
58 }
59
60 LL cnt(int l1, int l2)
61 {
62 for(int i = 1; i <= m; ++i)
63 {
64 for(int k = 0; k < 3; ++k)
65 vect[i][k] = vect[i - 1][k] + s[l2][i][k] - s[l1 - 1][i][k] -
66 s[l2][i - 1][k] + s[l1 - 1][i - 1][k];
67 }
68
69 for(int i = 1; i <= m; ++i)
70 sts[i] = getState(i);
71
72 sort(sts + 1, sts + m + 1, comp);
73
74 LL ret = 0;
75
76 for(int i = 1, j; i <= m; i = j)
77 {
78 j = i + 1;
79 while(j <= m && sts[i] == sts[j])
80 j++;
81
82 LL diff = j - i;
83 ret += diff * (diff - 1) / 2;
84 }
85
86 for(int i = 1; i <= m; ++i)
87 ret += sts[i] == good;
88
89 return ret;
90 }
91
92 int main()
93 {
94 ifstream in("omogene.in");
95 ofstream out("omogene.out");
96
97 in >> n >> m;
98 for(int i = 1; i <= n; ++i)
99 for(int j = 1; j <= m; ++j)
100 in >> v[i][j];
101
102
103 for(int i = 1; i <= n; ++i)
104 for(int j = 1; j <= m; ++j)
105 {
106 for(int k = 0; k < 3; ++k)
107 {
108 s[i][j][k] += s[i - 1][j][k] + s[i][j - 1][k]
109 - s[i - 1][j - 1][k];
110 }
111 s[i][j][v[i][j]]++;
112 }
113
114 for(int i = 1; i <= n; ++i)
115 for(int j = i; j <= n; ++j)
116 ans += cnt(i, j);
117
118 out << ans << "\n";
119 return 0;
120 }
13
14 inline bool test(const nod &t1,const nod &t2)
15 {
16 return t1.d01<t2.d01 ||
17 (t1.d01==t2.d01 && t1.d12<t2.d12) ||
18 (t1.d01==t2.d01 && t1.d12==t2.d12 && t1.d20<t2.d20);
19 }
20
21 nod v[10001];
22 int a[318][10001];
23 int z[318][10001],u[318][10001];
24 int t0,t1,t2,st0,st1,st2;
25 long long sol;
26 int n,m;
27
28 void citire()
29 {
30 f>>n>>m;
31 for(int i=1;i<=n;++i)
32 for(int j=1;j<=m;++j)
33 f>>a[i][j];
34 f.close();
35 }
36
37 void prelucrare()
38 {
39 for(int i=1;i<=n;++i)
40 for(int j=1;j<=m;++j)
41 {
42 z[i][j]=z[i-1][j]+(a[i][j]==0);
43 u[i][j]=u[i-1][j]+(a[i][j]==1);
44 }
45
46 for(int k=1;k<=n;++k)
47 for(int p=k;p<=n;++p)
48 {
49 int d=p-k+1;
50 st0=st1=st2=0;
51 v[0].d01=v[0].d12=v[0].d20=0;
52 for(int j=1;j<=m;++j)
53 {
54 t0=z[p][j]-z[k-1][j];st0+=t0;
55 t1=u[p][j]-u[k-1][j];st1+=t1;
56 t2=d-t0-t1;st2+=t2;
57 v[j].d01=st0-st1;
58 v[j].d12=st1-st2;
59 v[j].d20=st2-st0;
60 }
61
62 sort(v,v+m+1,test);
63
64 int x=1;
65 for(int i=1;i<=m;++i)
66 if(v[i-1].d01==v[i].d01 &&
67 v[i-1].d12==v[i].d12 &&
68 v[i-1].d20==v[i].d20)
69 x++;
70 else
71 {
72 sol=sol+1ll*x*(x-1)/2;
73 x=1;
74 }
75
76 sol=sol+1ll*x*(x-1)/2;
77 }
78 }
79
80 int main()
81 {
82 citire();
83 prelucrare();
84 g<<sol<<’\n’;
85 return 0;
86 }
CAPITOLUL 24. ONI 2016 448
ONI 2015
25.1 cub
Problema 1 - cub 100 de puncte
S rb torile de iarn tocmai s-au încheiat. Florinel dore³te s -³i ajute
p rinµii la despodobirea bradului. Tubul luminos pe care l-au folosit
3
anul acesta este mai special. Are N becuri luminoase numerotate de
3
la 1 la N , iar ecare bec care este inscripµionat cu un num r prim, va
r mâne mereu aprins.
Cutia în care trebuie strâns tubul este un cub de latur N . Becul cu
num rul 1, trebuie pus în colµul de coordonate (1,1,1), restul în spiral
pân la umplerea nivelului, apoi nivelul urm tor în sens invers, ³.a.m.d.
Cerinµe
Cunoscând latura N a cubului, s se umple cubul cu tubul luminos
(becurile ind legate cresc tor), apoi s se determine:
1. Coordonatele x, y, z ale becului cu num rul V . (x-linia, y -coloana, z -în lµimea)
2. Num rul de becuri luminoase situate pe ecare faµ a cubului.
Date de intrare
Fi³ierul de intrare cub.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 a ³ierului de intrare, sunt scrise dou numere naturale N ³i V separate printr-
un spaµiu reprezentând dimensiunea cubului ³i valoarea becului pentru care trebuie determinate
coordonatele.
Date de ie³ire
a Dac valoarea lui p este 1, se va rezolva numai cerinµa 1. În acest caz, în ³ierul de ie³ire
cub.out se vor scrie trei numere naturale x y z , separate prin câte un spaµiu, reprezentând
coordonatele becului cu valoarea V .
449
CAPITOLUL 25. ONI 2015 450
a Dac valoarea lui p este 2, se va rezolva numai cerinµa 2. În acest caz, ³ierul de ie³ire
cub.out va conµine 4 linii. Pe ecare linie i, se va scrie câte un num r natural , reprezentând
num rul de becuri inscripµionate cu numere prime de pe faµa i.
Restricµii ³i preciz ri
a 1 & N & 200
1&V &N
3
a
a Pentru rezolvarea corect a primei cerinµe se acord 20 de puncte, iar pentru cerinµa a doua
se acord 80 de puncte.
a Pentru 20% dintre teste: 1 & N & 20
a Pentru 30% dintre teste: 21 & N & 100
a Pentru 50% dintre teste: 101 & N & 200
Exemple:
cub.in cub.out Explicaµii
1 3 10 222 Atenµie! Pentru acest test se rezolv doar cerinµa 1).
linia 2, coloana 2, nivel 2 - este becul 10
2 3 10 4343 Atenµie! Pentru acest test se rezolv doar cerinµa 2).
4 - becuri inscripµionate cu numere prime pe faµa 1: 2, 3, 17, 19
3 - becuri inscripµionate cu numere prime pe faµa 2: 3, 5, 23
4 - becuri inscripµionate cu numere prime pe faµa 3: 5, 7, 13, 23
3 - becuri inscripµionate cu numere prime pe faµa 4: 7, 11, 19
Timp maxim de executare/test: 0.5 secunde
Memorie: total 8 MB
Dimensiune maxim a sursei: 10 KB
Dac N este un num r par, se vor folosi la ecare plecare 4 direcµii matricea ind completat
astfel.
Dac N este impar elementul din centru va completat ultimul.
Ultimul element completat pe nivelul 1, decide poziµia de plecare în umplerea nivelului urm tor,
parcurgând circular spre exterior în sens trigonometric matricea de la nivelul 2.
Matricea de pe nivelul 2 se poate obµine din valorile matricii de la nivelul 1 astfel:
B ij 2 n n 1 Aij .
unde A este matricea asociat primului nivel, iar B este matricea asociat nivelului 2.
Se observ c matricile de nivel mai mare decât 2, se pot obµine din matricile de la nivelele
anterioare astfel:
a Valoarea unui element de pe nivelul 3 se obµine adunând la valoarea de pe nivelul 1 cu
acelea³i coordonate valoarea 2*N*N.
a Valoarea unui element de pe nivelul 4 se obµine adunând la valoarea de pe nivelul 2 cu
acelea³i coordonate valoarea 2*N*N.
a Valoarea unui element de pe nivelul 5 se obµine adunând la valoarea de pe nivelul 3 cu
acelea³i coordonate valoarea 2*N*N. ³.a.m.d.
Pentru rezolvarea cerinµei 1 (20 pct.): ajunge s sc dem în mod repetat din valoarea V num rul
2*N*N, µinând minte c trecem peste 2 nivele la ecare sc dere. Coordonatele X ³i Y le vom obµine
c utând valoarea r mas în matricile A sau B, iar coordonata Z, se obµine din num rul total de
sc deri*2 + valoarea 1 sau 2, în funcµie de nivelul matricii la care ajungem.
Pentru rezolvarea cerinµei 2 (80 pct.): ajunge s test m elementele de pe chenarul matricilor
A ³i B:
CAPITOLUL 25. ONI 2015 451
136 {
137 g<<i<<" "<<p<<" "<<z<<"\n";
138 g.close();
139 return 0;
140 }
141 }
142 }
143
144 }
145 }
146 else
147 {
148 for (z=1;z<=n;z++)
149 if (z%2==1)
150 {
151 p=1; v=(z-1)*n2;
152
153 // coltul st-sus
154 v++;
155 if (pr[v]) { f1++; f4++; }
156
157 for (j=p+1; j<=n-p; j++)
158 {
159 v++;
160 if (pr[v]) f1++;
161 }
162
163 // coltul dreapta sus
164 v++;
165 if (pr[v]) { f1++; f2++; }
166
167 for (i=p+1; i<=n-p; i++)
168 {
169 v++;
170 if (pr[v]) f2++;
171 }
172
173 // coltul dreapta jos
174 v++;
175 if (pr[v]) { f2++; f3++; }
176
177 for (j=n-p; j>=p+1; j--)
178 {
179 v++;
180 if (pr[v]) f3++;
181 }
182
183 // coltul stanga-jos
184 v++;
185 if (pr[v]) { f3++; f4++; }
186
187 for (i=n-p; i>=p+1; i--)
188 {
189 v++;
190 if (pr[v]) f4++;
191 }
192
193 v=v+n2-(4*n-4);
194 }
195 else
196 {
197 p=1;
198 v=v+n2-(4*n-4);
199 for (i=p+1; i<=n-p; i++)
200 {
201 v++;
202 if (pr[v]) f4++;
203 }
204
205 // coltul stanga jos
206 v++;
207 if (pr[v]) { f4++; f3++; }
208
209 for (j=p+1; j<=n-p; j++)
210 {
211 v++;
CAPITOLUL 25. ONI 2015 454
39 f>>n>>k;
40 n2=n*n;
41 if (v==1)
42 {
43 z=1;
44 v=0;
45 while (k-v>n2)
46 {
47 z++;
48 v=v+n2;
49 }
50 if (z%2==1)
51 {
52 for (p=1;;p++)
53 {
54 for (j=p;j<=n-p+1;j++)
55 {
56 v++;
57 if (v==k)
58 {
59 g<<p<<" "<<j<<" "<<z<<"\n";
60 g.close();
61 return 0;
62 }
63 }
64 for (i=p+1;i<=n-p+1;i++)
65 {
66 v++;
67 if (v==k)
68 {
69 g<<i<<" "<<n-p+1<<" "<<z<<"\n";
70 g.close();
71 return 0;
72 }
73 }
74 for (j=n-p;j>=p;j--)
75 {
76 v++;
77 if (v==k)
78 {
79 g<<n-p+1<<" "<<j<<" "<<z<<"\n";
80 g.close();
81 return 0;
82 }
83 }
84 for (i=n-p;i>=p+1;i--)
85 {
86 v++;
87 if (v==k)
88 {
89 g<<i<<" "<<p<<" "<<z<<"\n";
90 g.close();
91 return 0;
92 }
93 }
94 }
95 }
96 else
97 {
98 v=v+n2+1;
99 for (p=1;;p++)
100 {
101 for (j=p;j<=n-p+1;j++)
102 {
103 v--;
104 if (v==k)
105 {
106 g<<p<<" "<<j<<" "<<z<<"\n";
107 g.close();
108 return 0;
109 }
110 }
111 for (i=p+1;i<=n-p+1;i++)
112 {
113 v--;
114 if (v==k)
CAPITOLUL 25. ONI 2015 456
115 {
116 g<<i<<" "<<n-p+1<<" "<<z<<"\n";
117 g.close();
118 return 0;
119 }
120 }
121 for (j=n-p;j>=p;j--)
122 {
123 v--;
124 if (v==k)
125 {
126 g<<n-p+1<<" "<<j<<" "<<z<<"\n";
127 g.close();
128 return 0;
129 }
130 }
131 for (i=n-p;i>=p+1;i--)
132 {
133 v--;
134 if (v==k)
135 {
136 g<<i<<" "<<p<<" "<<z<<"\n";
137 g.close();
138 return 0;
139 }
140 }
141 }
142
143 }
144 }
145 else
146 {
147 for (z=1;z<=n;z++)
148 if (z%2==1)
149 {
150 p=1; v=(z-1)*n2;
151
152 // coltul st-sus
153 v++;
154 k=prim(v);
155 if (k) { f1++; f4++; }
156
157 for (j=p+1; j<=n-p; j++)
158 {
159 v++;
160 k=prim(v);
161 if (k) f1++;
162 }
163
164 // coltul dreapta sus
165 v++;
166 k=prim(v);
167 if (k) { f1++; f2++; }
168
169 for (i=p+1; i<=n-p; i++)
170 {
171 v++;
172 k=prim(v);
173 if (k) f2++;
174 }
175
176 // coltul dreapta jos
177 v++;
178 k=prim(v);
179 if (k) { f2++; f3++; }
180
181 for (j=n-p; j>=p+1; j--)
182 {
183 v++;
184 k=prim(v);
185 if (k) f3++;
186 }
187
188 // coltul stanga-jos
189 v++;
190 k=prim(v);
CAPITOLUL 25. ONI 2015 457
267 }
268 return 0;
269 }
70 //afisare(b);
71 if (p==1)
72 {
73 ///cerinta 1
74 x=v;
75 int nivel=0;
76 while(x>2*n*n)
77 x=x-2*n*n, nivel+=2;
78 int stop=0;
79 for(i=1;i<=n && stop==0; i++)
80 for(j=1;j<=n && stop==0; j++)
81 {
82 if(a[i][j]==x)
83 {
84 fout<<i<<" "<<j<<" "<<nivel+1<<endl;
85 stop=1;
86 }
87 if(b[i][j]==x)
88 {
89 fout<<i<<" "<<j<<" "<<nivel+2<<endl;
90 stop=1;
91 }
92 }
93 }
94 else
95 {
96 ///cerinta 2
97 f1=f2=f3=f4=0;
98 ///fata 1 - linia 1 A,B,.... 200*200 elemente=40.000 nr de testat
99 for(j=1;j<=n;j++)
100 {
101 nr=a[1][j];
102 while(nr<n*n*n)
103 {
104 if (prim(nr)) f1++;
105 nr+=2*n*n;
106 }
107 nr=b[1][j];
108 while(nr<n*n*n)
109 {
110 if (prim(nr)) f1++;
111 nr+=2*n*n;
112 }
113 }
114 ///fata 2 - coloana n A,B,....
115 for(i=1;i<=n;i++)
116 {
117 nr=a[i][n];
118 while(nr<n*n*n)
119 {
120 if (prim(nr)) f2++;
121 nr+=2*n*n;
122 }
123 nr=b[i][n];
124 while(nr<n*n*n)
125 {
126 if (prim(nr)) f2++;
127 nr+=2*n*n;
128 }
129 }
130 ///fata 3 - linia n A,B,....
131 for(j=1;j<=n;j++)
132 {
133 nr=a[n][j];
134 while(nr<n*n*n)
135 {
136 if (prim(nr)) f3++;
137 nr+=2*n*n;
138 }
139 nr=b[n][j];
140 while(nr<n*n*n)
141 {
142 if (prim(nr)) f3++;
143 nr+=2*n*n;
144 }
145 }
CAPITOLUL 25. ONI 2015 460
49 for(j=c;j<=n-c;j++)
50 {
51 k++;
52 a[l][j][nivel]=k;
53 if (k==v && p==1) printf("%d %d %d\n",l,j,nivel);
54 }
55 ///dir2
56 for(i=l;i<=n-l;i++)
57 {
58 k++;
59 a[i][n-c+1][nivel]=k;
60 if (k==v && p==1) printf("%d %d %d\n",i,n-c+1,nivel);
61 }
62 ///dir3
63 for(j=n-c+1;j>c;j--)
64 {
65 k++;
66 a[n-l+1][j][nivel]=k;
67 if (k==v && p==1) printf("%d %d %d\n",n-l+1,j,nivel);
68 }
69 ///dir4
70 for(i=n-l+1;i>l;i--)
71 {
72 k++;
73 a[i][c][nivel]=k;
74 if (k==v && p==1) printf("%d %d %d\n",i,c,nivel);
75 }
76 l++;
77 c++;
78 }
79 if (n%2==1)
80 {
81 k++;
82 a[n/2+1][n/2+1][nivel]=k;
83 if (k==v && p==1) printf("%d %d %d\n",n/2+1,n/2+1,nivel);
84 }
85 // afisare();
86 if (nivel<n)
87 {
88 colt=a[1][1][nivel];
89 nivel++; /// nivelul par
90 lim=colt+n*n*2;
91 for(i=1;i<=n;i++)
92 for(j=1;j<=n;j++)
93 {
94 a[i][j][nivel]=(colt-1)+lim-a[i][j][nivel-1];
95 if (a[i][j][nivel]==v && p==1)
96 printf("%d %d %d\n",i,j,nivel);
97 }
98 k+=n*n;
99 // afisare();
100 }
101 }
102 ///fata 1
103 for(nivel=1;nivel<=n;nivel++)
104 for(j=1;j<=n;j++)
105 if(ciur[a[1][j][nivel]]==false)
106 {
107 // printf("%d ",a[1][j][nivel]);
108 f1++;
109 }
110 if (p==2) printf("%d\n",f1);
111 ///fata 2
112 for(nivel=1;nivel<=n;nivel++)
113 for(i=1;i<=n;i++)
114 if(ciur[a[i][n][nivel]]==false)
115 {
116 // printf("%d ",a[i][n][nivel]);
117 f2++;
118 }
119 if (p==2) printf("%d\n",f2);
120 ///fata 3
121 for(nivel=1;nivel<=n;nivel++)
122 for(j=1;j<=n;j++)
123 if(ciur[a[n][j][nivel]]==false)
124 {
CAPITOLUL 25. ONI 2015 462
58 int main()
59 {
60 ifstream fi("cub.in"); ofstream fo("cub.out");
61 int i,j,k,d,p,N,V;
62 fi>>p>>N>>V;
63
64 if (p==1)
65 {
66 for(i=0;i<=N+1;i++)
67 a[0][i]=a[N+1][i]=a[i][0]=a[i][N+1]=1;
68
69 i=j=1;
70 d=0;
71 for(k=1;k<=N*N;k++)
72 {
73 a[i][j]=k;
74 if(!a[i+dx[d]][j+dy[d]])
75 {
76 i+=dx[d];
77 j+=dy[d];
78 }
79 else
80 {
81 d=(d+1)%4;
82 i+=dx[d];
83 j+=dy[d];
84 }
85 }
86
87 k=V/(N*N);
88 V%=(N*N);
89 if (k&1)
90 V=N*N+1-V;
91
92 for (i=1;i<=N;i++)
93 for (j=1;j<=N;j++)
94 if (a[i][j]==V)
95 {
96 fo<<i<<" "<<j<<" "<<k+1<<"\n";
97 break;
98 }
99 }
100 else
101 {
102 int f[5],t;
103 f[1]=f[2]=f[3]=f[4]=0;
104 for (i=1;i<=N;i++)
105 for (j=1;j<=N;j++)
106 for (t=0;t<4;t++)
107 {
108 if (i&1)
109 k=j+(i-1)*N*N+t*(N-1);
110 else
111 k=i*N*N-j+1-t*(N-1);
112
113 if (t==3 && j==N)
114 k=(i&1)*(1+(i-1)*N*N);
115
116 f[t+1]+=prim(k);
117 }
118 for (t=1;t<=4;t++)
119 fo<<f[t]<<"\n";
120 }
121
122 return 0;
123 }
25.2 risc
Problema 2 - risc 100 de puncte
Pentru a participa la un concert, n persoane s-au a³ezat la coad pe un singur rând în a³-
teptarea deschiderii casei de bilete. În lµimile celor n persoane sunt toate distincte. Pe baza
acestei informaµii cruciale, agenµii de securitate au decis ca din motive de ... securitate, ordinea
persoanelor care a³teapt la coad trebuie schimbat în funcµie de în lµimile lor.
Astfel, agentii de paz vor alege, pe rând, câte o persoan ³i o vor trimite la sfâr³itul rândului.
Dup ecare operaµie de tipul acesta, s -i spunem de mutare, rândul se restrânge, ocupându-
se poziµia r mas liber . Strategia agenµilor de paz este aceasta: la terminarea tuturor operaµiilor
de mutare, riscul minim de securitate se obµine dac toate persoanele aate în dreapta persoanei
celei mai înalte vor mai înalte decât cele aate în stânga persoanei cele mai înalte. În plus, înal-
µimile persoanelor vor cresc toare pân la poziµia k a persoanei celei mai înalte ³i descresc toare
dup poziµia k .
Mai exact: dac h1 , h2 , ..., hn sunt în lµimile persoanelor dup nalizarea operaµiilor de
mutare, atunci: exist o poziµie k , cu 1 & k & n astfel încât
h1 $ h2 $ ...hk 1 $ hk % hk 1 % ... % hn 1 % hn
Cerinµe
Cunoscând num rul de persoane n ³i în lµimile h1 , h2 , ..., hn ale acestora s se scrie un program
care determin :
1. Poziµia persoanei celei mai înalte în rândul iniµial, în cazul în care nu sunt necesare operaµii
de mutare.
2. Num rul minim de mut ri necesare pentru ca rândul de persoane s prezinte un risc minim
de securitate.
Date de intrare
Pe prima linie a ³ierului de intrare risc.in se g se³te num rul natural p a c rui valoare poate
doar 1 sau 2.
Pe a doua linie a ³ierului de intrare se a num rul natural n cu semnicaµia din enunµ.
Pe a treia linie se g sesc n numere naturale, distincte: h1 , h2 , ..., hn , separate prin câte un
singur spaµiu, reprezentând în lµimile persoanelor.
Date de ie³ire
Fi³ierul de ie³ire este risc.out.
a Dac valoarea lui p este 1 atunci se va rezolva numai cerinµa 1. în acest caz, ³ierul de ie³ire
va conµine pe prima linie un num r natural poz ce reprezint poziµia persoanei celei mai înalte în
rândul iniµial. Dac rândul iniµial nu respect condiµiile de risc minim de securitate, atunci poz
este -1.
a Dac valoarea lui p este 2 se va rezolva numai cerinµa 2. în acest caz ³ierul de ie³ire va
conµine pe prima linie un num r natural m, reprezentând num rul minim de mut ri necesare
pentru a obµine risc minim de securitate.
Restricµii ³i preciz ri
a 1 & n & 100 000
a 1 & h1 , h2 , ...hn & 100 000
a Persoana cea mai înalt într-o conguraµie cu risc minim de securitate poate plasat pe
oricare dintre poziµiile 1...n
a Pentru 50% din teste, n & 2 000, iar pentru alte 40% din teste, n & 10 000
a Pentru rezolvarea corect a primei cerinµe se acord 20 de puncte, iar pentru cerinµa a doua
se acord 80 de puncte.
Exemple:
CAPITOLUL 25. ONI 2015 465
Cerinµa 1. 20 puncte
Se determin înalµimea hmax ³i poziµia pmax a celei mai înalte persoane.
Pentru ecare poziµie 2 & i & pmax se veric dac h[i] > h[i -1] ³i similar, pentru ecare
poziµie i % pmax se veric dac pentru persoana i aat în dreapta acesteia se veric dac
hi $ hi 1. Pentru a determina dac toate persoanele aate în dreapta poziµiei pmax sunt
mai înalte decât cele aate în stânga se veric condiµia hpmax 1 $ hn.
Cerinµa 2. Total - 80 de puncte
Soluµia 1 - Complexitate O n n, prof. Carmen Popescu, C. N. Gheorge Laz r Sibiu
Se marcheaz valorile care trebuie mutate folosind un vector boolean. Simultan cu aceste
mut ri vom calcula ³i urm toarele valori:
mx = maximul valorilor ce se mut la sfâr³it
mn = minimul valorilor ce vor în dreapta maximului dup mut ri
Pentru ecare în lµime hi, i $ k c ut m toate valorile din faµa sa care sunt mai mari, adic
hj % hi cu j $ i (este înc lcat prima condiµie de mai sus), acestea vor mutate.
Vom muta apoi la sfâr³it toate valorile aate în dreapta maximului care nu respect cerinµa
a doua de mai sus, deci pentru ecare în lµime hi cu i % k 1 vom muta la sfâr³it valorile din
faµa sa, care sunt mai mici decât hi, adic mut m valorile hj cu j % k ³i j $ i pentru care
hj $ hi.
Mut m apoi valorile care au r mas în stânga maximului ³i care sunt mai mari decât minimul
valorilor din dreapta (condiµia a treia de mai sus), deci mai mari decât mn.
Acum toate valorile sunt în jum tatea potrivit , îns s-ar putea ca elementele care se aau
iniµial în dreapta maximului ³i nu au fost mutate s e mai mici decât maximul valorilor mutate la
sfâr³it (încalc condiµia a doua de mai sus) si s trebuiasc s le mut m la sfâr³it. Vom muta
a³adar la sfâr³it valorile hi $ mx cu i % k .
O alt posibilitate de a aranja ³irul dat este s mut m maximul la sfâr³itul ³irului ³i apoi s
relu m mut rile ca mai sus. Se va alege cea mai favorabil din cele dou variante.
Aceast soluµie obµine 30 de puncte din 80 posibile.
CAPITOLUL 25. ONI 2015 466
Cu ro³u s-au reprezentat cele mai mici numere din ³ir aate în ordine cresc toare în parcurgerea
³irului de la stânga la dreapta. Num rul acestora este Asci 3 (pentru i ' 5). Cu albastru sunt
gurate cele mai mari numere din ³ir aate în ordine descresc toare în parcurgerea ³irului de la
stânga la dreapta. Num rul lor este Desc 2, iar cap tul din stânga al acestui sub³ir începe la
poziµia pmax 7.
Numerele marcate cu negru trebuie s e mutate. Ordinea mut rii poate aleas astfel încât
s respecte cerinµa de risc minim.
pmax 7, Asc7 Desc 3 2 % Ascn 3.
Prin urmare, M n Ascpmax Desc 10 5 5
O alt situaµie este exemplicat mai jos:
CAPITOLUL 25. ONI 2015 467
3 #include <iostream>
4 #include <fstream>
5 #include <algorithm>
6 #include <bitset>
7
8 using namespace std;
9
10 int a[100001];
11 int n,mx,p;
12
13 ifstream f("risc.in");
14 ofstream g("risc.out");
15
16 bitset<100001> b;
17 bitset<100001> c;
18
19 int main()
20 {
21 int v,i,j,k,mn;
22 f>>v>>n;
23 for (i=1;i<=n;i++)
24 {
25 f>>a[i];
26 if (a[i]>mx)
27 {
28 mx=a[i]; p=i;
29 }
30 }
31
32 if (v==1)
33 {
34 // ordinea din stanga
35 for (i=1;i<p;i++)
36 if (a[i]>a[i+1])
37 {
38 g<<-1<<"\n";
39 return 0;
40 }
41
42 // ordinea din dreapta
43 for (i=p+1;i<n;i++)
44 if (a[i]<a[i+1])
45 {
46 g<<-1<<"\n";
47 return 0;
48 }
49
50 // in stanga sunt numere mai mici decat minimul din dreapta
51 if (a[p-1]>a[n] || a[p+1]<a[p-1])
52 {
53 g<<-1<<"\n";
54 return 0;
55 }
56 g<<p<<"\n";
57 }
58 else
59 {
60 // CAZUL 1: mutam ce nu e ok din stanga si dreapta
61
62 // mn = minimul valorilor ce vor fi in dreapta dupa mutari
63 mn=a[p];
64
65 // marcam nr din stanga ce nu respecta ordinea si vor fi
66 // mutate la sfarsit
67 k=0;
68 mx=-1; // mx= maximul valorilor ce se muta la sfarsit
69 for (i=2;i<p;i++) // pt fiecare valoare din stanga
70 for (j=i-1;j>=1;j--) // mutam (marcam) numerele din fata sa
71 // care sunt mai mari, adica ele
72 // vor trebui mutate
73 if (a[j]>a[i] && !b[j])
74 {
75 b[j]=true;
76 k++;
77 if (a[j]>mx) mx=a[j];
78 if (a[j]<mn) mn=a[j];
CAPITOLUL 25. ONI 2015 470
79 }
80
81 // marcam valorile din dreapta care nu respecta ordinea si
82 // vor fi mutate la sfarsit
83 for (i=p+2;i<=n;i++)
84 {
85 if (a[i]<mn)
86 mn=a[i];
87 for (j=i-1;j>p;j--)
88 if (a[j]<a[i] && !b[j])
89 {
90 b[j]=true;
91 k++;
92 if (a[j]>mx) mx=a[j];
93 }
94 }
95
96 // marcam valorile care au ramas in stanga (nemutate) care sunt
97 // mai mari decat minimul din dreapta si care vor
98 // fi mutate la sfarsit
99 for (i=1;i<p;i++)
100 if (!b[i] && a[i]>mn)
101 {
102 b[i]=true;
103 k++;
104 if (a[i]>mx) mx=a[i];
105 }
106
107 // verificam valorile din dreapta care au ramas nemutate si care
108 // sunt mai mici decat maximul celor mutate, ele trebuie mutate
109 // la sfarsit
110 for (i=n;i>p;i--)
111 if (!b[i] && a[i]<mx)
112 k++;
113
114 // CAZUL 2:
115 // mutam maximul la sfarsit pe urma mutam ce nu respecta ordinea
116 // mn = minimul valorilor ce se vor afla in dreapta
117 mn=a[p];
118 int k1=1; // am mutat maximul la sfarsit
119 for (i=2;i<=n;i++)
120 if (i!=p)
121 for (j=i-1;j>=1;j--)
122 if (j!=p && a[j]>a[i] && !c[j])
123 {
124 c[j]=true;
125 k1++;
126 if (a[j]<mn) mn=a[j];
127 }
128 // cautam valorile ramase nemutate si care sunt mai mari decat
129 // minimul celor mutate si ele vor fi mutate
130 for (i=1;i<=n;i++)
131 if (i!=p && !c[i] && a[i]>mn)
132 k1++;
133
134 // solutia e cea din cazul cel mai favorabil
135 if (k<k1)
136 g<<k<<"\n";
137 else
138 g<<k1<<"\n";
139 }
140
141 return 0;
142 }
25.3 roboti
Problema 3 - roboti 100 de puncte
O rm de construcµii imobiliare a achiziµionat recent un teren dreptunghiular de dimensiuni
N M . Terenul este împ rµit în parcele de dimensiune 1 1. Pe unele dintre cele N M
parcele sunt plantaµi copaci. Firma dore³te construirea unui grandios complex comercial ³i este
necesar defri³area întregului teren. în acest scop sunt utilizaµi roboµi, ecare robot având baza
un p trat de latur L. Suprafaµa defri³at de ecare robot la un moment dat este chiar aria de
acoperire a robotului, L L. Fiecare robot p trunde prin colµul stânga sus de coordonate 1, 1,
se poate deplasa doar în dreapta ³i în jos ³i poate p r si suprafaµa numai prin colµul dreapta jos,
de coordonate N, M .
Cerinµe
Cunoscând dimensiunile N , M ale terenului ³i coordonatele parcelelor în care sunt plantaµi
copaci se cere:
1. Num rul minim de roboµi necesari defri³ rii întregului teren.
2. S se r spund la Q interog ri de forma k , unde k este un num r natural. Pentru ecare
interogare de aceast form va trebui determinat latura minim a unui robot astfel încât s e
necesari pentru defri³are cel mult k roboµi.
Date de intrare
Fi³ierul de intrare roboti.in conµine:
a Pe prima linie un num r natural p reprezentând varianta cerinµei de rezolvare. Pentru toate
testele de intrare, num rul p poate avea doar valoarea 1 sau valoarea 2.
a Pe a doua linie se a 3 numere naturale N , M , T separate prin câte un spaµiu reprezen-
tând num rul liniilor, num rul coloanelor terenului dreptunghiular, respectiv num rul copacilor
plantaµi.
a Urm toarele T linii conµin ecare câte dou numere naturale x, y separate prin câte un
spaµiu, reprezentând linia, respectiv coloana parcelei în care este plantat un copac.
a În cazul cerinµei 1, ultima linie conµine un singur num r natural L, reprezentând latura unui
robot.
a În cazul cerinµei 2, penultima linie va conµine un num r natural Q, iar ultima linie Q numere
naturale k1 , k2 , ..., kQ separate prin câte un spaµiu, reprezentând num rul maxim de roboµi ce pot
utilizaµi în ecare dintre cele Q interog ri.
Date de ie³ire
a Dac valoarea lui p este 1, se va rezolva numai cerinµa 1. În acest caz, în ³ierul de ie³ire
roboti.out se va scrie un singur num r natural n1 , reprezentând num rul minim de roboµi utilizaµi.
a Dac valoarea lui p este 2, se va rezolva numai cerinµa 2. În acest caz, în ³ierul de ie³ire
roboti.out se vor scrie Q linii. Fiecare linie i va conµine câte un num r natural ni , reprezentând
latura minim a unui robot astfel încât pentru defri³are s e utilizaµi cel mult ki roboµi.
Restricµii ³i preciz ri
a 2 & N, M, L & 150
a 1 & Q & 150
a 1 & ki & 150, 1 & i & Q
a 1 & T & 1000
a Latura robotului nu poate mai mare decât dimensiunile terenului
a Pe tot parcursul deplas rii, ecare robot se va aa în interiorul suprafeµei terenului.
a în orice moment în interiorul suprafeµei terenului se va aa cel mult un robot.
Exemple:
2 688415 41 p 2
3 352655 Prima valoare din ³ierul de ie³ire reprezint latura minim pe
4 738682 care o pot avea roboµii astfel încât pentru defri³area întregului
1 3 teren s e necesar un singur robot, conform primei interog ri.
A doua valoare din ³ierul de ie³ire reprezint latura minim pe
care o pot avea roboµii astfel încât pentru defri³area întregului
teren s e necesari cel mult trei roboµi, conform celei de-a doua
interog ri.
Atenµie! Pentru acest test se rezolv doar cerinµa 2.
Cerinµa 2. 50 de puncte
Se caut binar latura minim a roboµilor care trebuie folosiµi pentru a nu dep ³i num rul admis
de roboµi utilizaµi. Num rul de roboµi folosiµi se face la fel ca la cerinµa 1. Pentru un algoritm de
tip greedy, complexitatea soluµiei la cerinµa 2 este O Q n T log T
CAPITOLUL 25. ONI 2015 474
71 lo = L + 1;
72 }
73 }
74 }
75
76 fin.close();
77 fout.close();
78 }
79
80 int CountRobots(int L) // O(T * log(n)^2)
81 {
82 int cnt(0), cntUp(0);
83
84 for (const auto& c : cl)
85 {
86 cntUp = 1;
87 if (c.i > L && c.j <= m - L)
88 cntUp += Query(c.i - L, m - c.j - L + 1);
89
90 Update(c.i, m - c.j + 1, cntUp);
91 cnt = max(cnt, cntUp);
92 }
93
94 for (const auto& c : cl)
95 Reset(c.i, m - c.j + 1);
96
97 return cnt;
98 }
99
100 void Reset(int ic, int jc)
101 {
102 for (int i = ic; i <= n; i += i & -i)
103 for (int j = jc; j <= m; j += j & -j)
104 mx[i][j] = 0;
105 }
106
107 void Update(int ic, int jc, int val)
108 {
109 for (int i = ic; i <= n; i += i & -i)
110 for (int j = jc; j <= m; j += j & -j)
111 mx[i][j] = max(mx[i][j], val);
112 }
113
114 int Query(int ic, int jc)
115 {
116 int cnt(0);
117 for (int i = ic; i >= 1; i -= i & -i)
118 for (int j = jc; j >= 1; j -= j & -j)
119 cnt = max(cnt, mx[i][j]);
120 return cnt;
121 }
22
23 int main()
24 {
25 int x, y, p, T, L;
26
27 fin >> p >> n >> m >> T;
28
29 for (int i = 1; i <= T; ++i)
30 {
31 fin >> x >> y;
32 b[x][y] = 1;
33 }
34
35 if ( p == 1 )
36 {
37 fin >> L;
38 fout << CountRobots(L) << ’\n’;
39 }
40 else
41 {
42 int Q, k, lo, hi, Lmin;
43
44 for (fin >> Q; Q--; fout << Lmin << ’\n’)
45 {
46 fin >> k;
47 lo = 1, hi = n / k + 1;
48 while (lo <= hi)
49 {
50 L = (lo + hi) / 2;
51
52 if (CountRobots(L) <= k)
53 {
54 Lmin = L;
55 hi = L - 1;
56 }
57 else
58 lo = L + 1;
59 }
60 }
61 }
62
63 fin.close();
64 fout.close();
65 }
66
67 int CountRobots(int L)
68 {
69 int cnt = 0;
70 a = vector<VI>(n + 1, VI(m + 2));
71
72 for (int i = 1; i <= n; ++i)
73 for (int j = m; j >= 1; --j)
74 {
75 if ( b[i][j] )
76 {
77 if ( i > L && j <= m - L )
78 a[i][j] = 1 + a[i - L][j + L];
79 else
80 a[i][j] = 1;
81 }
82 else
83 a[i][j] = max(a[i][j + 1], a[i - 1][j]);
84
85 cnt = max(cnt, a[i][j]);
86 }
87
88 return cnt;
89 }
5 #include <iostream>
6 #include <fstream>
7 #include <algorithm>
8 #include <deque>
9
10 using namespace std;
11 using PII = pair<int, int>;
12
13 #define I q1.front().first
14 #define J q1.front().second
15
16 deque<PII> q, q1, q2, q3;
17 int n, m;
18
19 int CountRobots(int L);
20
21 int main()
22 {
23 ifstream fin("roboti.in");
24 ofstream fout("roboti.out");
25
26 int x, y, p, T, L;
27
28 fin >> p >> n >> m >> T;
29 for (int i = 1; i <= T; ++i)
30 {
31 fin >> x >> y;
32 q.push_back({x, y});
33 }
34
35 sort(q.begin(), q.end());
36
37 if ( p == 1 )
38 {
39 fin >> L;
40 fout << CountRobots(L) << ’\n’;
41 }
42 else
43 {
44 int Q, k, lo, hi, Lmin;
45
46 for (fin >> Q; Q--; fout << Lmin << ’\n’)
47 {
48 fin >> k;
49 lo = 1, hi = n / k + 1;
50 while (lo <= hi)
51 {
52 L = (lo + hi) / 2;
53
54 if ( CountRobots(L) <= k)
55 {
56 Lmin = L;
57 hi = L - 1;
58 }
59 else
60 lo = L + 1;
61 }
62 }
63 }
64
65 fin.close();
66 fout.close();
67 }
68
69 int CountRobots(int L)
70 {
71 int lastJ, lastI, i1, i2, j1, cnt = 0;
72 bool first(true);
73 for (q1 = q; !q1.empty(); q1.swap(q2))
74 {
75 cnt++;
76 lastJ = J, lastI = I, first = true;
77
78 for ( ; !q1.empty(); )
79 {
80 // cobor cat pot pe verticala
CAPITOLUL 25. ONI 2015 478
25.4 casa
Problema 4 - casa 100 de puncte
În aceast poveste este vorba despre o cas cu mai multe camere. O camer are forma unui
p trat de latur 1. Dac dou camere au un perete comun, atunci se poate trece dintr-o camer
în alta. Casa nu are neap rat form dreptunghiular .
O asemenea cas poate descris în povestea noastr în dou moduri:
- prin matricea minimal : o matrice cu elemente 0 ³i 1 în care exist N valori egale cu 1, ce
corespund camerelor, iar prima linie, ultima linie, prima coloan ³i ultima coloan au cel puµin un
element egal cu 1.
- prin construcµie: un ³ir de N 1 perechi ai , bi 1 & i $ n în care ai " r1, 2, ..., ix ³i
bi " rN, S, E, V x. Camerele vor numerotate de la 1 la n. Perechea ai , bi precizeaz poziµia
camerei i 1 faµ de camera ai : E înseamn la dreapta (est), N deasupra (nord), V la stânga
(vest), S dedesubt (sud). Observaµi c pentru prima camer nu exist nicio precizare!
De exemplu, casa de mai sus poate descris de ³irul (1 E) (2 E) (2 S) (3 S), adic a doua
camer e lipit la est de prima camer , urm toarea (a treia) la est de camera 2, a patra la sud
de camera 2, iar ultima la sud de camera 3.
Cerinµe
1. Se d descrierea unei case prin construcµie ³i se cere descrierea acesteia prin matricea
minimal .
2. Se d descrierea unei case prin matricea minimal ³i se cere descrierea acesteia prin con-
strucµie.
Date de intrare
Fi³ierul casa.in conµine:
a Pe prima linie un num r natural p reprezentând cerinµa care trebuie rezolvat . Pentru toate
testele de intrare, num rul p poate avea valoarea 1 sau 2.
a Dac valoarea lui p este 1 atunci liniile urm toare conµin descrierea unei case prin construcµie
astfel: pe linia a doua un num r natural N reprezentând num rul de camere ale casei, iar pe ecare
din urm toarele N 1 linii câte dou valori separate prin câte un spaµiu - un num r natural ³i un
caracter, cu semnicaµia de mai sus.
a Dac valoarea lui p este 2 atunci liniile urm toare conµin descrierea unei case prin matrice
minimal astfel: pe linia a doua dou numere naturale nenule M , N reprezentând dimensiunile
matricei, iar pe urm toarele M linii câte N numere 0 sau 1 separate prin câte un spaµiu.
Date de ie³ire
Dac valoarea lui p este 1 atunci se va rezolva numai cerinµa 1. În acest caz ³ierul casa.out
va conµine pe prima linie dou numere naturale M ³i N , separate prin câte un singur spaµiu repre-
zentând num rul de linii respectiv num rul de coloane ale matricei minimale, iar pe urm toarele
M linii câte N valori 0 sau 1 separate prin câte un singur spaµiu.
Dac valoarea lui p este 2 atunci se va rezolva numai cerinµa 2. În acest caz ³ierul casa.out
va conµine pe prima linie dou numere naturale N r ³i C separate printr-un singur spaµiu. N r
reprezint num rul de camere, iar C poziµia camerei 1 (cel mai mic num r de ordine al unei
coloane care conµine valoarea 1 în prima linie). Urm toarele N r 1 linii vor conµine ecare câte
dou valori separate printr-un singur spaµiu, reprezentând descrierea unei case prin construcµie
conform preciz rilor din enunµ. Coloanele vor numerotate începând de la 1, iar dac exist mai
multe soluµii va a³at cea mai mic în ordine lexicograc : perechea k, l va a³at înaintea
perechii k, l dac k $ k sau dac k k ³i l $ l (adic E < N < S < V).
CAPITOLUL 25. ONI 2015 480
Restricµii ³i preciz ri
a Matricea minimal a unei case are maximum 100 000 elemente.
Exemple:
casa.in casa.out Explicaµii
1 23
5 111
1 E 011
2 E
2 S
3 S
2 51
2 3 1E
1 11 1S
1 01 2E
4S
Timp maxim de executare/test: 0.1 secunde
Memorie: total 4 MB
Dimensiune maxim a sursei: 10 KB
Cerinµa 1.
Se determin câµi pa³i se fac spre nord, sud, est, vest, pornind din camera 1. Astfel se determin
dimensiunile matricei, apoi, având poziµionat corect camera 1, se completeaz matricea cu 1
urmând succesiv pa³ii daµi .
Cerinµa 2.
Se determin u³or poziµia primei camere, pe linia 1. Fiecare din camerele urm toare se deter-
min c utând pentru camera anterioar în cele 4 direcµii vecinii cu valoarea 1 care nu au fost deja
enumeraµi.
Deoarece nu se cunosc limitele maxime ale dimensiunilor m ³i n ale matricei, dar se cunoa³te
produsul lor m*n <= 100 000 se folose³te în locul unei matrice un vector de dimensiune 100 000
(liniarizare matrice).
20 fi>>nc;
21 for (i=1;i<nc;i++)
22 fi>>a[i]>>c[i];
23
24 int max_e=0,max_v=0,max_n=0,max_s=0;
25 for (i=1;i<=nc;i++)
26 {
27 for(j=0;j<4;j++)
28 p[i+1][j]=p[a[i]][j];
29
30 switch(c[i])
31 {
32 case ’N’:
33 p[i+1][2]--;
34 p[i+1][1]++;
35 if(p[i+1][1]>max_n)
36 max_n=p[i+1][1];
37 break;
38 case ’S’:
39 p[i+1][1]--;
40 p[i+1][2]++;
41 if(p[i+1][2]>max_s)
42 max_s=p[i+1][2];
43 break;
44 case ’E’:
45 p[i+1][3]--;
46 p[i+1][0]++;
47 if(p[i+1][0]>max_e)
48 max_e=p[i+1][0];
49 break;
50 case ’V’:
51 p[i+1][0]--;
52 p[i+1][3]++;
53 if(p[i+1][3]>max_v)
54 max_v=p[i+1][3];
55 break;
56 }
57 }
58
59 m=max_n+max_s+1;
60 n=max_e+max_v+1;
61 fo<<m<<" "<<n<<"\n";
62 p[1][1]=max_n+1;
63 p[1][2]=max_v+1;
64
65 for (i=1;i<nc;i++)
66 {
67 switch(c[i])
68 {
69 case ’N’:
70 p[i+1][1]=p[a[i]][1]-1;
71 p[i+1][2]=p[a[i]][2];
72 break;
73 case ’S’:
74 p[i+1][1]=p[a[i]][1]+1;
75 p[i+1][2]=p[a[i]][2];
76 break;
77 case ’E’:
78 p[i+1][1]=p[a[i]][1];
79 p[i+1][2]=p[a[i]][2]+1;
80 break;
81 case ’V’:
82 p[i+1][1]=p[a[i]][1];
83 p[i+1][2]=p[a[i]][2]-1;
84 break;
85 }
86 }
87
88 for (i=1;i<=nc;i++)
89 t[(p[i][1]-1)*n+p[i][2]-1]=1;
90
91 for (i=1;i<=m;i++)
92 {
93 for (j=1;j<=n;j++)
94 fo<<t[(i-1)*n+j-1]<<" ";
95 fo<<"\n";
CAPITOLUL 25. ONI 2015 482
96 }
97 }
98
99 if (op==2)
100 {
101 fi>>m>>n;
102 nc=0;
103 k=0;
104
105 for (j=1;j<=n;j++)
106 {
107 fi>>t[j-1];
108 nc+=t[j-1];
109 if (k==0 && t[j-1]==1)
110 k=j;
111 }
112
113 for (i=2;i<=m;i++)
114 for (j=1;j<=n;j++)
115 {
116 fi>>t[(i-1)*n+j-1];
117 nc+=t[(i-1)*n+j-1];
118 }
119
120 fo<<nc<<" "<<k<<"\n";
121 p[1][0]=1;
122 p[1][1]=k;
123 t[k-1]=2;
124 k=1;
125 v=1;
126
127 while (v<nc)
128 {
129 i=p[k][0];
130 j=p[k][1];
131
132 if (j<n && t[(i-1)*n+j]==1)
133 {
134 v++;
135 t[(i-1)*n+j]=v+1;
136 p[v][0]=i;
137 p[v][1]=j+1;
138 p[v][2]=1;
139 }
140
141 if (i>1 && t[(i-2)*n+j-1]==1)
142 {
143 v++;
144 t[(i-2)*n+j-1]=v+1;
145 p[v][0]=i-1;
146 p[v][1]=j;
147 p[v][2]=2;
148 }
149
150 if (i<m && t[i*n+j-1]==1)
151 {
152 v++;
153 t[i*n+j-1]=v+1;
154 p[v][0]=i+1;
155 p[v][1]=j;
156 p[v][2]=3;
157 }
158
159 if (j>1 && t[(i-1)*n+j-2]==1)
160 {
161 v++;
162 t[(i-1)*n+j-2]=v+1;
163 p[v][0]=i;
164 p[v][1]=j-1;
165 p[v][2]=4;
166 }
167
168 k++;
169 }
170
171 for (k=2;k<=nc;k++)
CAPITOLUL 25. ONI 2015 483
172 {
173 i=p[k][0];
174 j=p[k][1];
175 switch(p[k][2])
176 {
177 case 1: j--; break;
178 case 2: i++; break;
179 case 3: i--; break;
180 case 4: j++; break;
181 }
182
183 fo<<t[(i-1)*n+j-1]-1<<" "<<pct[p[k][2]]<<"\n"; }
184 }
185
186 return 0;
187 }
57 a[1][1]=1;
58 for(i=2;i<=t;i++) a[coada[i].x][coada[i].y]=1;
59
60 ///afisare
61 for(i=1;i<=lmax;i++)
62 {
63 for(j=1;j<cmax;j++)
64 fout<<a[i][j]<<" ";
65 fout<<a[i][j]<<endl; ///ultimul de pe linie
66 }
67 }
68
69 if (caz==2)
70 {
71 fin>>n>>m;
72 bool a[n+2][m+2]; ///definire locala de matrice
73
74 ///initializare bordura
75 for(i=0;i<=n+1;i++) a[i][0]=a[i][m+1]=0;
76 for(j=1;j<=m+1;j++) a[0][j]=a[n+1][j]=0;
77
78 ///prelucrare
79 t=0;
80 lmax=0;
81 cmax=0;
82 for(i=1;i<=n;i++)
83 for(j=1;j<=m;j++)
84 {
85 fin>>a[i][j];
86 t+=a[i][j];
87 if ((lmax+cmax==0) && (a[i][j]==1)) lmax=i,cmax=j;
88 }
89 fout<<t<<" "<<cmax<<"\n";
90
91 st=dr=1;
92 coada[1].x=lmax;
93 coada[1].y=cmax;
94 a[lmax][cmax]=0;
95 while(st<=dr)
96 {
97 // st - nr camerei vecina
98 lmax=coada[st].x;
99 cmax=coada[st].y;
100 for(k=0;k<4;k++)
101 if (a[lmax+dx[k]][cmax+dy[k]]==1)
102 {
103 fout<<st;
104 if (k==0) fout<<" E\n";
105 if (k==1) fout<<" N\n";
106 if (k==2) fout<<" S\n";
107 if (k==3) fout<<" V\n";
108 a[lmax+dx[k]][cmax+dy[k]]=0;
109 dr++;
110 coada[dr].x=lmax+dx[k];
111 coada[dr].y=cmax+dy[k];
112 }
113 st++;
114 }
115 }
116
117 return 0;
118 }
11 {
12 int l,c;
13 } q[100010];
14
15 int a[100010];
16 int dx[4]={0,1,-1,0}, dy[4]={1,0,0,-1},dx1[]={0,-1,1,0},dy1[]={-1,0,0,1};
17 char dir1[]="ESNV";
18 int var,i,j,n,lmax,cmax,cmin,v,m,nr,lmin;
19 char ch;int dir[256];
20
21 int cmp(matrice a, matrice b)
22 {
23 if(a.l==b.l)
24 return a.c<b.c;
25 return a.l<b.l;
26 }
27
28 int main()
29 {
30 f>>var;
31 dir[’E’]=0;
32 dir[’S’]=1;
33 dir[’N’]=2;
34 dir[’V’]=3;
35
36 if(var==1)
37 {
38 f>>n;
39 q[1].l=1;
40 q[1].c=1;
41 cmin=lmin=1000000000;
42
43 for(i=2;i<=n;i++)
44 {
45 f>>v>>ch;
46 q[i].l=q[v].l+dx[dir[ch]];
47 q[i].c=q[v].c+dy[dir[ch]];
48
49 if(q[i].l>lmax)
50 lmax=q[i].l;
51
52 if(q[i].l<lmin)
53 lmin=q[i].l;
54
55 if(q[i].c>cmax)
56 cmax=q[i].c;
57
58 if(q[i].c<cmin)
59 cmin=q[i].c;
60 }
61
62 if(cmin<=0)
63 {
64 cmax+=(-cmin)+1;
65 for(i=1;i<=n;i++)
66 q[i].c+=(-cmin)+1;
67 }
68
69 if(lmin<=0)
70 {
71 lmax+=(-lmin);
72 for(i=1;i<=n;i++)
73 q[i].l+=(-lmin)+1;
74 }
75
76 g<<lmax<<" "<<cmax<<’\n’;
77
78 sort(q+1,q+n+1,cmp);
79
80 int k=1;
81 for(i=1;i<=lmax;i++)
82 {
83 for(j=1;j<=cmax;j++)
84 if(i==q[k].l&&j==q[k].c)
85 {
86 g<<1<<" ";k++;
CAPITOLUL 25. ONI 2015 486
87 }
88 else
89 g<<0<<" ";
90
91 g<<’\n’;
92 }
93
94 return 0;
95 }
96
97 f>>n>>m;
98 int x,c1;
99 for(i=1;i<=n;i++)
100 for(j=1;j<=m;j++)
101 {
102 f>>x;
103 if(x==1)
104 {
105 nr++;
106 if(nr==1)
107 c1=j;
108
109 a[(i-1)*m+j]=-1;
110 }
111 }
112
113 g<<nr<<" "<<c1<<’\n’;
114
115 q[1].l=1;
116 q[1].c=c1;
117 a[c1]=1;
118 int p=1,u=1;
119 nr=1;
120
121 while(p<=u)
122 {
123 for(int k=0;k<4;k++)
124 {
125 int l=q[p].l+dx[k];
126 int c=q[p].c+dy[k];
127 int t=(l-1)*m+c;
128 if(l>=1&&l<=n&&c>=1&&c<=m&&a[t]==-1)
129 {
130 nr++;
131 g<<a[(q[p].l-1)*m+q[p].c]<<" "<<dir1[k]<<’\n’;
132 a[t]=nr;
133 u++;
134 q[u].l=l;
135 q[u].c=c;
136 }
137 }
138
139 p++;
140 }
141
142 return 0;
143 }
25.5 lenes
Problema 5 - lenes 100 de puncte
Lene³ul este un animal foarte lene³. El se deplaseaz numai în linie dreapt , dar face din când
în când câte un popas. în aceast problem lene³ul trebuie s traverseze de la nord la sud ³i
înapoi un teren reprezentat de o matrice de dimensiuni M N cu valori numere naturale. Valorile
reprezint efortul cerut pentru traversarea zonei respective. Lene³ul va alege o coloan pentru
traversarea matricei, iar pentru popasuri, în num r de k1, va alege zone al turate drumului din
CAPITOLUL 25. ONI 2015 487
coloana din stânga sau cea din dreapta. în cazul în care se va întoarce va proceda la fel, dar va
face k2 popasuri. Regulile problemei cer ca cele dou drumuri s nu aib zone comune.
Cerinµe
Cunoscând dimensiunile M , N ale terenului, num rul de popasuri k1, k2 ³i efortul pentru
traversarea ec rei zone a terenului, s se determine:
1. Efortul minim de parcurgere a terenului de la Nord la Sud, folosind k1 popasuri.
2. Efortul minim de parcurgere a terenului de la Nord la Sud ³i înapoi de la Sud la Nord,
folosind k1 popasuri la deplasarea Nord - Sud, respectiv k2 popasuri la deplasarea Sud - Nord.
Date de intrare
Fi³ierul lenes.in conµine:
a Pe prima linie un num r natural p reprezentând cerinµa de rezolvare. Pentru toate testele
de intrare num rul p poate avea doar valoarea 1 sau 2.
a Pe linia a doua sunt 4 numere naturale M , N , k1, k2, separate prin câte un spaµiu cu
semnicaµia de mai sus.
a Pe urm toarele M linii se g sesc câte N numere naturale separate prin câte un spaµiu,
reprezentând eforturile de traversare a ec rei zone a terenului.
Date de ie³ire
a Dac valoarea lui p este 1, se va rezolva numai cerinµa 1. în acest caz ³ierul lenes.out va
conµine un singur num r natural reprezentând efortul minim necesar pentru traversarea terenului
în condiµiile date de la Nord la Sud.
a Dac valoarea lui p este 2, se va rezolva numai cerinµa 2. în acest caz ³ierul lenes.out va
conµine un singur num r natural reprezentând efortul minim necesar pentru traversarea terenului
în condiµiile date în ambele sensuri de la Nord la Sud ³i de la Sud la Nord.
Restricµii ³i preciz ri
a 3 & M, N & 500
a 0 & k1, k2 & M
a Valorile din matrice sunt numere naturale din intervalul 1, 1000.
a Lene³ul poate s fac popasuri pe aceea³i linie în ambele celule din stânga ³i din dreapta
coloanei parcurse.
a Deplasarea între ultima zon a drumului parcurs de la Nord la Sud ³i prima zon a drumului
parcurs de la Sud la Nord la întoarcere se face cu efort 0.
Exemple:
35 if ( down )
36 ++ v[ Mat[lin + 1][i] ];
37 }
38
39 for ( int i = 0; i < VMax && k ; ++ i )
40 if ( k >= v[i] )
41 {
42 res += i * v[i];
43 k -= v[i];
44 }
45 else if ( v[i] )
46 {
47 res += k * i;
48 k = 0;
49 }
50
51 return res;
52 }
53
54 int case1()
55 {
56
57 int ret = get_line_sum(1, k1);
58
59 for ( int i = 1; i <= N; ++ i )
60 ret = min( ret, get_line_sum(i, k1));
61
62 return ret;
63 }
64
65 int case2()
66 {
67
68 int ret = oo;
69
70 for ( int i = 1; i <= N; ++ i )
71 V[i] = get_line_sum(i, k2);
72
73 left[1] = V[1];
74 for ( int i = 2; i <= N; ++ i )
75 left[i] = min(V[i], left[i - 1]);
76
77 right[N] = V[N];
78 for ( int i = N - 1; i > 0; -- i )
79 right[i] = min(V[i], right[i + 1]);
80
81
82 // computing distant lines
83 for ( int i = 1; i <= N; ++ i )
84 {
85 int r = get_line_sum(i, k1);
86 int other = oo;
87
88 if ( i > 3 ) other = min(other, left[i - 3]);
89 if ( i < N - 2) other = min(other, right[i + 3]);
90
91 ret = min(ret, r + other);
92 }
93
94 // computing adiacent lines
95 for ( int i = 1; i < N; ++ i )
96 {
97
98 int r1 = get_line_sum(i, k1 , true, false);
99 int r2 = get_line_sum(i + 1, k2, false, true);
100
101 ret = min( ret, r1 + r2 );
102
103 r1 = get_line_sum(i, k2 , true, false);
104 r2 = get_line_sum(i + 1, k1, false, true);
105
106 ret = min( ret, r1 + r2 );
107 }
108
109 //fprintf(stderr, "%d\n", ret);
110 // computing common margin lines
CAPITOLUL 25. ONI 2015 490
111
112 bool parity = true;
113
114 for ( int i = 1; i < N - 1; ++ i )
115 {
116
117 int sum = Sum[i] + Sum[i + 2];
118 int up = i - 1;
119 int mid = i + 1;
120 int down = i + 3;
121 int index_up = 1;
122 int index_down = 1;
123
124 for ( int j = 1; j <= M && j <= k1 + k2; ++ j )
125 sum += Mat[mid][j];
126
127 // adding extra elements
128 for ( int j = M + 1; j <= k1 + k2; ++ j )
129 {
130 if ( index_up <= k1 &&
131 Mat[up][index_up] <= Mat[down][index_down] ||
132 index_down > k2 )
133 {
134 sum += Mat[up][index_up];
135 ++ index_up;
136 }
137 else
138 {
139 sum += Mat[down][index_down];
140 ++ index_down;
141 }
142 }
143
144 ret = min(ret, sum);
145 // fprintf(stderr, "begining with: (%d, %d, %d)\n",
146 // index_up - 1, min(M, k1 + k2), index_down - 1);
147 for ( int j = min(M, k1 + k2); j > 0; -- j )
148 {
149 sum -= Mat[mid][j];
150 if ( index_up <= k1 &&
151 Mat[up][index_up] <= Mat[down][index_down] ||
152 index_down > k2 )
153 {
154 sum += Mat[up][index_up];
155 ++ index_up;
156 }
157 else
158 {
159 sum += Mat[down][index_down];
160 ++ index_down;
161 }
162
163 ret = min( ret, sum );
164 if ( ret == sum )
165 {
166 // fprintf(stderr, "(up: %d, mid: %d, down: %d -> %d\n",
167 // index_up - 1, j - 1, index_down - 1, ret);
168 }
169 }
170
171 if ( parity )
172 {
173 parity = false;
174 -- i;
175 }
176 else
177 {
178 parity = true;
179 }
180
181 swap( k1, k2 );
182 }
183
184 return ret;
185 }
186
CAPITOLUL 25. ONI 2015 491
44 }
45 a[i][0]=INT_MAX;
46 a[i][n+1]=INT_MAX;
47 }
48
49 for (j=1;j<=n;j++)
50 {
51 a[0][j]=INT_MAX;
52 a[m+1][j]=INT_MAX;
53 // sortam coloana j
54 for (i=1;i<m;i++)
55 for (i1=i+1;i1<=m;i1++)
56 if (a[i][j]>a[i1][j])
57 {
58 s=a[i][j];
59 a[i][j]=a[i1][j];
60 a[i1][j]=s;
61 }
62
63 }
64
65 if (p==1)
66 {
67 for (j=1;j<n;j++)
68 {
69 s=calc(j,k1);
70 if (s<mn) mn=s;
71 }
72 g<<mn<<"\n";
73 }
74 else
75 {
76 int cc;
77 // cazul 1: doua coloane alaturate (j si j+1)
78 for (j=2;j<n-1;j++)
79 {
80 for (int g=1;g<=2;g++)
81 {
82 s=0;
83 for (i=1;i<=k1;i++)
84 s=s+a[i][j-1];
85 for (i=1;i<=k2;i++)
86 s+=a[i][j+2];
87
88 s=s+sum[j]+sum[j+1];
89 if (s<mn) mn=s;
90 s1=k1; k1=k2; k2=s1;
91 }
92 }
93
94 // cazul 2: coloanele j si j+2 (o coloana goala intre ele)
95 for (j=2;j<n-2;j++)
96 for (int g=1; g<=2; g++)
97 {
98 s1=0;
99 for (i=1; i<=k1; i++)
100 s1+=a[i][j-1];
101 for (i=1; i<=k2; i++)
102 s1+=a[i][j+3];
103
104 // incercam sa inlocuim o parte din popasuri cu
105 // popasuri pe coloana din mijloc, j+1
106 i1=k1; i2=1; i3=k2;
107 s=s1;
108 do
109 {
110 ok=0;
111 if (i1>0 &&
112 a[i1][j-1]>=a[i3][j+3] &&
113 a[i1][j-1]>a[i2][j+1]) // inlocuim un popas de pe
114 // coloana j-1 cu popas pe
115 {
116 // coloana j+1
117 s=s+a[i2][j+1]-a[i1][j-1];
118 i1--;
119 i2++;
CAPITOLUL 25. ONI 2015 493
120 ok=1;
121 }
122 else
123 if (i3>0 &&
124 a[i3][j+3]>=a[i1][j-1] &&
125 a[i3][j+3]>a[i2][j+1]) // inlocuim un popas de pe
126 // coloana j-1 cu popas pe
127 {
128 // coloana j+1
129 s=s+a[i2][j+1]-a[i3][j+3];
130 i3--;
131 i2++;
132 ok=1;
133 }
134 } while (ok==1);
135
136 s+=sum[j]+sum[j+2];
137 if (s<mn)
138 mn=s;
139
140 s=k1; k1=k2; k2=s;
141 }
142
143 // caz particular la cazul 2: coloana 1 si coloana 3
144 for (int g=1;g<=2;g++)
145 {
146 s1=0;
147 for (i=1;i<=k1;i++)
148 s1+=a[i][2];
149
150 i1=k1+1;
151 i2=1;
152 for (i=1;i<=k2;i++)
153 if (i1<=m && a[i1][2]<a[i2][4])
154 {
155 s1+=a[i1][2]; i1++;
156 }
157 else
158 {
159 s1+=a[i2][4]; i2++;
160 }
161
162 s1+=sum[1]+sum[3];
163 if (s1<mn)
164 mn=s1;
165
166 s1=k1;
167 k1=k2;
168 k2=s1;
169 }
170
171 // caz particular la cazul 2: coloana n-2 si coloana n
172 for (int g=1;g<=2;g++)
173 {
174 s1=0;
175 for (i=1;i<=k1;i++)
176 s1+=a[i][n-1];
177
178 i1=k1+1;
179 i2=1;
180 for (i=1;i<=k2;i++)
181 if (i1<=m && a[i1][n-1]<a[i2][n-3])
182 {
183 s1+=a[i1][n-1]; i1++;
184 }
185 else
186 {
187 s1+=a[i2][n-3]; i2++;
188 }
189
190 s1+=sum[n]+sum[n-2];
191 if (s1<mn)
192 mn=s1;
193
194 s1=k1;
195 k1=k2;
CAPITOLUL 25. ONI 2015 494
196 k2=s1;
197 }
198
199 // cazul 3: doua linii total independente
200 for (j=1;j<=n-3;j++)
201 {
202 s1=calc(j,k1); // dus pe j intrs pe j1
203 s2=calc(j,k2); // dus pe j1 intors pe j
204 for (j1=j+3;j1<=n;j1++)
205 {
206 i1=s1+calc(j1,k2);
207 i2=s2+calc(j1,k1);
208 if (i1<mn)
209 mn=i1;
210 if (i2<mn)
211 mn=i2;
212 }
213 }
214
215 g<<mn<<"\n";
216 }
217 }
51 sum[j][1]=a[j][1];
52 for (i=2;i<=m;i++)
53 sum[j][i]=a[j][i]+sum[j][i-1];
54 }
55
56 if (p==1)
57 {
58 for (i=1;i<=n;i++)
59 {
60 s=calc(i,k1);
61 if (s<mn) mn = s;
62 }
63 g<<mn<<’\n’;
64 }
65 else
66 {
67 // cazul 1: doua coloane consecutive
68 for (i=2;i<n-1;i++)
69 {
70 s = sum[i-1][k1] + sum[i][m] + sum[i+1][m] + sum[i+2][k2];
71 if (s<mn) mn=s;
72
73 s = sum[i-1][k2] + sum[i][m] + sum[i+1][m] + sum[i+2][k1];
74 if (s<mn) mn=s;
75 }
76
77 // cazul 2: 2 coloane cu una intre ele
78 for (int tt=1;tt<=2;tt++)
79 {
80 for (i=2;i<=n-3;i++)
81 {
82
83 i1=k1; i2=0; i3=k2;
84 s = sum[i][m] + sum[i+2][m];
85 do
86 {
87 gg=0;
88 if (i1>=1 && i2<=m &&
89 a[i+1][i2+1]<a[i-1][i1] && a[i+3][i3]<=a[i-1][i1])
90 {
91 i1--; i2++; gg=1;
92 }
93 else
94 if (i3>=1 && i2<=m &&
95 a[i+1][i2+1]<a[i+3][i3] && a[i-1][i1]<=a[i+3][i3])
96 {
97 i3--; i2++; gg=1;
98 }
99 } while (gg==1);
100 s1 = s + sum[i-1][i1] + sum[i+1][i2] + sum[i+3][i3];
101 if (s1<mn) mn=s1;
102 }
103
104 // coloanele 1 si 3
105 s = sum[1][m] + sum[3][m];
106
107 if (n>3)
108 {
109 for (j=0;j<=k2;j++)
110 if (k1+j<=m && k2>j)
111 {
112 s1 = sum[2][k1+j];
113 s1 += sum[4][k2-j];
114 s1 += s;
115 if (s1<mn) mn=s1;
116 }
117 }
118 else
119 {
120 s=s+sum[2][k1+k2];
121 if (s<mn) mn=s;
122 }
123
124 // coloanele n-2 si n
125 if (n>3)
126 {
CAPITOLUL 25. ONI 2015 496
25.6 sipet
Problema 6 - sipet 100 de puncte
Un arheolog a g sit un sipet interesant. Dup ce l-a deschis cu grij , a
constatat cu surprindere c sipetul conµine b nuµi de aur. Uitându-se mai
atent a mai g sit ceva: un pergament ascuns într-un compartiment secret al
sipetului, cu un text scris într-o limb antic , pe care, din fericire, arheologul
o cuno³tea. Din text a reie³it c un grup de negustori foarte bogaµi a vrut
s ascund în mare secret averea breslei lor, format din monede de aur,
deoarece se prevestea un r zboi cumplit. Negustorii ³tiau c exist ³anse ca aceast comoar s
e g sit ³i conscat de du³mani, deci s-au sf tuit cum e mai bine s procedeze, cum s ascund
comoara. Arheologul a reu³it s deduc din text urm toarele:
a) Cele N monede, care formau averea breslei, au fost împ rµite în maximum trei feluri de
gr mezi, formate din p1, p2 ³i p3 b nuµi, p1, p2 ³i p3 ind numere prime consecutive, p1 $ p2 $ p3.
Fiecare gr mad a fost pus în întregime într-un sipet.
b) Este posibil s existe 0 (zero) gr mezi formate din p1 sau p2 sau p3 monede, scopul ind
s se obµin o împ rµire în care num rul monedelor r mase nedistribuite s e minim, iar dac
exist mai multe posibilit µi, se alege aceea pentru care num rul de gr mezi este mai mare. Dac
exist mai multe astfel de soluµii, se consider corect oricare dintre ele.
c) Monedele care nu au putut distribuite conform regulilor stabilite, au fost donate bisericii.
Cerinµe
Scrieµi un program care determin num rul maxim S de sipete ³i num rul sipetelor cu p1, p2
respectiv p3 monede, precum ³i suma donat bisericii.
Date de intrare
Fi³ierul sipet.in conµine, pe prima linie num rul natural T , iar pe urm toarele T linii câte
dou numerele naturale N ³i p1, desp rµite printr-un singur spaµiu.
CAPITOLUL 25. ONI 2015 497
Date de ie³ire
Fi³ierul sipet.out va conµine pe primele T linii câte 5 numere naturale, separate prin câte
un spaµiu: S , x, y , z ³i r, reprezentând num rul maxim S de sipete, num rul x de sipete cu
p1 monede, num rul y de sipete cu p2 monede, respectiv num rul z de sipete cu p3 monede ³i
num rul r de monede donate bisericii, corespunz toare datelor de intrare de pe linia T 1 a
³ierului sipet.in. Dac exist mai multe soluµii corecte, este acceptat oricare dintre ele.
Restricµii ³i preciz ri
a 1 & N & 10 000 000
a 2 & p1 $ p2 $ p3 & N
a 1 & T & 10 - în ³ierul de intrare nu vor mai mult de 10 perechi de numere N p1
Exemple:
sipet.in sipet.out Explicaµii
3 33000 - num rul maxim de sipete este 3, toate cu câte 3 monede;
15 5 21010 - sau: 2 0 2 0 0 (1*3+1*7=2*5=10); (ambele soluµii sunt co-
10 3 31110 recte!)
41 11 - num rul maxim de sipete este 3; 1 sipet cu 11, unul cu 13 ³i
unul cu 17 monede.
Timp maxim de executare/test: 1.5 secunde
Memorie: total 128 MB
Dimensiune maxim a sursei: 10 KB
71 (R == -1 || R != -1 &&
72 A + B + C < v[N - pos].a + v[N - pos].b + c ))
73 {
74 found = true;
75 A = v[N - pos].a;
76 B = v[N - pos].b;
77 C = c;
78 R = r;
79 }
80 }
81
82 for ( int a = 0; a * p[1] <= N; ++ a )
83 for ( int b = 0; a * p[1] + b * p[2] <= N && b < p[1]; ++ b )
84 {
85 int pos = a * p[1] + b * p[2];
86 bb[pos] = false;
87 }
88
89 printf("%d %d %d %d %d\n", A + B + C, A, B, C, R);
90
91 }
92
93 return 0;
94 }
ONI 2014
26.1 harta
Problema 1 - harta 100 de puncte
Pe baza unei imagini preluate din satelit, se realizeaz harta unei mici localit µi. Localitatea
ocup o suprafaµ dreptunghiular , cu laturile orientate pe direcµiile Nord-Sud, respectiv Est-Vest.
Studiind imaginea obµinut de la satelit, cartograi au constatat c toate cele k cl diri au
forma unor dreptunghiuri distincte. Imaginea poate reprezentat sub forma unui tablou cu
n m celule a³ezate pe n linii numerotate de la 1 la n ³i m coloane numerotate de la 1 la m.
Numim drum, un dreptunghi al tabloului care str bate întreaga localitate pe direcµia Est-Vest
³i are un num r maxim de linii sau un dreptunghi care str bate întreaga localitate pe direcµia
Nord-Sud ³i are un num r maxim de coloane. Drumurile, evident, nu trebuie s treac prin
cl diri.
Cartograi sunt interesaµi ca pe aceast hart s e reprezentate la scar doar cl dirile, nu
³i drumurile. De aceea, pentru realizarea h rµii, l µimile drumurilor au fost reduse la o singur
celul .
Tabloul care reprezint imaginea localit µii se codic astfel: 1 pentru o celul ocupat de o
cl dire ³i 0 pentru o celul neocupat .
Cerinµe
Cunoscând n, m ³i k , precum ³i tabloul care codic imaginea, se cere s se determine:
1. Num rul S de celule ocupate de c tre cl direa p tratic cu latura maxim ³i num rul
de cl diri C alese dintre celelalte k 1 cl diri, cu proprietatea c ecare dintre ele încape în
interiorul cl dirii p tratice cu latur maxim , f r s se suprapun peste celulele marginale ale
acesteia.
2. Tabloul care reprezint harta, în urma prelucr rii imaginii iniµiale.
Date de intrare
Fi³ierul de intrare harta.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 linia a doua se g sesc numerele naturale n, m ³i k separate prin câte un spaµiu.
Pe ecare dintre urm toarele k linii, se g sesc câte patru numere naturale i1 j1 i2 j2 separate
prin câte un spaµiu, primele dou numere reprezentând coordonatele celulei din extremitatea Nord-
Vest, iar ultimele dou , coordonatele celulei din extremitatea Sud-Est pentru ecare dintre cele k
cl diri.
Date de ie³ire
a Dac valoarea lui p este 1, atunci se va rezolva numai cerinµa 1. În acest caz, în ³ierul de
ie³ire harta.out se vor scrie cele dou numere S ³i C având semnicaµia descris la cerinµa 1,
separate printr-un singur spaµiu.
a Dac valoarea lui p este 2, atunci se va rezolva numai cerinµa 2. În acest caz, ³ierul de
ie³ire harta.out va conµine tabloul care reprezint harta obµinut pe baza imaginii din satelit.
Fi³ierul va avea n1 linii. Pe ecare linie se vor g si câte m1 valori 0 sau 1 separate prin câte un
singur spaµiu. Celulele situate pe marginile cl dirilor vor avea valoarea 1. Celulele din interiorul
cl dirilor, ca ³i cele din exterior, vor avea valoarea 0.
500
CAPITOLUL 26. ONI 2014 501
Restricµii ³i preciz ri
a3 & n, m & 1500
a1 & i1 & i2 & n
a 1 & j1 & j2 & m
a 1 & k & 1000
a 1 & Lmax & 50 (Lmax - latura maxim a unui dreptunghi)
a Se garanteaz c exist soluµie pentru ambele cerinµe, pentru toate datele de test.
a Pentru rezolvarea corect a primei cerinµe se acord 20 de puncte, iar pentru cerinµa a doua
se acord 80 de puncte.
Exemple:
Cerinµa a) - 20 puncte
Se determin latura Lmax a celei mai mari cl diri p tratice. Apoi, pentru ecare cl dire, se
determin dac laturile sale de lungimi L ³i H îndeplinesc condiµia: L $ Lmax 1 ³i H $ Lmax 1.
Cerinµa b) Total - 80 de puncte
Soluµia 1 - 30 de puncte
Liniile ³i coloanele care trebuie ³terse trebuie s nu conµin valori 1. Se reµin numerele de
ordine acele acestor linii ³i coloane. Dac determinarea acestor linii sau coloane se face prin
parcurgerea lor ³i ³tergerea se fece linie cu linie, respectiv coloan cu coloan , atunci, în funcµie
de alte optimiz ri, se pot obµine 30 de puncte.
Soluµia 2 - 55 de puncte
CAPITOLUL 26. ONI 2014 502
Se reµin la fel ca în soluµia anterioar numerele de ordine ale linilor ³i coloanelor care trebuie
³terse. Pentru ecare drum pe hart , se ³terg num rul maxim posibil de linii, respectiv coloane
adiacente.
Solutia 3 - 80 de puncte
În timpul citirii se genereaz cl dirile în interiorul matricei a conform cerinµelor de a³are.
Pentru a evita operaµiile de ³tergere de linii/coloane se marcheaz liniile/coloanele care trebuie
sa e ³terse astfel:
- initial a[i][0]=0; respectiv a[0][j]=0;
- dac linia i / coloana j intersecteaz cel puµin o cl dire, atunci a[i][0]=1; respectiv a[0][j]=1;
- dac a[i][0]==0 si a[i+1][0]==0, atunci a[i][0]=2; (marc m linia i pentru eliminare)
- dac a[0][j]==0 si a[0][j+1]==0, atunci a[0][j]=2; (marc m coloana j pentru eliminare)
- se a³eaz toate elementele a[i][j] pentru care a[i][0]!=2 && a[0][j]!=2
Soluµia 4 - 80 de puncte
Se reµin în ³irurul x toate liniile pe care se g se³te cel puµin o celul marginal ocupat de
o cl dire, iar în ³irul y toate coloanele pe care se g se³te cel puµin o celul marginal ocupat
de o cl dire. Pentru ecare dreptunghi i1 j1 i2 j2, se insereaz în x ³i y ³i coordonatele celulei
i1 1, j1 1 situate în exteriorul c dirii.
în ³irurile xa ³i xb se reµin liniile ³i coloanele tuturor celulelor marginale ocupate de cl diri.
Se ordoneaz cresc tor ³irurile x ³i y , apoi, pentru ecare valoare din ³irul xa, se caut binar
poziµia i a acesteia în ³irul x, iar pentru ecare valoare din ³irul ya, se caut binar poziµia j a
acesteia în ³irul y .
Poziµia i, j obµinut astfel reprezint noile coordonate ale unei celule marginale ocupate de
o cl dire pe hart .
38 int main()
39 {
40 fin >> T >> N >> M >> k;
41 int i1, j1, i2, j2;
42 x.pb(0), y.pb(0);
43 s1[0] = true;
44 s2[0] = true;
45 for ( int i = 0; i < k; ++i )
46 {
47 fin >> i1 >> j1 >> i2 >> j2;
48 d.pb(Dr(i1, j1, i2, j2));
49 L = i2 - i1 + 1, H = j2 - j1 + 1;
50 if ( L == H && L > Lmax )
51 Lmax = L;
52
53 for ( int i = i1; i <= i2; ++i)
54 {
55 xa.pb(i), ya.pb(j1), xa.pb(i), ya.pb(j2);
56 if ( !s1[i] )
57 x.pb(i), s1[i] = true;
58 }
59
60 for ( int j = j1; j <= j2; ++j )
61 {
62 xa.pb(i1), ya.pb(j);
63 xa.pb(i2), ya.pb(j);
64 if ( !s2[j] )
65 y.pb(j), s2[j] = true;
66 }
67
68 if ( !s1[i1 - 1] )
69 x.pb(i1 - 1), s1[i1 - 1] = true;
70 if ( !s2[j1 - 1] )
71 y.pb(j1 - 1), s2[j1 - 1] = true;
72 imax = max(imax, i2);
73 jmax = max(jmax, j2);
74 }
75
76 if ( T == 1 )
77 {
78 for ( int i = 0; i < k; ++i )
79 {
80 L = d[i].i2 - d[i].i1 + 1, H = d[i].j2 - d[i].j1 + 1;
81 if ( L < Lmax - 1 && H < Lmax - 1 )
82 nr_dr++;
83 }
84 fout << Lmax * Lmax << ’ ’ << nr_dr << ’\n’;
85 }
86 else
87 {
88 c1 = VI(imax + 1);
89 c2 = VI(jmax + 1);
90
91 for (int i = 0; i < x.size(); ++i )
92 c1[x[i]]++;
93 for (int i = 0; i < y.size(); ++i )
94 c2[y[i]]++;
95
96 for (int i = 1; i <= imax; ++i )
97 c1[i] += c1[i - 1];
98 for (int i = 1; i <= jmax; ++i )
99 c2[i] += c2[i - 1];
100
101 b1 = VI(x.size()); // aici - x sortat
102 b2 = VI(y.size());
103
104 for ( int i = 0; i < x.size(); ++i )
105 b1[c1[x[i]] - 1] = x[i], c1[x[i]]--;
106
107 for ( int i = 0; i < y.size(); ++i )
108 b2[c2[y[i]] - 1] = y[i], c2[y[i]]--;
109
110 n = 0, m = 0; int i, j;
111 for (size_t k = 0; k < xa.size(); ++k )
112 {
113 i= GetPos(b1, xa[k]);
CAPITOLUL 26. ONI 2014 504
29 }
30 fclose(fin);
31 }
32
33 void solve()
34 {
35 int a,b;
36 if(p==1)
37 {
38 for(int i=1;i<=k;i++)
39 {
40 a=(d[i].i2-d[i].i1+1);
41 b=(d[i].j2-d[i].j1+1);
42 if(a==b)
43 {
44 s=a*b;
45 if(s>S)
46 {
47 S=s;
48 dmax=d[i];
49 }
50 }
51 }
52
53 for(int i=1;i<=k;i++)
54 {
55 if(d[i].i2-d[i].i1+1<=dmax.i2-dmax.i1-1&&
56 d[i].j2-d[i].j1+1<=dmax.j2-dmax.j1-1)
57 C++;
58 }
59 fprintf(fout,"%d %d\n",S,C);
60
61 }
62 else
63 {
64 int i,j,di=0,dj=0,ix=1,iy,xx=1,yy=1;
65 dreptunghi aux;
66 for(i=1;i<k;i++)
67 for(j=i+1;j<=k;j++)
68 {
69 if(d[i].i1>d[j].i1)
70 {
71 aux=d[i];
72 d[i]=d[j];
73 d[j]=aux;
74 }
75
76 if(d2[i].i2>d2[j].i2)
77 {
78 aux=d2[i];
79 d2[i]=d2[j];
80 d2[j]=aux;
81 }
82
83 if(d1[i].j1>d1[j].j1)
84 {
85 aux=d1[i];
86 d1[i]=d1[j];
87 d1[j]=aux;
88 }
89 }
90
91 for(i=1;i<=k;i++)
92 {
93 if(d[i].i1-2>=xx)
94 for(int ix=xx;ix<=d[i].i1-2;ix++)
95 linii[ix]=1;
96
97 if(d[i].i2>=xx)
98 xx=d[i].i2+1;
99
100 if(d1[i].j1-2>=yy)
101 for(int iy=yy;iy<=d1[i].j1-2;iy++)
102 coloane[iy]=1;
103
104 if(d1[i].j2>=yy)
CAPITOLUL 26. ONI 2014 506
105 yy=d1[i].j2+1;
106 }
107
108 if(n-xx>=1)
109 for(int ix=xx;ix<=n-1;ix++)
110 linii[ix]=1;
111
112 if(m-yy>=1)
113 for(int iy=yy;iy<=m-1;iy++)
114 coloane[iy]=1;
115
116 int ii=1,iii=1;
117 i=1;
118 while(i<=n)
119 {
120 if(!linii[i])
121 {
122 while(d[ii].i1==i&&ii<=k)
123 {
124 x[d[ii].j1]=x[d[ii].j2]=d[ii].i2-d[ii].i1+1;
125
126 for(int jj=d[ii].j1+1;jj<d[ii].j2;jj++)
127 x[jj]=1;
128 ii++;
129 }
130
131 while(d2[iii].i2==i&&iii<=k)
132 {
133 for(int jj=d2[iii].j1+1;jj<d2[iii].j2;jj++)
134 x[jj]=1;
135 iii++;
136 }
137
138 for(j=1;j<=m;j++)
139 if(!coloane[j])
140 if(!x[j])
141 fprintf(fout,"0 ");
142 else
143 {
144 fprintf(fout,"1 ");
145 x[j]--;
146 }
147 fprintf(fout,"\n");
148 }
149
150 i++;
151 }
152 }
153 }
154
155 int main()
156 {
157 read();
158 solve();
159 fclose(fout);
160 return 0;
161 }
16 } d[DIM];
17
18 int sc[DIM], sl[DIM], a[DIM][DIM];
19 int k, N, M, Lmax, L, H, T, nr_dr;
20
21 void WriteMatr(int a[][DIM], int N, int M);
22 void DeleteLine(int L);
23 void DeleteColumn(int C);
24
25 int main()
26 {
27 fin >> T >> N >> M >> k;
28 int i1, j1, i2, j2;
29
30 for ( int i = 0; i < k; ++i )
31 {
32 fin >> i1 >> j1 >> i2 >> j2;
33 d[i].i1 = i1, d[i].j1 = j1, d[i].i2 = i2, d[i].j2 = j2;
34 L = i2 - i1 + 1, H = j2 - j1 + 1;
35
36 if ( L == H && L > Lmax )
37 Lmax = L;
38
39 for ( int i = i1; i <= i2; ++i)
40 a[i][j1] = a[i][j2] = 1, sl[i] += 2;
41
42 for ( int j = j1; j <= j2; ++j )
43 a[i1][j] = a[i2][j] = 1, sc[j] += 2;
44 }
45
46 if ( T == 1 )
47 {
48 for ( int i = 0; i < k; ++i )
49 {
50 L = d[i].i2 - d[i].i1 + 1, H = d[i].j2 - d[i].j1 + 1;
51 if ( L < Lmax - 1 && H < Lmax - 1 )
52 nr_dr++;
53 }
54
55 fout << Lmax * Lmax << ’ ’ << nr_dr << ’\n’;
56 }
57 else
58 {
59 for ( int col = 1; col <= M; ++col ) // pt fiec coloana O(M)
60 {
61 int k = 0;
62 while ( col + k <= M && !sc[col + k] )
63 k++;
64
65 if ( k > 1 )
66 {
67 for ( int j = col + 1; j < col + k; ++j )
68 a[1][j] = 2;
69
70 col += k - 1;
71 }
72 }
73
74 for ( int j = 1; j <= M; ++j )
75 if ( a[1][j] == 2 )
76 DeleteColumn(j), --j;
77
78 for ( int lin = 1; lin <= N; ++lin ) // pt fiec linie O(N)
79 {
80 int k = 0;
81 while ( lin + k <= N && !sl[lin + k] )
82 k++;
83
84 if ( k > 1 )
85 {
86 for ( int i = lin + 1; i < lin + k; ++i )
87 a[i][1] = 2;
88
89 lin += k - 1;
90 }
91 }
CAPITOLUL 26. ONI 2014 508
92
93 for ( int i = 1; i <= N; ++i )
94 if ( a[i][1] == 2 )
95 DeleteLine(i), --i;
96
97 WriteMatr(a, N, M);
98 }
99
100 fin.close();
101 fout.close();
102 return 0;
103 }
104
105 void DeleteLine(int L)
106 {
107 for ( int j = 1; j <= M; ++j )
108 for ( int i = L; i < N; ++i )
109 a[i][j] = a[i + 1][j];
110 N--;
111 }
112
113
114 void DeleteColumn(int C)
115 {
116 for ( int i = 1; i <= N; ++i )
117 for ( int j = C; j < M; ++j )
118 a[i][j] = a[i][j + 1];
119 M--;
120 }
121
122 void WriteMatr(int a[][DIM], int N, int M)
123 {
124 for ( int i = 1; i <= N; ++i )
125 {
126 for ( int j = 1; j <= M; ++j )
127 fout << a[i][j] << ’ ’;
128 fout << ’\n’;
129 }
130 }
34 {
35 fin >> i1 >> j1 >> i2 >> j2;
36 d[i].i1 = i1, d[i].j1 = j1, d[i].i2 = i2, d[i].j2 = j2;
37 L = i2 - i1 + 1, H = j2 - j1 + 1;
38 if ( L == H && L > Lmax )
39 Lmax = L;
40
41 for ( int i = i1; i <= i2; ++i)
42 a[i][j1] = a[i][j2] = 1, sl[i] += 2;
43
44 for ( int j = j1; j <= j2; ++j )
45 a[i1][j] = a[i2][j] = 1, sc[j] += 2;
46 }
47
48 if ( T == 1 )
49 {
50 for ( int i = 0; i < k; ++i )
51 {
52 L = d[i].i2 - d[i].i1 + 1, H = d[i].j2 - d[i].j1 + 1;
53 if ( L < Lmax - 1 && H < Lmax - 1 )
54 nr_dr++;
55 }
56
57 fout << Lmax * Lmax << ’ ’ << nr_dr << ’\n’;
58 }
59 else
60 {
61 for ( int col = 1; col <= M; ++col ) // pt fiec coloana O(M)
62 {
63 int k = 0;
64 while ( col + k <= M && !sc[col + k] )
65 k++;
66
67 if ( k > 1 )
68 {
69 for ( int j = col + 1; j < col + k; ++j )
70 a[1][j] = 2;
71
72 col += k - 1;
73 }
74 }
75
76 for ( int j = 1; j <= M; ++j )
77 {
78 int k = 0;
79 while ( j + k <= M && a[1][j + k] == 2 )
80 ++k;
81
82 if ( k ) DeleteKColumns(j, k), --j;
83 }
84
85 for ( int lin = 1; lin <= N; ++lin ) // pt fiec linie O(N)
86 {
87 int k = 0;
88 while ( lin + k <= N && !sl[lin + k] )
89 k++;
90
91 if ( k > 1 )
92 {
93 for ( int i = lin + 1; i < lin + k; ++i )
94 a[i][1] = 2;
95 lin += k - 1;
96 }
97 }
98
99 for ( int i = 1; i <= N; ++i )
100 {
101 int k = 0;
102 while ( i + k <= N && a[i + k][1] == 2 )
103 ++k;
104
105 if ( k ) DeleteKLines(i, k), --i;
106 }
107
108 WriteMatr(a, N, M);
109 }
CAPITOLUL 26. ONI 2014 510
110
111 fin.close();
112 fout.close();
113 return 0;
114 }
115
116 void DeleteKLines(int L, int k)
117 {
118 for ( int j = 1; j <= M; ++j )
119 for ( int i = L; i + k <= N; ++i )
120 a[i][j] = a[i + k][j];
121
122 N -= k;
123 }
124
125 void DeleteKColumns(int C, int k)
126 {
127 for ( int i = 1; i <= N; ++i )
128 for ( int j = C; j + k <= M; ++j )
129 a[i][j] = a[i][j + k];
130
131 M -= k;
132 }
133
134 void WriteMatr(int a[][DIM], int N, int M)
135 {
136 for ( int i = 1; i <= N; ++i )
137 {
138 for ( int j = 1; j <= M; ++j )
139 fout << a[i][j] << ’ ’;
140
141 fout << ’\n’;
142 }
143 }
39
40 a = (Max - 1) * (Max - 1);
41 nr = 0;
42 for (i=1; i<=k; ++i)
43 if (C[i].l * C[i].L <= a &&
44 C[i].l < Max - 1 &&
45 C[i].L < Max - 1)
46 ++nr;
47
48 printf("%d %d\n", Max * Max, nr);
49 }
50 else
51 {
52 for (; k>0; --k)
53 {
54 for (i=C[k].x1; i<=C[k].x2; ++i)
55 {
56 A[i][C[k].y1] = A[i][C[k].y2] = 1;
57 l[i] = 1;
58 }
59
60 for (i=C[k].y1; i<=C[k].y2; ++i)
61 {
62 A[C[k].x1][i] = A[C[k].x2][i] = 1;
63 c[i] = 1;
64 }
65 }
66
67 for (i=1; i<=m; ++i)
68 if (c[i] == 0)
69 {
70 j = i + 1;
71 while (c[j] == 0 && j <= m)
72 c[j++] = 2;
73 }
74
75 for (i=1; i<=n; ++i)
76 if (l[i] == 0)
77 {
78 j = i + 1;
79 while (l[j] == 0 && j <= n)
80 l[j++] = 2;
81 }
82
83 for (i=1; i<=n; ++i)
84 if (l[i] < 2)
85 {
86 for (j=1; j<=m; ++j)
87 if (c[j] < 2) printf("%d ", (int) A[i][j]);
88 printf("\n");
89 }
90 }
91
92 return 0;
93 }
18
19 int main()
20 {
21 fin>>p>>n>>m>>k;
22 if(p==1)
23 {
24 for(i=1;i<=k;i++)
25 {
26 fin>>i1>>j1>>i2>>j2;
27 lat=i2-i1+1;
28 lung=j2-j1+1;
29 lx=lat;
30 if(lung>lx)lx=lung;
31 patrate[lx]++;
32 if(lat==lung)
33 if(lat>lmax)
34 lmax=lat;
35 }
36
37 S=lmax*lmax;
38 C=0;
39 for(i=1;i<=lmax-2;i++)
40 C=C+patrate[i];
41
42 fout<<S<<" "<<C;
43 }
44 else
45 {
46 for(i=1;i<=k;i++)
47 {
48 fin>>i1>>j1>>i2>>j2;
49 for(l1=i1;l1<=i2;l1++)
50 {
51 a[l1][j1]=1;
52 a[l1][j2]=1;
53 a[l1][0]=1;//marcat linie care ramane
54 }
55
56 for(c1=j1;c1<=j2;c1++)
57 {
58 a[i1][c1]=1;
59 a[i2][c1]=1;
60 a[0][c1]=1;//marcat coloana care ramane
61 }
62 }
63
64 for(l1=1;l1<=n-1;l1++)
65 if(a[l1][0]==0 && a[l1+1][0]==0)
66 a[l1][0]=2;//linia l1 se va sterge
67
68 for(c1=1;c1<=m-1;c1++)
69 if(a[0][c1]==0 && a[0][c1+1]==0)
70 a[0][c1]=2;//coloana c1 se va sterge
71
72 //vom pastra doar liniile si coloanele marcate diferit de 2
73 for (l1=1;l1<=n;l1++)
74 {
75 if(a[l1][0]!=2)
76 {
77 for(c1=1;c1<=m;c1++)
78 if(a[0][c1]!=2)
79 fout<<(int)a[l1][c1]<<" ";
80
81 fout<<"\n";
82 }
83 }
84 }
85
86 fout.close();
87 fin.close();
88 return 0;
89 }
1 /* 100 puncte
2 Constantin Galatan
3 */
4 #include <fstream>
5 #include <vector>
6 #include <algorithm>
7
8 using namespace std;
9
10 #define pb push_back
11 #define DIM 1501
12
13 ifstream fin("harta.in");
14 ofstream fout("harta.out");
15
16 struct Dr
17 {
18 int i1, j1, i2, j2;
19 Dr(int _i1, int _j1, int _i2, int _j2)
20 : i1(_i1), j1(_j1), i2(_i2), j2(_j2) {
21 }
22 };
23
24 typedef vector<int> VI;
25
26 VI xa, ya, x, y;
27 vector<Dr> d;
28 int imax, jmax;
29 int T, N, M, n, m, k, L, H, Lmax;
30 bool A[DIM][DIM], s1[DIM], s2[DIM];
31
32 void One(), Two(), WriteMatr(bool a[][DIM], int N, int M);
33
34 int main()
35 {
36 fin >> T >> N >> M >> k;
37 int i1, j1, i2, j2;
38 x.pb(0), y.pb(0);
39 s1[0] = true, s2[0] = true;
40 for ( int i = 0; i < k; ++i )
41 {
42 fin >> i1 >> j1 >> i2 >> j2;
43 d.pb(Dr(i1, j1, i2, j2));
44 L = i2 - i1 + 1, H = j2 - j1 + 1;
45 if ( L == H && L > Lmax )
46 Lmax = L;
47
48 for ( int i = i1; i <= i2; ++i)
49 {
50 xa.pb(i), ya.pb(j1), xa.pb(i), ya.pb(j2);
51 if ( !s1[i] ) x.pb(i), s1[i] = true;
52 }
53
54 for ( int j = j1; j <= j2; ++j )
55 {
56 xa.pb(i1), ya.pb(j); xa.pb(i2), ya.pb(j);
57 if ( !s2[j] ) y.pb(j), s2[j] = true;
58 }
59
60 if ( !s1[i1 - 1] )
61 x.pb(i1 - 1), s1[i1 - 1] = true;
62 if ( !s2[j1 - 1] )
63 y.pb(j1 - 1), s2[j1 - 1] = true;
64 imax = max(imax, i2); jmax = max(jmax, j2);
65 }
66
67 if ( T == 1 )
68 One();
69 else
70 Two();
71
72 fin.close();
73 fout.close();
74 return 0;
75 }
76
CAPITOLUL 26. ONI 2014 514
77 void One()
78 {
79 int nr_dr(0);
80 for ( int i = 0; i < k; ++i )
81 {
82 L = d[i].i2 - d[i].i1 + 1, H = d[i].j2 - d[i].j1 + 1;
83 if ( L < Lmax - 1 && H < Lmax - 1)
84 nr_dr++;
85 }
86 fout << Lmax * Lmax << ’ ’ << nr_dr << ’\n’;
87 }
88
89 void Two()
90 {
91 sort(x.begin(), x.end());
92 sort(y.begin(), y.end());
93
94 x.erase(unique(x.begin(), x.end()), x.end());
95 x.erase(unique(x.begin(), x.end()), x.end());
96 y.erase(unique(y.begin(), y.end()), y.end());
97
98 int i, j;
99 for (size_t k = 0; k < xa.size(); ++k )
100 {
101 i = lower_bound(x.begin(), x.end(), xa[k]) - x.begin();
102 j = lower_bound(y.begin(), y.end(), ya[k]) - y.begin();
103 n = max(n, i), m = max(m, j);
104 A[i][j] = 1;
105 }
106
107 if ( n < M ) n++;
108 if ( m < M ) m++;
109 WriteMatr(A, n, m);
110 }
111
112 void WriteMatr(bool a[][DIM], int N, int M)
113 {
114 for ( int i = 1; i <= N; ++i )
115 {
116 for ( int j = 1; j <= M; ++j )
117 fout << a[i][j] << ’ ’;
118 fout << ’\n’;
119 }
120 }
26.2 qvect
Problema 2 - qvect 100 de puncte
Se consider N vectori cu elemente întregi, numerotaµi de la 1 la N , sortaµi cresc tor, ecare
vector având un num r precizat de elemente.
Cerinµe
S se r spund la Q întreb ri de tipul:
a) 1 i j
cu semnicaµia: care este minimul dintre modulele diferenµelor oric ror dou elemente, pri-
mul element aparµinând vectorului numerotat cu i, iar cel de al doilea element aparµinând
vectorului numerotat cu j ?
b) 2 i j
cu semnicaµia: care este valoarea ce se g se³te pe poziµia median în vectorul obµinut prin
interclasarea vectorilor având numerele de ordine i, i 1, ...,j (i $ j ).
Date de intrare
CAPITOLUL 26. ONI 2014 515
Fi³ierul de intrare qvect.in conµine pe prima linie dou numerele naturale N Q, separate
printr-un spaµiu, ce reprezint num rul de vectori, respectiv num rul de întreb ri.
Pe ecare dintre urm toarele N linii se g se³te descrierea unui vector sub forma: k a1 a2 ... ak ,
unde k reprezint num rul de elemente, iar a1 , ..., ak reprezint elementele vectorului, separate
prin câte un spaµiu.
Pe ecare dintre urm toarele Q linii se g se³te descrierea unei întreb ri sub forma unui triplet
de numere naturale: t i j , separate prin câte un spaµiu, unde t reprezint tipul întreb rii ³i poate
lua numai valorile 1 sau 2, iar i ³i j au semnicaµia precizat în cerinµ .
Date de ie³ire
Fi³ierul de ie³ire qvect.out va conµine Q numere întregi, câte unul pe linie, reprezentând în
ordine, r spunsurile la cele Q întreb ri.
Restricµii ³i preciz ri
a 1 & N, i, j & 100
a 1 & Q & 1 000
a 1 & t & 2
a 1 & k & 5 000
a -1 000 000 000 & a1 , a2 , ...ak & 1 000 000 000
a Prin valoarea aat pe poziµia median a unui vector a cu k elemente se înµelege valoarea
elementului situat pe poziµia [k/2], adic partea întreag a lui k / 2.
a 15% dintre teste vor conµine numai întreb ri de tipul 1
a 15% dintre teste vor conµine numai întreb ri de tipul 2
Exemple:
qvect.in qvect.out Explicaµii
3 3 13 Prima întrebare este de tipul 2. Vectorul nou obµinut prin
7 1 4 5 8 11 18 19 3 interclasarea vectorilor numerotaµi cu 2 ³i cu 3 este urm -
6 2 4 5 10 21 29 10 torul: 2, 4, 5, 10, 13, 14, 15, 15, 21, 29 ³i conµine 6+4=10
4 13 14 15 15 elemente, valoarea elementului median este 13.
2 23 A doua întrebare este de tipul 1. Diferenµa minim se
1 23 obµine pentru perechea (10,13), unde valoarea 10 aparµine
2 13 vectorului numerotat cu 2, iar valoarea 13 aparµine vecto-
rului numerotat cu 3.
A treia întrebare este de tipul 2. Poziµia median în vecto-
rul nou obµinut prin interclasare este (7+6+4)/2 = 8, deci
valoarea ce se g se³te pe poziµia median este 10.
Timp maxim de executare/test: 1.0 secunde
Memorie: total 8 MB din care pentru stiv 2 MB
Dimensiune maxim a sursei: 15 KB
66 }
67
68 return rez;
69 }
70
71 int main()
72 {
73 int n, q, op, i, j, x, y, m;
74
75 f >> n >> q;
76 for (i=1; i<=n; ++i)
77 {
78 f >> x;
79 a[i][0] = x;
80 nr[i] = nr[i-1] + x;
81 for (j=1; j<=x; ++j)
82 f>> a[i][j];
83 }
84
85 while ( q-- )
86 {
87 f >> op >> x >> y;
88 switch (op)
89 {
90 case 1:
91 {
92 g << q1(x, y) << "\n";
93 break;
94 };
95 case 2:
96 {
97 m = (nr[y] - nr[x-1]) / 2;
98 g << q2(x, y, m) << "\n";
99 break;
100 };
101 }
102 }
103
104 return 0;
105 }
1 #include <algorithm>
2 #include <fstream>
3
4 using namespace std;
5
6 ifstream f("qvect.in");
7 ofstream g("qvect.out");
8
9 int a[101][5005], poz[101], n, q,nr;
10 int b[250005],c[250005];
11
12 void citeste()
13 {
14 f>>n>>q;
15 for(int i=1;i<=n;i++)
16 {
17 f>>a[i][0];
18 for(int j=1;j<=a[i][0];j++)
19 f>>a[i][j]; poz[i]=1;
20 }
21 }
22
23 int abs(int x)
24 {
25 return max(x,-x);
26 }
27
28 int cerinta1(int n1, int n2)
29 {
30 int i=1,j=1,m=0,nr1,nr2, dif=1000000005,x,y;
31 nr1=a[n1][0]; nr2=a[n2][0];
32 while(i<=nr1 && j<=nr2)
33 {
34 if(a[n1][i]<a[n2][j])
35 {
36 x=a[n1][i];i++;
37 if(m==2)
38 dif=min(dif, abs(x-y));
39 m=1;
40 }
41 else
42 if(a[n1][i]>a[n2][j])
43 {
44 y=a[n2][j];j++;
45 if(m==1)
46 dif=min(dif, abs(x-y));
47 m=2;
48 }
49 else
50 if(a[n1][i]==a[n2][j])
51 return 0;
52 }
53
54 if(i<=nr1)
55 {
56 if(m==2)
57 dif=min(dif, abs(a[n1][i]-y));
58 }
59 else
60 {
61 if(m==1)
62 dif=min(dif, abs(x-a[n2][j]));
63 }
64
65 return dif;
66 }
67
68 int interc(int k, int p,int nr)
69 {
70 int i=1,j=1,n=0;
71 while(i<=k && j<=a[p][0] && n<nr)
72 if(b[i]<=a[p][j])
73 c[++n]=b[i++];
74 else
75 c[++n]=a[p][j++];
76
CAPITOLUL 26. ONI 2014 521
31 nr2=a[n2][0];
32 while(i<=nr1 && j<=nr2)
33 {
34 if(a[n1][i]<a[n2][j])
35 { x=a[n1][i];i++;
36 if(m==2)
37 dif=min(dif, abs(x-y));
38 m=1;
39 }
40 else
41 if(a[n1][i]>a[n2][j])
42 {
43 y=a[n2][j];j++;
44 if(m==1)
45 dif=min(dif, abs(x-y));
46 m=2;
47 }
48 else
49 if(a[n1][i]==a[n2][j])
50 return 0;
51 }
52
53 if(i<=nr1)
54 {
55 if(m==2)
56 dif=min(dif, abs(a[n1][i]-y));
57 }
58 else
59 {
60 if(m==1)
61 dif=min(dif, abs(x-a[n2][j]));
62 }
63
64 return dif;
65 }
66
67 int minim(int n1, int n2)
68 {
69 int p=0,i, mi=1000000005,j,k;
70
71 for(i=n1;i<=n2;i++)
72 {
73 j=poz[i];
74 if(j<=a[i][0] && a[i][j]<mi)
75 {
76 mi=a[i][j];
77 p=i;
78 }
79 }
80
81 poz[p]++;
82 return mi;
83 }
84
85 int cerinta2(int n1, int n2)
86 {
87 int i,med,nr=0;
88 for(i=1;i<=n;i++)
89 poz[i]=1;
90
91 for(i=n1;i<=n2;i++)
92 nr+=a[i][0];
93
94 nr/=2;
95 for(i=1;i<=nr;i++)
96 med=minim(n1,n2);
97
98 return med;
99 }
100
101 int main()
102 {
103 citeste();
104
105 int k,t,i,j;
106
CAPITOLUL 26. ONI 2014 523
107 for(k=1;k<=q;k++)
108 {
109 f>>t>>i>>j;
110 if(t==1)
111 g<<cerinta1(i,j)<<endl;
112 else
113 g<<cerinta2(i,j)<<endl;
114 }
115
116 return 0;
117 }
62 dif=min(dif, abs(a[n1][i]-y));
63 }
64 else
65 {
66 if(m==1)
67 dif=min(dif, abs(x-a[n2][j]));
68 }
69
70 return dif;
71 }
72
73 int cerinta2(int n1, int n2)
74 {
75 int i,j,nr=0,k;
76 for(i=n1;i<=n2;i++)
77 nr+=a[i][0];
78
79 nr/=2;
80 k=min(nr,a[n1][0]);
81 for(i=1;i<=k;i++)
82 b[i]=a[n1][i];
83
84 for(i=n1+1;i<=n2;i++)
85 {
86 for(j=1;j<=a[i][0] && j<=nr;j++)
87 b[++k]=a[i][j];
88
89 sort(b+1,b+k+1);
90 k=min(k,nr);
91 }
92
93 return b[k];
94 }
95
96 int main()
97 {
98 citeste();
99 int k,t,i,j;
100 for(k=1;k<=q;k++)
101 {
102 f>>t>>i>>j;
103 if(t==1)
104 g<<cerinta1(i,j)<<endl;
105 else
106 g<<cerinta2(i,j)<<endl;
107 }
108
109 return 0;
110 }
24 int abs(int x)
25 {
26 return max(x,-x);
27 }
28
29 int cerinta1(int n1, int n2)
30 {
31 int i=1,j=1,m=0,nr1,nr2, dif=1000000005,x,y;
32 nr1=a[n1][0];
33 nr2=a[n2][0];
34
35 while(i<=nr1 && j<=nr2)
36 {
37 if(a[n1][i]<a[n2][j])
38 {
39 x=a[n1][i];i++;
40 if(m==2)
41 dif=min(dif, abs(x-y));
42 m=1;
43 }
44 else
45 if(a[n1][i]>a[n2][j])
46 {
47 y=a[n2][j];
48 j++;
49 if(m==1)
50 dif=min(dif, abs(x-y));
51 m=2;
52 }
53 else
54 if(a[n1][i]==a[n2][j])
55 return 0;
56 }
57
58 if(i<=nr1)
59 {
60 if(m==2)
61 dif=min(dif, abs(a[n1][i]-y));
62 }
63 else
64 {
65 if(m==1)
66 dif=min(dif, abs(x-a[n2][j]));
67 }
68
69 return dif;
70 }
71
72
73 int cerinta2(int n1, int n2)
74 {
75 int i,j,nr=0,k;
76 for(i=n1;i<=n2;i++)
77 nr+=a[i][0];
78
79 nr/=2;
80 k=min(nr,a[n1][0]);
81 for(i=1;i<=k;i++)
82 b[i]=a[n1][i];
83
84 for(i=n1+1;i<=n2;i++)
85 {
86 for(j=1;j<=a[i][0] && j<=nr;j++)
87 b[++k]=a[i][j];
88
89 sort(b+1,b+k+1);
90 k=min(k,nr);
91 }
92
93 return b[k];
94 }
95
96 int main()
97 {
98 citeste();
99 freopen("qvect.out","w", stdout);
CAPITOLUL 26. ONI 2014 526
60 q=b[i];
61 r=-1;
62 while(p<=q && r==-1)
63 {
64 m=p+(q-p)/2;
65 if(v==a[i][m])
66 return m;
67
68 if(v<a[i][m])
69 q=m-1;
70 else
71 p=m+1;
72 }
73
74 return -1;
75 }
76
77 void sortare()
78 {
79 int i,j,k,p,q,r,s,ok;
80
81 //sterg elementele suplimentare
82 k=1;
83 for (i=2;i<=n;i++)
84 {
85 if(v[k]!=v[i])
86 v[++k]=v[i];
87 }
88
89 n=k;
90 ok=0;
91 while(ok==0)
92 {
93 r=0;
94 s=0;
95 do
96 {
97 p=r+1;
98 q=p;
99 while(q+1<=n && v[q]<=v[q+1])
100 q++;
101
102 s++;
103 r=q+1;
104 while(r+1<=n && v[r]<=v[r+1])
105 r++;
106
107 if(p<=q && q<r && r<=n)
108 {
109 s++;
110 i=p;
111 j=q+1;
112 k=0;
113 while(i<=q && j<=r)
114 {
115 if(v[i]<v[j])
116 w[++k]=v[i++];
117 else
118 w[++k]=v[j++];
119 }
120
121 while(i<=q)
122 w[++k]=v[i++];
123
124 while(j<=r)
125 w[++k]=v[j++];
126
127 i=p;
128 for(j=1;j<=k;j++)
129 v[i++]=w[j];
130 }
131 } while(r<n);
132
133 if(s==1) ok=1;
134 }
135
CAPITOLUL 26. ONI 2014 528
212 {
213 fin>>a[i][j];
214 n++;
215 v[n]=a[i][j];
216 }
217 }
218
219 sortare();
220
221 for (i=1;i<=Q;i++)
222 {
223 fin>>t>>i1>>j1;
224 if(t==1)
225 fout<<dif_min(i1,j1);
226 else
227 fout<<mediana(i1,j1);
228
229 fout<<"\n";
230 }
231
232 fout.close();
233 fin.close();
234 return 0;
235 }
26.3 tg
Problema 3 - tg 100 de puncte
Fie un num r natural N . Spunem c a, b, c este un triplet geometric
Ó
limitat de N , dac a, b
³i c sunt trei numere naturale astfel încât 1 & a $ b $ c & N ³i b a c.
Cerinµe
S se determine num rul tripletelor geometrice limitate de num rul natural N .
Date de intrare
Fi³ierul de intrare tg.in conµine pe prima linie un num r natural N .
Date de ie³ire
În ³ierul de ie³ire tg.out se va scrie num rul tripletelor geometrice limitate de N .
Restricµii ³i preciz ri
a 4&N & 4 000 000
Exemple:
tg.in tg.out Explicaµii
8 2 Cele dou triplete sunt 1, 2, 4 ³i 2, 4, 8
Timp maxim de executare/test: 0.1 secunde
Memorie: total 32 MB din care pentru stiv 8 MB
Dimensiune maxim a sursei: 5 KB
CAPITOLUL 26. ONI 2014 530
Complexitate O N N
Pentru ecare a din mulµimea r1, 2, ..., N 2x ³i pentru ecare c din mulµimea a 2, a 3, ..., N
se veric dac a c este p trat perfect ³i în caz armativ se calculeaz b sqrt a c ³i se
contorizeaz rezultatul.
Complexitate O N sqrt N
Pentru ecare a din mulµimea 1, 2, ..., N 2 se observ c dac ar exista tripletul a, b, c atunci
ar trebui s avem c b b©a, deci b b ar trebui s e multiplu al lui a ³i în acela³i timp ar trebui
s e p trat perfect, iar b % a.
Ne-ar ajuta astfel s ³tim care este cel mai mic p trat perfect multiplu al lui a. Fie a1 acest
num r. Am avea a1 a x, unde x este cel mai mic posibil astfel incat a1 s e p trat perfect.
e e e f f f
Dac a p11 p22 ... pkk , atunci x p11 p22 ... pkk unde fi ei mod 2 , adic x este
produsul factorilor primi care apar la puteri impare în descompunerea lui a.
Se mai observ apoi c orice alt multiplu al lui a care este si p trat perfect va de forma
a2 a x k , unde k ' 1. Pentru k 1 se obtine a1 . Deoarece trebuie s avem b Õb % a a,
2
atunci patratele perfecte care ne intereseaz pentru obµinerea lui c se obµin pentru k % xa . Astfel
Ó Õ
a x k si c b b©a x k . Deoarece c & N vom avea k & N
2
putem determina b x
.
ÕCu alte cuvinte
Õ pentru ecare
Õ a din mulµimea r 1, 2, ..., N 2x vom parcurge k din mulµimea
r x 1 , x 2 , ..., x x ³i astfel vom obµine toate tripletele geometrice c utate, care sunt
a a a
Ó 2
de forma ( a, b a x k , c x k ).
Pentru determinarea lui x putem folosi algoritmul de descompunere în factori primi O sqrt a.
Complexitate O N
Ideea de rezolvare este asem natoare cu cea anterioar . Se incearc diminuarea efortului de
calculare la ecare pas a lui x prin construirea vectorului xi = cel mai mic numar natural care
înmulµit cu i produce un p trat perfect, adic vom avea i xi cel mai mic patrat perfect multiplu
al lui i.
Se procedeaz asem n tor cu algoritmul Ciurul lui Eratostene. Se iniµializeaz xi cu 0 ³i
se parcurge în ordinea 1, 2, 3, ..., N . Daca avem xi 0 atunci vom marca xi j j i pentru
toti 1 & i j j & N .
24
25 fin.close();
26 fout.close();
27 }
26
27 x=v[a];
28 k1=sqrt(a/x);
29 k2=sqrt(n/x);
30 s=s+k2-k1;
31 }
32
33 fout<<s<<endl;
34 fout.close();
35 fin.close();
36 return 0;
37 }
17 x=1;
18 t=a;
19 d=2;
20 while(d*d<=t)
21 {
22 c=0;
23 while(t%d==0)
24 {
25 c++;
26 t=t/d;
27 }
28 if(c%2==1) x=x*d;
29 d++;
30 }
31
32 if(t>1) x=x*t;
33 k1=sqrt(a/x);
34 k2=sqrt(n/x);
35 s=s+k2-k1;
36 }
37
38 fout<<s<<endl;
39 fout.close();
40 fin.close();
41 return 0;
42 }
26.4 progresie
Problema 4 - progresie 100 de puncte
Cerinµe
S se determine un ³ir strict Ócresc tor, cu lungimea N , format din numere naturale nenule,
1 & a1 $ a2 $ a3 $ ... $ aN & 2N N , cu proprietatea c oricare trei termeni distincµi ai ³irului nu
sunt în progresie aritmetic , adic pentru oricare numere naturale i, j ³i k cu 1 & i $ j $ k & N ,
este îndeplinit condiµia: ai ak j 2 aj . Prin x s-a notat partea întreag a lui x.
De Ó
exemplu, pentru N 5, cel mai mare termen al ³irului va trebui s e mai mic sau egal cu
2 5 5% adic aN & 22, deci o soluµie este: 1, 2, 4, 5, 10.
Date de intrare
Fi³ierul de intrare progresie.in conµine pe primul rând num rul natural N cu semnicaµia de
mai sus.
Date de ie³ire
În ³ierul de ie³ire progresie.out se vor scrie pe primul rând, desp rµite prin câte un spaµiu,
cele N elemente ale ³irului ai , 1 & i & N .
Restricµii ³i preciz ri
a 3 & N & 20 000
a Dac soluµia nu este unic , se va accepta orice soluµie corect .
Exemple:
progresie.in progresie.out Explicaµii
5 1 2 4 5 10 N 5; aN & 22;
Un ³ir strict cresc tor format din 5 numere naturale
nenule cu proprietatea c oricare 3 termeni ai s i nu
sunt în progresie aritmetic este: 1, 2, 4, 5, 10
7 3 5 6 11 12 14 15 N 7; aN & 37;
Un ³ir strict cresc tor format din 7 numere naturale
nenule cu proprietatea c oricare 3 termeni ai s i nu
sunt în progresie aritmetic este: 3, 5, 6, 11, 12, 14, 15
CAPITOLUL 26. ONI 2014 534
Varianta 1
Aceast soluµie utilizeaz un algoritm asem n tor cu algoritmul lui Eratostene de determinare
a numerelor prime. Se utilizeaz un vector care iniµial pe toate poziµiile este iniµializat cu 1 ³i apoi
începând cu a doua poziµie se elimin din acest ³ir toate poziµiile obµinute cu formula 2*poziµia
curent - i unde i ia toate valorile anterioare poziµiei curente. Se avanseaz apoi în ³ir pân la
prima valoare nenul . Soluµia are un ordin de complexitate O n log n ³i obµine aproximativ
30% din punctaj.
Varianta 2
Fie Tn mulµimea tuturor întregilor nenegativi a c ror scriere în baza 3 conµine cel mult n cifre,
toate ind diferite de cifra 2.
Num rul de elemente din Tn este 2n deoarece elementele lui Tn sunt n-uple formate din 0 ³i 1,
iar cel mai mare întreg din Tn este 111....11 = (3n - 1)/2. Tn nu va conµine trei numere distincte
în progresie aritmetic deoarece dac x, y, z " Tn 2y x z , num rul 2y conµine numai cifrele 0
³i 2 în reprezentarea sa în baza trei. Rezult c x y z , µinând seama de algoritmul de adunare
în baza trei, ceea ce contrazice ipoteza. Soluµia obµine aproximativ 50% din punctaj.
Varianta 3
Soluµia are la baz un mecanism constructiv, observând c din prima stare notat S1 r1, 2x
se poate trece în starea urm toare reunind elementele lui S1 cu elementele lui S1 adunate cu prima
putere a lui 3. Se obµine astfel S2 r1, 2, 4, 5x. Apoi se obµine S3 r1, 2, 4, 5, 10, 11, 13, 14x. Se
continu mecanismul atât timp cât valorile din starea curent sunt mai mici sau egale cu N . Se
poate demonstra prin inducµie matematic c acest algoritm conduce la mulµimi cu proprietatea
cerut de problem . Ordinul de complexitate al acestei soluµii este O n ³i obµine punctaj maxim.
Varianta 4 prof. Eugen Nodea - Colegiul Naµional Tudor Vladimirescu Tg. Jiu
Se poate construi un ³ir care respect cerinµele folosind relaµia de recurenµ :
a[2*i] = 3 * a[i] - 2
a[2*i+1] = 3 * a[i] - 1, i=0, ..., N, cu a[0] = 1
Complexitate : O N
Varianta 5 prof. Piµ-Rada Ionel-Vasile, Colegiu Naµional Traian Drobeta Turnu - Severin
Se construie³te ³irul v[1], v[2], ..., v[N-1], format din numere naturale nenule cu proprietatea
c
(*) oricare dou secvenµe adiacente din ³irul v[] au sume diferite, astfel:
- primii trei termeni sunt 1, 2, 1
- al patrulea termen nu poate 1, 2, 3, 4 deci va aleas valoarea 5, apoi pentru termenii
cinci, ³ase ³i ³apte se pot alege valorile 1, 2, 1 ³i se obµine ³irul cu ³apte termeni 1, 2, 1, 5, 1, 2, 1
- al optulea termen nu poate dintre 1, 2, 3, ...,13 ³i se va alege valoarea 14, apoi iara³i se pot
completa urm torii ³apte termeni egali cu primii ³apte termeni ³i se obtine un ³ir cu 15 termeni
1, 2, 1, 5, 1, 2, 1, 14, 1, 2, 1, 5, 1, 2, 1
p
- apare astfel ideea de a construi un ³ir care pe poziµiile i egale cu puteri ale lui doi, i 2 , s
aib valoarea egal cu suma termenilor anteriori plus 1,
v[i] = 1 +v[1] + v[2] + ... + v[i-1],
apoi urm torii i 1 termeni vor ale³i identici cu primii obµinându-se un ³ir cu 2 i 1 termeni
³i procesul va repetat.
irul cerut de problem se va obµine prin a[1]=1 ³i a[k+1]=a[k]+v[k], pentru 1 & k $ N .
Din ³irul 1, 2, 1, 5, 1, 2, 1, 14, 1, 2, 1, 5, 1, 2, 1 se va obµine ³irul 1, 2, 4, 5, 10, 11, 13, 14, 28,
29, 31, 32, 37, 38, 40, 41, ...
Algoritmul permite implementare cu complexitatea O N .
CAPITOLUL 26. ONI 2014 535
21
22 f>>n;
23
24 a[1]=1;a[2]=2;k=2;
25
26 i=1;
27 un=0;
28 p=3;
29 while (!un)
30 {
31 t=k;
32 for(j=1;j<=k;j++)
33 {
34 x=a[j]+p;
35 if (x<=3*n*sqrt(n)) a[++t]=x;
36 else un=1;
37
38 }
39
40 if (!un)
41 k=2*k;
42 else
43 k=t;
44 i++;
45 p=p*3;
46 }
47 // cout << t ;
48
49 for(i=1;i<=n;i++)
50 g<<a[i]<<" ";
51
52 g<<"\n";
53 f.close();
54 g.close();
55 return 0;
56 }
1 # include <cstdio>
2 # include <cmath>
3 using namespace std;
4
5 int N, K, i;
6 int a[100003];
7
8 int main()
9 {
10 freopen("progresie.in", "r", stdin);
11 freopen("progresie.out","w",stdout);
12
13 scanf("%d", &N);
14
15 a[0] = 1;
16 for (i=0; i<=N; ++i)
17 {
18 a[2*i] = 3 * a[i] - 2;
19 a[2*i+1] = 3 * a[i] - 1;
20 }
21
22 for (i=0; i<N; ++i)
23 printf("%d ", a[i]);
24
25 return 0;
26 }
1 #include <stdio.h>
2 #include <math.h>
3
4 #define NMax 10002
5
6 int N, Limit;
7 bool b[2 * NMax * NMax];
8 int sol[NMax];
9
10 bool bkt( int x, int val )
11 {
12 if ( x == N + 1 )
13 return true;
14
15 for ( int v = val; v <= Limit; ++ v )
16 if ( b[v]==false )
17 {
18 for ( int i = 1; i < x; ++ i)
19 b[ 2 * v - sol[i] ]=true;
20
21 sol[x] = v;
22
23 if ( bkt( x + 1, v + 1) )
24 return true;
25
26 for ( int i = 1; i < x; ++ i)
27 b[ 2 * v - sol[i] ]=false;
28 }
29
30 return false;
31 }
32
33 int main()
34 {
35 freopen("progresie.in", "r", stdin);
36 freopen("progresie.out", "w", stdout);
37
38 scanf("%d", &N);
39 Limit = 2 * N * sqrt(N);
40 if ( bkt( 1, 1 ) )
41 {
42 for ( int i = 1; i <= N; ++ i)
43 printf("%d ", sol[i]);
44
45 printf("\n");
46 }
47 else
48 return 0;
49 }
26.5 reex
Problema 5 - reex 100 de puncte
La un concurs de robotic , în timpul prezent rii, un roboµel cu corp cilindric cu diametrul de
o unitate scap de sub control ³i se deplaseaz într-un ring de form dreptunghiular . Ringul este
împ rµit în N M p trate identice, cu latura de o unitate, a³ezate pe N linii ³i M coloane.
Robotul poate p r si ringul numai pe la colµuri, acestea
ind numerotate de la 1 la 4, colµul cu num rul 1 ind cel din
stânga jos apoi restul ind numerotate în sens trigonometric.
Suprafaµa ringului este delimitat de exterior prin intermediul
a patru pereµi desp rµitori: doi pereµi verticali (a³ezaµi de
la colµul 1 la colµul 4, respectiv de la colµul 2 la colµul 3) ³i doi
pereµi orizontali (a³ezaµi de la colµul 1 la colµul 2, respectiv
de la colµul 3 la colµul 4), f r a bloca ie³irile, ca în desenul al turat.
CAPITOLUL 26. ONI 2014 539
Robotul p trunde în ring prin colµul cu num rul 1 sub un unghi de 45 grade ³i cu o vitez de
un p trat/s.
Ciocnirile cu pereµii sunt considerate perfect elastice (robotul nu-³i pierde din vitez ) iar un-
ghiul de incidenµ este egal cu cel de reexie.
Cerinµe
Se cere s se determine:
a) dup câte secunde ³i prin ce colµ al ringului va ie³i robotul;
b) de câte ori se ciocne³te robotul de pereµii orizontali ³i verticali, rezultând o schimbare de
direcµie, pân la ie³irea din ring.
Date de intrare
Fi³ierul de intrare reex.in conµine pe prima linie dou numere naturale N ³i M , separate
printr-un singur spaµiu.
Date de ie³ire
Fi³ierul de ie³ire reex.out va conµine pe prima linie dou numere naturale S ³i C , separate
printr-un singur spaµiu, S reprezentând num rul de secunde dup care robotul va ie³i din ring, iar
C reprezint num rul colµului prin care acesta va ie³i. Pe a doua linie, ³ierul de ie³ire va conµine
dou numere naturale H ³i V , separate printr-un spaµiu, H reprezentând num rul de ciocniri cu
pereµii orizontali ai ringului, iar V num rul de ciocniri cu pereµii verticali.
Restricµii ³i preciz ri
a 3 & N, M & 2 000 000 000
a Pentru rezolvarea corect a unei singure cerinµe se acord 50% din punctaj, iar pentru
rezolvarea corect a ambelor cerinµe se acord 100% din punctaj.
Exemple:
reex.in reex.out Explicaµii
36 11 4 4 1
Pân la ie³ire se parcurg 11 p trate,
ie³irea se produce pe la colµul 4. Se
produc 4 ciocniri cu pereµii orizontali
³i o ciocnire cu pereµii verticali.
57 13 4 2 1
Se parcurg 13 p trate, ie³irea se face
la colµul 4 ³i de produc 2 ciocniri cu
pereµii orizontali (în punctele a ³i c
respectiv o ciocnire cu pereµii verti-
cali în punctul b).
Soluµia 1 - 40 de puncte
Se simuleaz deplasarea robutului din p trat în p trat pe diagonal (x x 1 ³i y z 1),
se veric ciocnirea cu un petete orizontal (y 1 sau y N ) sau cu un perete vertical (x 1 sau
x M ). Se veric dac s-a ajuns într-un colµ astfel:
- Colµul 1 (stânga jos) cu x 1 ³i y 1;
- Colµul 2 (dreapta jos) cu x M ³i y 1;
CAPITOLUL 26. ONI 2014 540
În urma ec rei ciocniri se schimba direcµia de deplasare pe axa x sau y , în funcµie de peretele
ciocnit.
Pentru rezolvarea cerinµei 1) se num r p traµelele parcurse p na se ajunge într-un colµ, viteza
ind de un p trat/s, timpul în secunde coincide cu num rul de p trate parcurse.
În cazul unei ciocniri cu un perete se num r aceast ciocnire în funtie de perete (orizontal
sau vertical).
Soluµia 2 - 68 de puncte
Se simuleaz deplasarea robotului din perete în perete ³i se înâlnesc dou situaµii:
- se poate face un salt pe x ³i y cu min N, M (N -lungimea ³i M -l µimea ringului);
- se produce o ciocnire înainte de a parcurge o distanµ egal cu min N, M , situaµie în care
incrementarea se face f r dep ³irea lui N ³i M sau 1.
în acest caz timpul (nr. de p trate parcurse) se poate calcula mai simplu dup relaµia:
S V M 1, în care S - nr. de secunde, V - nr. de ciocniri cu pereµii verticali, M - lungimea
ringului.
Solutia 3 - 100 de puncte
Dac se analizeaz parcursul robotului desf ³urat (vezi imaginea de mai jos) ³i se noteaz
n N 1 ³i m M 1 se poate observa c num rul de ciocniri cu pereµii orizontali H , respectiv
num rul de ciocniri cu pereµii verticali V sunt daµi de relaµiile:
H N ©cmmdc N, M ³i V M ©cmmdc N, M în care cu cmmdc N, M s-a notat cel mai
mare divizor comun al lui N ³i M .
Nr. de p trate parcurse ³i implicit timpul în secunde se poate calcual ca S cmmmc N, M 1.
Colµul în care se produce ie³irea se poate determina din nr. de ciocniri cu pereµii orizontali ³i
verticali astfel:
- pt. num r impar de ciocniri cu pereµii orizontali se poate ie³i pe latura de sus adic colµurile
3 sau 4.
- pt. V par singura posibilitate de ie³ire este colµul 2 (pe latura de jos);
- pt. H impar ie³irea se va face pe latura din dreapta, colµurile 2 sau 3;
- pt. H par ie³irea se face pe latura sin stânga singura posibilitate ind colµul 4 .
Colµul exact se determin prin combinarea posibilit tilor rezultate în funtie de paritatea lui H
³i V .
11 {
12 f >> n >> m;
13 --n, --m;
14
15 //cmmdc
16 a = n;
17 b = m;
18 while(b)
19 {
20 r = a % b;
21 a = b; b = r;
22 }
23
24 //cmmmc
25 cmmmc = n * m / a;
26
27 v = n / a;
28 h = m / a;
29 c = 1;
30 if (v % 2 == 0)
31 c = 4;
32 else
33 if (h % 2 == 0)
34 c = 2;
35 else
36 c = 3;
37
38 g << cmmmc + 1 << " " << c << "\n";
39 g << h - 1 << " " << v - 1 << "\n";
40 return 0;
41 }
42 b.x+=dx;
43 b.y+=dy;
44 //cout << "B("<<b.y<<"."<<b.x<<")\n ";
45 if (b.x == m) {dx= -1; E++;} //lat E
46 if (b.y == n) {dy= -1; N++;} //lat N
47 if (b.x == 1) {dx = 1; W++;} //lat W
48 if (b.y == 1) {dy = 1; S++;} //lat S
49 if ((b.x==c1.x) && (b.y==c1.y)) {colt=1; S--; W--;}
50 if ((b.x==c2.x) && (b.y==c2.y)) {colt=2; S--; E--;}
51 if ((b.x==c3.x) && (b.y==c3.y)) {colt=3; N--; E--;}
52 if ((b.x==c4.x) && (b.y==c4.y)) {colt=4; N--; W--;}
53
54 } while (!colt);
55
56 outFile << x << " " << colt << "\n";
57 outFile << N + S << " " << E + W << "\n";
58
59 inFile.close();
60 outFile.close();
61 return 0;
62 }
52
53 outFile << s << " " << colt << "\n";
54 outFile << nh -1 << " " << nl -1 << "\n";
55
56 inFile.close();
57 outFile.close();
58 return 0;
59 }
65 b.x+=n-b.y;
66 else
67 b.x-=n-b.y;
68
69 b.y=n;
70 }
71 else
72 if (b.x+dx < 1)
73 {
74 if (dy > 0)
75 b.y+=b.x-1;
76 else
77 b.y-=b.x-1;
78
79 b.x=1;
80 }
81 else
82 if (b.y+dy < 1)
83 {
84 if (dx > 0)
85 b.x+=b.y-1;
86 else
87 b.x-=b.y-1;
88
89 b.y=1;
90 }
91 }
92
93 //cout << "B("<<b.y<<"."<<b.x<<")\n ";
94 //cin >> ch;
95 if (b.x == m) {dx= -dx; E++; s+=m-1;} //lat E
96 if (b.y == n) {dy= -dy; N++;} //lat N
97 if (b.x == 1) {dx = -dx; W++; s+=m-1;} //lat W
98 if (b.y == 1) {dy = -dy; S++;} //lat S
99 if ((b.x==c1.x) && (b.y==c1.y)) {colt=1; S--; W--;}
100 if ((b.x==c2.x) && (b.y==c2.y)) {colt=2; S--; E--;}
101 if ((b.x==c3.x) && (b.y==c3.y)) {colt=3; N--; E--;}
102 if ((b.x==c4.x) && (b.y==c4.y)) {colt=4; N--; W--;}
103 } while (!colt);
104
105 outFile << s << " " << colt << "\n";
106 outFile << N + S << " " << E +W << "\n";
107
108 inFile.close();
109 outFile.close();
110 return 0;
111 }
26 ofstream outFile;
27
28 // citire date din fis
29 inFile.open("reflex.in");
30 outFile.open("reflex.out");
31 inFile >> n >> m;
32
33 N=n-1;
34 M=m-1;
35 CMMDC=cmmdc(N,M);
36 // CMMMC = N * M / CMMDC;
37 nl=N/CMMDC;
38 nh=M/CMMDC;
39 if (nl%2==0)
40 colt=4;
41 else
42 if (nh%2==0)
43 colt=2;
44 else
45 colt=3;
46
47 s = nl;
48 s = s * M + 1;
49
50 outFile << s << " " << colt << "\n";
51 outFile << nh -1 << " " << nl -1 << "\n";
52
53 inFile.close();
54 outFile.close();
55 return 0;
56 }
42 if (nh%2==0)
43 colt=2;
44 else
45 colt=3;
46
47 s = nl;
48 s = s * M + 1;
49
50 outFile << s << " " << colt << "\n";
51 outFile << nh -1 << " " << nl -1 << "\n";
52
53 inFile.close();
54 outFile.close();
55 return 0;
56 }
26.6 traseu
Problema 6 - traseu 100 de puncte
într-un ora³ exist un hotel de form cubic , cu N etaje, nu-
merotate de la 1 la N . Suprafaµa ec rui etaj K (1 & K & N )
este p tratic ³i este împ rµit în N N camere identice al turate,
dispuse pe N linii ³i N coloane, ecare camer având drept eti-
chet un triplet de numere naturale KLC (K =etajul, L=linia,
C =coloana, 1 & L, C & N ), ca în imaginea al turat .
Dintre cele N N N camere ale hotelului, una este special
deoarece în ea locuie³te de mult timp un ³oricel. Fiind isteµ, el ³tie
eticheta camerei în care se a precum ³i eticheta camerei în care
buc tarul hotelului depoziteaz alimente.
Studiind hotelul, ³oricelul a constatat c pe ecare etaj, din orice camer poate intra în toate
camerele care au un perete comun cu aceasta (existând un mic oriciu pentru aerisire).
De asemenea, ³oricelul a constatat c din ecare camer (situat la etajele 2, 3,
..., sau N 1) poate intra în camera situat imediat deasupra ei ³i în camera situat
imediat sub ea.
Fiind un ³oricel binecrescut, el nu intr în nicio camer ocupat de clienµi ca s
nu-i deranjeze.
Hotelul având mulµi clienµi, ³oricelul trebuie s -³i g seasc cel mai scurt traseu de
la camera lui la camera cu alimente, traseu care s treac printr-un num r minim de
camere, toate neocupate.
Cerinµe
Se cere s se determine:
a) num rul de camere prin care trece cel mai scurt traseu al ³oricelului de la camera lui la
camera cu alimente (inclusiv camera lui ³i camera cu alimente);
b) etichetele camerelor prin care trece traseul determinat la punctul a).
Date de intrare
Fi³ierul traseu.in conµine:
a pe prima linie, dou numere naturale N ³i M separate printr-un spaµiu, N cu semnicaµia
din enunµ iar M reprezentând num rul de camere ocupate de clienµii hotelului;
a pe a doua linie, trei numere naturale K1 L1 C1, separate prin câte un spaµiu, reprezentând
eticheta camerei în care se a ³oricelul;
a pe a treia linie, trei numere naturale K2 L2 C2, separate prin câte un spaµiu, reprezentând
eticheta camerei în care sunt depozitate alimentele;
a pe ecare dintre urm toarele M linii, câte trei numere naturale X Y Z , separate prin câte
un spaµiu, reprezentând etichetele celor M camere ocupate de clienµi.
CAPITOLUL 26. ONI 2014 547
Date de ie³ire
Fi³ierul de ie³ire traseu.out va conµine pe prima linie un num r natural T reprezentând
num rul de camere prin care trece cel mai scurt traseu al ³oricelului de la camera lui la camera
cu alimente determinat la punctul a).
Pe ecare din urm toarele T linii, se vor scrie câte trei numere naturale X Y Z , separate prin
câte un spaµiu, reprezentând etichetele camerelor prin care trece traseul determinat la punctul
a), în ordinea în care sunt parcurse camerele de c tre ³oricel pentru a ajunge din camera lui în
camera cu alimente.
Restricµii ³i preciz ri
a 2 & N & 100; 1 & M & 5000 ³i M $ N N 2
a oricelul nu intr decât în camere neocupate de clienµi.
a Camera ³oricelului este o camer neocupat de clienµi.
a Dac exist mai multe trasee ale ³oricelului de la camera lui la camera de alimente care trec
prin exact T camere, atunci traseul a³at va cel mai mic traseu din punct de vedere lexicograc.
a Eticheta (X1 Y1 Z1 ) se consider strict mai mic în sens lexicograc ca eticheta (X2 Y2 Z2 )
dac este satisf cut doar una dintre condiµiile:
1) X1 $ X2 2) X1 X2 ³i Y1 $ Y2 3) X1 X2 ³i Y1 Y2 ³i Z 1 $ Z2
a Eticheta X1 Y1 Z1 se consider egal cu eticheta X2 Y2 Z2 dac X1 X2 ³i Y1 Y2 ³i
Z1 Z2 . Vom scrie egalitatea lor astfel: (X1 Y1 Z1 ) = (X2 Y2 Z2 ).
a Traseul ce trece (în aceast ordine) prin camerele cu etichetele (X1 Y1 Z1 ), (X2 Y2 Z2 ), ...,
(XT YT ZT ) este mai mic din punct de vedere lexicograc decât traseul (A1 B1 C1 ), (A2 B2 C2 ),
..., (AT BT CT ) dac exist un indice J (1 & J & T ) astfel încât (X1 Y1 Z1 ) = (A1 B1 C1 ), (X2
Y2 Z2 ) = (A2 B2 C2 ), ..., (XJ 1 YJ 1 ZJ 1 ) = (AJ 1 BJ 1 CJ 1 ) iar eticheta (XJ YJ ZJ ) este
strict mai mic decât eticheta (AJ BJ CJ ).
a Se acord : 40% din punctaj pentru determinarea corect a num rului T ³i 100% din punctaj
pentru rezolvarea corect a ambelor cerinµe.
a Se garanteaz c exist soluµie pentru ambele cerinµe, pentru toate datele de test.
Exemple:
traseu.in traseu.out Explicaµii
3 4 7 Hotelul are trei etaje (1,2 ³i 3). Pe ecare etaj sunt 3*3 camere.
1 1 1 1 1 1 ³oricelul se a în camera cu eticheta 1 1 1 iar camera cu alimente
3 3 3 1 1 2 are eticheta 3 3 3.
3 3 1 1 1 3 Sunt 4 camere ocupate de cli-
2 1 1 1 2 3 enµi. Acestea au etichetele : 3
3 1 1 1 3 3 3 1, 2 1 1, 3 1 1, 3 1 3.
3 1 3 2 3 3 Traseul cel mai scurt trece
3 3 3 prin T=7 camere.
Sunt mai multe astfel de tra-
see. De exemplu:
1) (1 1 1, 1 1 2, 1 1 3, 1 2 3,
1 3 3, 2 3 3, 3 3 3)
2) (1 1 1, 1 1 2, 1 1 3, 2 1 3, 2
2 3, 3 2 3, 3 3 3)
3) (1 1 1, 1 2 1, 1 3 1, 1 3 2, 2 3 2, 3 2 3, 3 3 3) etc.
Cel mai mic astfel de traseu (în sens lexicograc) este traseul 1).
Timp maxim de executare/test: 1.0 secunde
Memorie: total 16 MB din care pentru stiv 8 MB
Dimensiune maxim a sursei: 10 KB
- Poate accesibil oricare din cele 6 camere cu dac elemntul masivului corespunz tor eti-
chetei camerei este 0 sau este mai mare ca A[x][y][z]
- Vizit m ³i marc m ecare camer accesibil memorând valoarea A[x][y][z]+1 în elementul
corespunz tor etichetei camerei în masiv. Valoare memorat reprezentând num rul minim
de camere prin care trebuie s treac ³oricelul pentru a ajunge în camera cu eticheta curent ,
plecând din camera iniµial .
- Poziµiile camerelor care au fost vizitate le vom reµine într-o coad , în ordinea vizit rii lor.
- Primul elemnt din coad reµine poziµia (K1,L1,C1), memorat pe poziµia 1.
- Cât timp nu a fost vizitat camera cu alimente, vom vizita pentru poziµia curent p din
coad (x,y,z) cele maximum 6 camere accesibile. Vom ad uga la nalul cozii poziµiile ec rei
camere accesibile, în ordinea vizit rii. Trecem la poziµia p+1 din coad ³i acest procedeu.
- La nal, valoarea T=A[K2][L2][C2] reprezint num rul minim de camere prin care trece
taseul cel mai scurt al ³oricelului de la camera lui la camera cu alimente.
- Traseul se va reconstitui plecând de la camera cu alimente c tre camera ³oricelului. Se
viziteaz cele maximum 6 camere accesibile marcate cu T-1, în ordinea din desen, pentru
a obµine traseul cel mai mic în sens lexicograc. Dintre acestea se alege prima camer
marcat cu T-1. Apoi, pentru camera aleas se viziteaz camerele accesibile marcate cu T-2
în ordinea din imagine ³i din nou se alege prima dintre acestea, etc. Traseul a fost obµinut
dac s-a ajuns la camera ³oricelului marcat cu 1.
- Poziµiile acestor T camere alese se vor memora într-un vector ale c ror componente se vor
a³a în ordine invers .
3
Complexitate O N
88 if (a[x][y+1][z]==val-1)
89 ++y;
90 else
91 if (a[x+1][y][z]==val-1)
92 ++x;
93 --val;
94 c[val].x=x;
95 c[val].y=y;
96 c[val].z=z;
97 }
98 }
99
100 int main()
101 {
102 citeste();
103 bordare();
104 coada();
105
106 int val=a[k2][l2][c2];
107 g<<val<<endl;
108 c[val].x=k2;
109 c[val].y=l2;
110 c[val].z=c2;
111 drum(val);
112
113 for(int i=1;i<=val; i++)
114 g<<c[i].x<<’ ’<<c[i].y<<’ ’<<c[i].z<<endl;
115
116 g.close();
117 return 0;
118 }
42 void coada()
43 {
44 p=u=1;
45 c[1].x=k1;
46 c[1].y=l1;
47 c[1].z=c1;
48 a[k1][l1][c1]=1;
49 while((p<=u)&&(a[k2][l2][c2]==0))
50 {
51 x=c[p].x;
52 y=c[p].y;
53 z=c[p++].z;
54 for(i=0;i<6;i++)
55 {
56 xc=x+dx[i];
57 yc=y+dy[i];
58 zc=z+dz[i];
59 if (a[xc][yc][zc]==0)
60 {
61 u++;
62 a[xc][yc][zc]=a[x][y][z]+1;
63 c[u].x=xc;
64 c[u].y=yc;
65 c[u].z=zc;
66 }
67 }
68 }
69 }
70
71 void drum(short int x, short int y, short int z, int val)
72 {
73 if(val>1)
74 {
75 if (a[x-1][y][z]==val-1) drum(x-1,y,z,val-1);
76 else
77 if (a[x][y-1][z]==val-1) drum(x,y-1,z,val-1);
78 else
79 if (a[x][y][z-1]==val-1) drum(x,y,z-1,val-1);
80 else
81 if (a[x][y][z+1]==val-1) drum(x,y,z+1,val-1);
82 else
83 if (a[x][y+1][z]==val-1) drum(x,y+1,z,val-1);
84 else
85 if (a[x+1][y][z]==val-1) drum(x+1,y,z,val-1);
86
87 g<<x<<’ ’<<y<<’ ’<<z<<endl;
88 }
89 }
90
91 int main()
92 {
93 citeste();
94 bordare();
95 coada();
96
97 int val=a[k2][l2][c2];
98 g<<val<<endl;
99 g<<k1<<’ ’<<l1<<’ ’<<c1<<endl;
100 drum(k2,l2,c2,val);
101
102 //cout<<val;
103 g.close();
104 return 0;
105 }
9
10 struct cel
11 {
12 short k, l, c;
13 };
14
15 short dx[]={-1, 0, 1, 0, 0, 0};
16 short dy[]={ 0, 1, 0,-1, 0, 0};
17 short dz[]={ 0, 0, 0, 0, 1,-1};
18 bool a[102][102][102];
19 int M[102][102][102], T[102][102][102];
20 short n, m, k1, l1, c1, k2, l2, c2;
21
22 queue <cel> q;
23
24 void lee()
25 {
26 short k;
27 cel x, y;
28 x.k = k1; x.l = l1; x.c = c1;
29 M[x.k][x.l][x.c] = 1;
30 T[x.k][x.l][x.c] = -1;
31 q.push(x);
32
33 while(!q.empty())
34 {
35 x = q.front(); q.pop();
36 for (k=0; k<6; ++k)
37 {
38 y.k = x.k + dz[k];
39 y.l = x.l + dx[k];
40 y.c = x.c + dy[k];
41 if (a[y.k][y.l][y.c] == 0)
42 if (M[x.k][x.l][x.c] + 1 < M[y.k][y.l][y.c])
43 {
44 if (T[y.k][y.l][y.c] == 0)
45 T[y.k][y.l][y.c] = x.k*1000000 + x.l*1000 + x.c;
46 else
47 {
48 if(T[y.k][y.l][y.c] > x.k*1000000+x.l*1000+x.c)
49 T[y.k][y.l][y.c] = x.k*1000000+x.l*1000+x.c;
50 }
51
52 M[y.k][y.l][y.c] = M[x.k][x.l][x.c] + 1;
53 q.push(y);
54 }
55 else
56 if (M[x.k][x.l][x.c] + 1 == M[y.k][y.l][y.c])
57 {
58 if (T[y.k][y.l][y.c] > x.k*1000000 + x.l*1000 + x.c)
59 T[y.k][y.l][y.c] = x.k*1000000 + x.l*1000 + x.c;
60 }
61 }
62 }
63 }
64
65 void afis(short k, short l, short c)
66 {
67 short k2, l2, c2;
68 int x;
69 if (k == k1 && l == l1 && c == c1)
70 g << k << " " << l << " " << c << "\n";
71 else
72 {
73 x = T[k][l][c];
74 k2 = x / 1000000;
75 l2 = x / 1000 % 1000;
76 c2 = x % 1000;
77 afis(k2, l2, c2);
78 g << k << " " << l << " " << c << "\n";
79 }
80 }
81
82 int main()
83 {
84 short k, l, c;
CAPITOLUL 26. ONI 2014 553
85 f >> n >> m;
86 for (k=0; k<=n+1; ++k)
87 for (l=0; l<=n+1; ++l)
88 for (c=0; c<=n+1; ++c)
89 {
90 M[k][l][c] = inf;
91 if (k==0 || l==0 || c==0)
92 a[k][l][c] = 1;
93 if (k==n+1 || l==n+1 || c==n+1)
94 a[k][l][c] = 1;
95 }
96
97 f >> k1 >> l1 >> c1;
98 f >> k2 >> l2 >> c2;
99
100 while (m--)
101 {
102 f >> k >> l >> c;
103 a[k][l][c] = 1;
104 }
105
106 lee();
107
108 g << M[k2][l2][c2] << "\n";
109 afis(k2, l2, c2);
110 return 0;
111 }
46 L=l+dl[j];
47 C=c+dc[j];
48 if(1<=K && K<=N && 1<=L && L<=N &&
49 1<=C && C<=N && A[K][L][C]==0)
50 {
51 A[K][L][C]=j + (1 + A[k][l][c] / 10) * 10;
52 tl++;
53 tail[tl].K=K;
54 tail[tl].L=L;
55 tail[tl].C=C;
56 tlen++;
57 if(K==K2 && L==L2 && C==C2)break;
58 }
59 }
60
61 tf++;
62 tlen--;
63 }
64
65 T=A[K2][L2][C2]/10;
66 K=K2;
67 L=L2;
68 C=C2;
69
70 for(i=T;i>=1;i--)
71 {
72 tail[i].K=K;
73 tail[i].L=L;
74 tail[i].C=C;
75 j=A[K][L][C]%10;
76 j=5-j;
77 K=K+dk[j];
78 L=L+dl[j];
79 C=C+dc[j];
80 }
81
82 fout<<T<<"\n";
83 for (i=1;i<=T;i++)
84 {
85 fout<<(int)tail[i].K<<" "<<(int)tail[i].L<<" "<<(int)tail[i].C<<"\n";
86 }
87
88 fout.close();
89 fin.close();
90 return 0;
91 }
ONI 2013
27.1 aranjare
Problema 1 - aranjare 100 de puncte
Toat lumea ³tie c Mirel are 2 N sticluµe cu parfum a³ezate pe un raft cu 2 N poziµii,
numerotate de la 1 la 2 N . El are N sticluµe cu parfum cump rate din µar ³i alte N sticluµe cu
parfum cump rate din Franµa.
Sticluµele cump rate din µar sunt etichetate cu r1 , r2 , r3 , ..., rN , iar sticluµele cump rate din
Franµa sunt etichetate cu f1 , f2 , f3 , ..., fN . Fiecare sticluµ are asociat valoarea cu care a fost
cump rat .
Iniµial, Mirel are a³ezate pe primele N poziµii sticluµele cump rate din µar sortate cres-
c tor dup valoare, iar pe urm toarele N poziµii sticluµele cump rate din Franµa sortate tot
cresc tor dup valoare. Astfel, cele 2 N sticluµe cu parfum sunt a³ezate în felul urm tor:
r1 , r2 , r3 , ..., rN , f1 , f2 , f3 , ..., fN . Mai exact, sticluµa ri se a pe poziµia i, iar sticluµa fi se a
pe poziµia N i, pentru i din intervalul 1, N .
Prietenul s u cel mai bun, Marian, s-a gândit s -i fac o surprinz ³i s -i schimbe aranjarea
sticluµelor cu parfum în urm toarea ordine: r1 , f1 , r2 , f2 , r3 , f3 , ..., rN , fN . Cum Marian are dou
mâini, el poate face numai urm torul tip de operaµie: ia dou sticluµe cu parfum de pe raft (de
pe dou poziµii diferite) ³i le interschimb .
Cerinµe
Dându-se num rul N , ³i 2 N valori reprezentând valoarea ec rei sticluµe cu parfum, ajutaµi-l
pe Marian s fac operaµiile necesare pentru a schimba ordinea sticluµelor cu parfum în ordinea
precizat în enunµ.
Date de intrare
Fi³ierul de intrare aranjare.in conµine pe prima linie num rul N , iar pe urm toarea linie 2 N
numere naturale, separate prin câte un spaµiu. Primele N numere reprezint valorile sticluµelor
cump rate din µar , iar urm toarele N numere reprezint valorile sticluµelor cump rate din Franµa.
Atât primele N , cât ³i ultimele N numere sunt sortate cresc tor în funcµie de valoare.
Date de ie³ire
Fi³ierul de ie³ire aranjare.out va conµine mai multe linii. Pe ecare linie se vor aa dou
numere diferite x ³i y din intervalul 1, 2 N , semnicând faptul c Marian trebuie s interschimbe
sticluµa de pe poziµia x cu sticluµa de pe poziµia y .
Restricµii ³i preciz ri
a 2 & N & 100 000
a Dac exist mai multe soluµii, se poate a³a oricare dintre ele.
a Soluµia nu trebuie s fac neap rat num rul minim de operaµii.
a Pentru 15% din teste se garanteaz c N & 13.
a Pentru alte 25% din teste se garanteaz c N & 300.
a Pentru alte 30% din teste se garanteaz c N & 1000.
555
CAPITOLUL 27. ONI 2013 556
Exemple:
aranjare.in aranjare.out Explicaµii
3 24 În explicaµia de mai jos, ecare sticluµ are numele etichetei
135235 35 urmat de valoarea ei în parantez .
34 irul iniµial este: r1 1r2 3r3 5f1 2f2 3f3 5
Dup prima mutare devine: r1 1f1 2r3 5r2 3f2 3f3 5
Dup a doua mutare devine: r1 1f1 2f2 3r2 3r3 5f3 5
Dup ultima mutare devine: r1 1f1 2r2 3f2 3r3 5f3 5
Timp maxim de executare/test: 0.5 secunde
Memorie: total 16 MB din care pentru stiv 8 MB
Dimensiune maxim a sursei: 5 KB
pentru i de la 1 la 2 N
` dac pe poziµia i nu avem sticluµa care trebuie:
t facem swap între i ³i pozitia pe care se a sticluµa ce trebuie a³ezat pe poziµia i
La ecare pas aducem pe poziµia corect cel puµin o sticluµ , deci rezult c sunt necesare cel
mult 2 N astfel de mut ri pentru a duce conguraµia iniµial la conguraµia nal .
Complexitate: O N
27 if (v[2*i]!=n+i)
28 {
29 v[p[n+i]]=v[2*i];
30 p[v[2*i]]=p[n+i];
31 fout<<2*i<<" "<<p[n+i]<<"\n";
32 }
33
34 if (v[2*i+1]!=i+1)
35 {
36 v[p[i+1]]=v[2*i+1];
37 p[v[2*i+1]]=p[i+1];
38 fout<<2*i+1<<" "<<p[i+1]<<"\n";
39 }
40 }
41
42 return 0;
43 }
27.2 gradina
Problema 2 - gradina 100 de puncte
P cal a reu³it s duc la bun sfâr³it în elegerea cu boierul c ruia-i fusese slug ³i, conform
învoielii, boierul trebuie s -l r spl teasc dându-i o parte din livada sa cu pomi fructiferi. Boierul
este un om foarte ordonat, a³a c livada sa este un p trat cu latura de N metri unde, pe vremuri,
fuseser plantate N rânduri cu câte N pomi ecare. Orice pom fructifer putea identicat
cunoscând num rul rândului pe care se a ³i poziµia sa în cadrul rândului respectiv. Cu timpul,
unii pomi s-au uscat ³i acum mai sunt doar P pomi. P cal trebuie s -³i delimiteze în livad o
gr din p trat cu latura de K metri.
Cerinµe
Cunoscând dimensiunile livezii ³i gr dinii, num rul pomilor din livad ³i poziµia ec ruia,
determinaµi num rul maxim de pomi dintr-o gr din p trat de latur K ³i num rul modurilor
în care poate amplasat gr dina cu num rul maxim de pomi.
Date de intrare
Fi³ierul gradina.in conµine:
- pe prima linie numerele naturale N , P ³i K , separate prin câte un spaµiu, cu semnicaµia din
enunµ;
- pe urm toarele P linii câte 2 numere naturale Lin ³i Col, separate printr-un spaµiu, repre-
zentând num rul rândului, respectiv poziµia în rând a ec rui pom din livad .
Date de ie³ire
Fi³ierul gradina.out va conµine:
- pe prima linie num rul maxim de pomi fructiferi dintr-o gr din p trat cu latura de K
metri;
- pe a doua linie num rul de posibilit µi de a amplasa gr dina astfel încât s conµin num rul
maxim de pomi determinat.
Restricµii ³i preciz ri
a 2 & N & 1000
1&P &N
2
a
a 1&K&N
Exemple:
CAPITOLUL 27. ONI 2013 558
Pentru a putea determina gr dina cu num r maxim de pomi vom calcula un tablou bidimen-
sional S cu sume parµiale:
S ij = suma elementelor din subtabloul care are colµul stânga-sus de coordonate (1,1) ³i
colµul dreapta-jos de coordonate i, j , adic num rul pomilor din aceast zon ;
Bazându-ne pe tabloul S , pentru ecare poziµie i, j , determin m num rul pomilor din sub-
tabloul care are colµul stânga-sus de coordonate i k 1, j k 1 ³i colµul dreapta-jos de
coordonate i, j , dup formula:
20 }
21
22 fclose(fin);
23 }
24
25 void solve ()
26 {
27 for(int i=1;i<=n;++i)
28 for(int j=1;j<=n;++j)
29 a[i][j]+=a[i][j-1]+a[i-1][j]-a[i-1][j-1];
30
31 for(int i=k;i<=n;++i)
32 for(int j=k;j<=n;++j)
33 {
34 int np = a[i][j]-a[i-k][j]-a[i][j-k]+a[i-k][j-k];
35 if (np>pmax)
36 {
37 pmax=np;
38 nsol=1;
39 }
40 else
41 if (np==pmax)
42 ++nsol;
43 }
44 }
45
46 int main ()
47 {
48 read ();
49 solve ();
50
51 FILE *fout = fopen("gradina.out","wt");
52 fprintf(fout,"%d\n%d\n",pmax,nsol);
53 fclose(fout);
54 return 0;
55 }
27.3 split
Problema 3 - split 100 de puncte
Fie un ³ir a1 , a2 , ..., aN de numere naturale. Se împarte ³irul în patru secvenµe astfel încât
orice element din ³ir s aparµin unei singure secvenµe ³i ecare secvenµ s conµin cel puµin
dou elemente. Mai exact, se identic trei indici i $ j $ k astfel încât prima secvenµ este
format din elementele a1 , a2 , ..., ai , a doua din elementele ai1 , ai2 , ..., aj , a treia din elementele
aj 1 , aj 2 , ..., ak ³i ultima din elementele ak1 , ak2 , ..., an . Pentru ecare secvenµ se determin
costul ei ca ind diferenµa dintre valoarea maxim ³i cea minim din acea secvenµ .
Cerinµe
S se determine o împ rµire a ³irului în patru secvenµe astfel încât suma costurilor celor patru
secvenµe s e maxim .
Date de intrare
Fi³ierul split.in conµine pe prima linie num rul natural N . Pe linia a doua se g sesc N numere
naturale, separate prin câte un spaµiu, reprezentând elementele ³irului a.
Date de ie³ire
Fi³ierul split.out conµine pe prima linie un singur num r natural reprezentând suma maxim
a costurilor celor patru secvenµe. Pe linia a doua se a trei numere naturale i, j ³i k , separate
prin câte un spaµiu, cu semnicaµia din enunµ.
Restricµii ³i preciz ri
CAPITOLUL 27. ONI 2013 560
Exemple:
split.in split.out Explicaµii
11 29 Cele 4 secvenµe sunt:
9 7 3 0 2 1 8 6 0 11 4 479 9 7 3 0 (cost 9 - 0 = 9)
2 1 8 (cost 8 - 1 = 7)
6 0 (cost 6 - 0 = 6)
11 4 (cost 11 - 4 = 7)
O alt soluµie care obµine tot suma maxim 29 este 5 7
9, dar nu are i minim.
Timp maxim de executare/test: 1.0 secunde
Memorie: total 16 MB din care pentru stiv 8 MB
Dimensiune maxim a sursei: 5 KB
Se construiesc mai întâi liniar vectorii maxst, minst, maxdr, mindr, de lungime N :
minsti = valoarea minim din secvenµa a1..i
maxsti = valoarea maxim din secvenµa a1..i
mindri = valoarea minim din secvenµa ai..N
maxdri = valoarea minim din secvenµa ai..N
Pentru ecare j (4 & j & n 4):
avom c uta poziµia i plecând de la j spre stânga ³i determinând la ecare pas minimul ³i
maximul din intervalul i..j (aceste dou valori aparµin secvenµei a doua). Evident, prima secvenµ
are costul dat de maxsti 1 minsti 1.
a vom c uta poziµia k plecând de la j 1 dpre dreapta ³i determinând la ecare pas minimul
³i maximul din intervalul j 1..k (aceste dou valori aparµin secvenµei a treia). Evident, ultima
secvenµ are costul dat de maxdrk 1 mindrk 1.
a calculeaz costul celor 4 secvenµe ³i actualizeaz costul maxim al celor 4 secvenµe
2
Complexitatea total este O N .
93 }
94 else
95 {
96 maxim = a[j+2];
97 minim = a[j+1];
98 }
99
100 soldr = maxim - minim + maxdr[j+3] - mindr[j+3];
101 dk = j + 2;
102 for (k = j + 3; k <= n - 2; k++)
103 {
104 if (a[k] > maxim) maxim = a[k];
105 if (a[k] < minim) minim = a[k];
106 x = maxim - minim + maxdr[k+1] - mindr[k+1];
107 if (soldr < x)
108 {
109 soldr = x;
110 dk = k;
111 }
112 }
113
114 x = solst + soldr;
115 if (x > solmax)
116 {
117 solmax = x;
118 xi = di;
119 xj = j;
120 xk = dk;
121 }
122 }
123
124 ofstream fout(outFile);
125 fout << solmax << "\n";
126 fout << xi << " " << xj << " " << xk << "\n";
127 fout.close();
128
129 return 0;
130 }
27.4 momente
Problema 4 - momente 100 de puncte
G are un ceas digital care a³eaz ora printr-o valoare între 0 ³i 23 sub forma unui num r de
una sau dou cifre, minutul printr-o valoare între 0 ³i 59 sub forma unui num r de exact dou cifre
(prima cifr este 0 dac num rul de minute care trebuie a³at este mai mic decât 10) ³i secunda
printr-o valoare între 0 ³i 59 sub forma unui num r de exact doua cifre (dac num rul de secunde
care trebuie a³at este mai mic decât 10, atunci prima cifr este 0). Aceste informaµii apar în
ordinea: num rul de ore, num rul de minute, num rul de secunde ³i sunt separate prin câte un
spaµiu. Exemple: 23 39 17 (pentru ora 23, 39 minute ³i 17 secunde) , 1 00 01 (pentru ora 1, 0
minute ³i o secund ) sau 0 02 02 (pentru ora 0, 2 minute ³i 2 secunde).
G observ c dac al tur aceste trei valori poate construi un num r natural. Asfel, pentru
exemplele de mai sus obµine numerele 233917, 10001 ³i respectiv 202 (Atenµie! Num rul rezultat
nu începe cu 0 - eventualele cifre nule aate la începutul lui sunt eliminate!). G mai observ c
exist momente de timp, când num rul astfel format este un palindrom, cum este cazul celui de-al
doilea ³i celui de-al treilea exemplu. G denume³te aceste momente de timp momente palindromice
³i dore³te s ae câte astfel de momente sunt într-un interval de timp dat.
Un interval de timp este situat pe parcursul anului 2013 ind precizat prin data ³i ora exact
când începe ³i data ³i ora exact când se termin . Data este precizat prin doua numere care
reprezint luna ³i ziua, iar ora exact sub forma a³at de ceasul digital al lui G.
Cerinµe
Determinaµi câte momente palidromice au loc în k intervale de timp date.
CAPITOLUL 27. ONI 2013 563
Date de intrare
Fi³ierul de intrare momente.in conµine pe prima linie num rul natural k cu semnicaµia din
enunµ. Pe ecare dintre urm toarele k linii se a câte 10 valori naturale separate prin câte un
spaµiu. Primele cinci numere reprezint luna, ziua, ora, minutul ³i secunda când începe intervalul
de timp dat. Urm toarele cinci numere reprezint luna, ziua, ora, minutul ³i secunda când se
termin intervalul de timp dat.
Date de ie³ire
Fi³ierul de ie³ire momente.out va conµine k linii. Pe linia i (1 & i & k ) se va aa un singur
num r care va reprezenta num rul de momente palindromice din intervalul i.
Restricµii ³i preciz ri
a k & 100 000
a data de început precede data de sfâr³it pentru ecare interval de timp;
a în anul 2013 luna februarie are 28 zile;
a pentru 50% dintre teste vom avea k 1;
a se nume³te palindrom un num r care citit de la stânga la dreapta sau de la dreapta la stânga
are aceea³i valoare.
a dac intervalul de timp considerat începe sau se termin cu un moment palindromic, acesta
este num rat.
Exemple:
momente.in momente.out Explicaµii
1 24 Fi³ierul de intrare conµine un singur interval de timp, intre
2 28 23 44 32 28 februarie ora 23, 44 minute ³i 32 secunde ³i 1 martie
3 1 0 02 02 ora 0, 2 minute ³i 2 secunde.
In acest interval de timp sunt 24 momente palindomice
dupa cum urmeaza:
- în data de 28 februarie la orele 23 44 32 ³i 23 55 32;
- în data de 1 martie la orele 0 00 00, 0 00 01, 0 00 02, 0
Timp maxim de executare/test: 1.2 secunde
Memorie: total 16 MB din care pentru stiv 8 MB
Dimensiune maxim a sursei: 5 KB
Ideea de plecare in rezolvarea problemei este sa determinam cate palindromuri sunt intr-o zi
intreaga (de la ora 0 la 23:59:59). Putem determina acest numar prin simulare directa, adica
testand daca ecare moment din acest interval este sau nu palindrom. Astfel determinam ca sunt
699 palindromuri într-o zi.
Obtinerea raspunsului pentru un singur interval necesit s determin m:
1 câte zile întregi sunt în intervalul dat (aceasta putem s o facem prin diverse metode -
chiar printr-o metod brut );
- un tabou precalculat în care reµinem momentele de timp care sunt palindromice ³i aplic m o
c utare binar în acest tablou => complexitate O k log 700 pentru întrega soluµie (100
de puncte);
- metoda brut : determinarea numerelor a³ate de ceas din secund în secund ³i num rarea
celor care sunt palindromice (obµinând cel mult 50 puncte)
Soluµiile bazate pe simularea brut (parcurgerea ec rui interval din secund în secund ) obµin
cel mult 20 puncte.
59
60
61 begin
62
63 mom[0] := 1;
64
65 precalc;
66
67 assign(fo,’momente.out’);
68 assign(fi,’momente.in’);
69 rewrite(fo);
70 reset(fi);
71 readln(fi,k);
72
73 for i := 1 to k do
74
75 begin
76
77 ct3 := 0; ct2 := 0; ct1 := 0; ctz := 0;
78
79
80 read(fi,luna1,zi1,ora1,min1,sec1);
81 read(fi,luna2,zi2,ora2,min2,sec2);
82
83
84 if ora1+min1+sec1=0 then
85 ctz:=1;
86
87 luna := luna1;
88 zi := zi1;
89 while not ((zi=zi2) and (luna=luna2)) do
90 begin
91 inc(zi);
92 if zifin[luna]+1=zi then
93 begin
94 zi := 1;
95 inc(luna)
96 end;
97 inc(ctz);
98 end;
99 dec(ctz);
100
101
102 ct2 := 699*ctz; //zile complete*699 /zi
103
104 nr := ora1*3600 + min1*60 + sec1;
105
106 if nr>0 then
107 ct1 := 699 - mom[nr-1]
108 else
109 ct1 := 0;
110
111 nr := ora2*3600 + min2*60 + sec2;
112
113 ct3 := mom[nr];
114
115 writeln(fo,ct1+ct2+ct3);
116
117 end;
118
119 close(fo);
120 end.
27.5 secvente
Problema 5 - secvente 100 de puncte
Consider m ³irul de numere naturale nenule distincte a1 , a2 , ..., aN . Not m cu Li lungimea
maxim a unei secvenµe de elemente cu valori consecutive care se poate obµine prin ordonarea
CAPITOLUL 27. ONI 2013 566
cresc toare a primelor i elemente din ³irul dat. De exemplu, pentru ³irul 7, 2, 3, 8, 20, 4, 10, 9
avem:
L1 1, L2 1, L3 2, L4 2, L5 2, L6 3, L7 3, L8 4.
Cerinµe
S se determine L1 , L2 , ..., LN .
Date de intrare
Fi³ierul secvente.in conµine pe prima linie num rul natural N . Pe ecare din urm toarele N
linii se g se³te câte un num r natural, deci pe linia i 1 se va aa elementul ai , pentru i 1...N .
Date de ie³ire
Fi³ierul secvente.out conµine exact N linii. Pe linia i (i 1...N ) se va a³a valoarea Li .
Restricµii ³i preciz ri
a 3 & N & 200 000 a 1 & ai & 1 000 000, pentru orice i 1...N a Pentru 35% din teste se
garanteaz c N & 1000
Exemple:
secvente.in secvente.out Explicaµii
8 1 L 1. ³irul : 7. Lungime maxim 1
7 1 L2. ³irul: 7,3. Lungime maxim 1
3 2 L 3. ³irul: 7,3,2. ³irul sortat este 2,3,7. Lungimea maxim este
2 2 2 (dat de secvenµa 2,3)
8 2 L 4. ³irul: 7,3,2,8. Lungime maxim 2 (dat de 2,3)
20 3 L5. ³irul: 7,3,2,8,20. Lungime maxim 2 (dat de 2,3).
4 3 L 6. ³irul: 7,3,2,8,20,4. ³irul sortat este 2,3,4,7,8,20. Lungimea
10 4 maxim este 3 (dat de secvenµa 2,3,4).
9 L 7. ³irul: 7,3,2,8,20,4,10. Lungime maxim 3 (dat de 2,3,4).
L 8. ³irul: 7, 3, 2, 8, 20, 4, 10, 9.
³irul sortat este 2,3,4,7,8,9,10,20. Lungimea maxim este 4 (dat
de secvenµa 7,8,9,10).
Timp maxim de executare/test: 0.2 secunde
Memorie: total 16 MB din care pentru stiv 8 MB
Dimensiune maxim a sursei: 5 KB
Soluµie 35 pct
O prim idee ar s avem un vector de vizite pentru a ³ti la ecare pas dac un element se
a în secvenµa curent (care începe pe poziµia 1). Un algoritm de rezolvare este urm torul:
` vz v i = true;
` crt = num rul de valori de 1 consecutive în vectorul vz în jurul poziµiei v i
` dac crt % best
t best crt
` scrie best
CAPITOLUL 27. ONI 2013 567
Complexitate: O(N*N)
Soluµie 100 pct
Pornind de la ideea anterioar , putem renunµa la vz ³i s -l înlocuim cu pos, unde posx este:
Pentru valorile x care aparµin unei secvenµe de valori consecutive dar nu se a pe marginile
secvenµei, se observ c posx este irelevant.
Noul algoritm de rezolvare este:
best = 0
pentru ecare i de la 1 la N
` begin v i, poziµia unde începe secvenµa singurului element v i
` end v i, poziµia unde se termin secvenµa singurului element v i
` dac posv i 1! 0, adic elementul v i 1 se a deja într-o secvenµ
t begin posv i 1, actualiz m începutul secvenµei în care se a elementul v i
` dac posv i 1! 0, adic elementul v i 1 se a deja într-o secvenµ
t end posv i 1, actualiz m sfâr³itul secvenµei în care se a elementul v i
` deci elementul v i se a în interiorul secvenµei begin, end. Cum poziµiile de început
³i de sfâr³it al elementelor din interiorul intervalului sunt irelevante, actualiz m pos
doar pentru elementele din cap t:
t posbegin end
t posend begin
` dac end begin 1 % best:
t best end begin 1
` scrie best
27.6 spider
Problema 6 - spider 100 de puncte
Omul p ianjen (Spiderman) sare de pe o cl dire pe alta, aat în imediata vecin tate, în nord,
est, sud sau vest. Cl dirile din cartierul omului p ianjen au o în lµime exprimat în numere
naturale ³i sunt a³ezate pe m rânduri, câte n pe ecare rând.
Spiderman va alege s sar pe una dintre cl dirile vecine, care are în lµimea mai mic sau egal ,
iar diferenµa de în lµime este minim . Dac exist mai multe cl diri vecine de aceea³i în lµime,
omul p ianjen aplic ordinea preferenµial nord, est, sud, vest, dar nu sare înc o dat pe o cl dire
pe care a mai s rit. Scopul omului p ianjen este acela de a reu³i s fac un num r maxim de
s rituri succesive.
Cerinµe
Scrieµi un program care determin num rul maxim de s rituri succesive, pe care îl poate
efectua, pornind de la oricare dintre cl diri, precum ³i poziµiile cl dirilor care formeaz drumul
maxim.
Date de intrare
Fi³ierul spider.in conµine, pe prima linie, dou numere naturale, m ³i n, desp rµite printr-un
spaµiu. Fiecare dintre urm toarele m rânduri conµine n numere naturale, separate prin câte un
spaµiu, reprezentând în lµimile cl dirilor.
CAPITOLUL 27. ONI 2013 569
Date de ie³ire
Fi³ierul de ie³ire spider.out va conµine, pe prima linie, un singur num r natural k , repre-
zentând num rul maxim de s rituri. Urm toarele k linii vor conµine câte dou numere naturale,
separate printr-un spaµiu, reprezentând coordonatele cl dirilor care formeaz drumul maxim, în
ordinea parcurgerii. Dac exist mai multe soluµii, în ³ierul de ie³ire se va scrie drumul care
porne³te de la poziµia i, j cu i minim, iar dac exist mai multe soluµii cu acela³i i minim, se va
scrie în ³ier soluµia cu i ³i j de valoare minim .
Restricµii ³i preciz ri
a 0 $ m, n & 1000
a în lµimile cl dirilor sunt numere naturale din intervalul [1,10000000]
a în orice zon p tratic de 2x2 cl diri vecine exist cel mult 2 cl diri de aceea³i în lµime.
Exemple:
spider.in spider.out Explicaµii
55 8 Spiderman porne³te de pe blocul de 90 de metri aat în
35 3842 40 50 54 poziµia (5, 4), face 8 s rituri ³i ajunge în poziµia (1, 4), de
34 3830 75 50 53 unde nu mai are posibilit µi de a s ri.
70 7888 86 30 43
39 9088 23 25 33
35 8089 90 34 34
24
25
15
14
Timp maxim de executare/test: 3.0 secunde
Memorie: total 64 MB din care pentru stiv 8 MB
Dimensiune maxim a sursei: 5 KB
Soluµie 35 pct
Se denesc dou matrice: A si B cu maxim 1 000 de rânduri ³i maxim 1 000 de coloane,
precum ³i dou tablouri, v ³i w, având cel mult 1 000 000 de elemente. în matricea A se citesc
valorile în lµimilor cl dirilor (numere naturale din intervalul [1, 10 000 000]. Se construie³te câte
unui drum, pornind de la toate elementele matricei A, ³i se reµine drumul de lungime maxim .
Se utilizeaz o funcµie care prime³te, prin intermediul parametrului pas, num rul de ordine al
drumului care se construie³te. Funcµia întoarce în lµimea cl dirii cu diferenµa de în lµime minim ,
³i care respect condiµiile din enunµ. Funcµia veric în matricea B dac cl direa de coordonate
i, j a mai fost - sau nu - vizitat de Spiderman: dac B ij pas, atunci cl direa de coordonate
i, j a fost deja vizitat pe parcursul drumului cu num rul de ordine pas, deci cl direa nu este
eligibil . Dac B ij este diferit de pas, atunci se alege cl direa respectiv ³i lui B ij i se
atribuie valoarea pas.
Se utilizeaz un subprogram care prime³te, prin parametrii de intrare r ³i c, coordonatele unei
cl diri ³i construie³te drumul care poate parcurs pornind de la aceea cl dire. Pentru selectarea
unei cl diri se utilizeaz funcµia descris mai sus. Dac drumul cu num rul de ordine actual
este mai lung decât precedentul drum, se va reµine lungimea drumului în variabila k , precum ³i
elementele vectorului de direcµii v în vectorul w, care va avea lungimea k ³i va reµine direcµiile
corespunz toare drumului maxim. Elementele vectorului v se denesc astfel:
v i 1, dac direcµia aleas pentru s ritura i este Nord;
v i 2, dac direcµia aleas pentru s ritura i este Est;
v i 3, dac direcµia aleas pentru s ritura i este Sud;
v i 4, dac direcµia aleas pentru s ritura i este Vest.
Programul principal va apela acest subprogram pentru toate elementele matricei A, pornind
de la elementul de coordonate 1, 1, parcurgând matricea de la linia 1 la linia m, ³i elementele
CAPITOLUL 27. ONI 2013 570
pe linii, de la 1 la n. Datele unui drum se vor reµine doar dac lungimea sa este strict mai mare
decât cea mai mare lungime obµinut pân în acel moment. La scrierea datelor în ³ierul de ie³ire
(k ³i cooronatele cl dirilor care formeaz drumul maxim) se va porni de la coordonatele primei
cl diri, iar coordonatele cl dirilor care formeaz drumul maxim se vor determina prin interpretarea
corect a elementelor vectorului w.
Complexitate: O N N M M
Soluµie 100 pct
Pornind de la soluµia anterioar , observ m c , dac nu am avea dou valori identice pe poziµii
al turate, nu are sens s calcul m din ecare poziµie de început care este lungimea maxim ,
deoarece putem stoca într-o matrice auxiliar bestij lungimea maxim a unei secvenµe care
începe pe poziµia i, j , iar atunci când determin m un drum s actualiz m toate aceste costuri
ale poziµiilor prin care trece.
Cum putem avea dou valori vecine cu aceea³i valoare, acest tablou best trebuie schimbat puµin
în bestxy d având semnicaµia: lungimea maxim a unei secvenµe care începe pe poziµia x, y
care nu face prima s ritur în direcµia d (d poate avea valori de la 0 la 3, ecare valoare semnicând
una din cele 4 direcµii posibile).
Complexitate: O N M
123 }
124 }
125
126 }
127
128 void write()
129 {
130
131 printf("%d\n", steps - 1);
132
133 point prv = outside;
134
135 while(sol != outside)
136 {
137 printf("%d %d\n", sol.first, sol.second);
138 point aux = getNextPosition(sol, prv).first;
139
140 prv = sol;
141 sol = aux;
142 }
143 }
144
145 int main()
146 {
147 freopen(infile, "r", stdin);
148 freopen(outfile, "w", stdout);
149
150 read();
151 solve();
152 write();
153
154 fclose(stdin);
155 fclose(stdout);
156 return 0;
157 }
ONI 2012
28.1 7segmente
Problema 1 - 7segmente 100 de puncte
Un indicator cu 7 segmente este un dispozitiv de a³aj electronic destinat
a³ rii unei cifre zecimale. Aceste dispozitive sunt utilizate pe scar larg în
ceasuri digitale, contoare electronice ³i alte aparate, pentru a³area informaµiilor
numerice. Cele 7 segmente au fost notate cu literele a, b, c, d, e, f, g, dup
modelul din gura al turat . A³area uneia din cifrele de la 1 la 9 const în
aprinderea anumitor segmente din cele 7, dup cum urmeaz :
Cifr 1 2 3 4 5 6 7 8 9
Segmente b, c a, b, a, b, c, b, c, f, a, c, d, a, c, d, a, b, c a, b, c, a, b, c,
aprinse d, e, g d, g g f, g e, f, g d, e, f, g d, f, g
Proiectarea diverselor sisteme de a³aj trebuie s µin cont ³i de puterea necesar pentru
a³area unei cifre. Pentru aprinderea unui segment este necesar o putere de 1 mW. Astfel, în
funcµie de cifra a³at , dispozitivul necesit o putere egal cu num rul de segmente aprinse la
a³area cifrei respective. Puterea necesar pentru a³area unui num r natural este egal cu suma
puterilor necesare a³ rii ec reia dintre cifrele sale.
Cerinµe
S se scrie un program care cite³te dou numere naturale nenule n ³i p, (num rul n având
toate cifrele nenule) ³i calculeaz :
a num rul natural k reprezentând puterea necesar pentru a³area num rului n;
a cel mai mare num r natural t, format numai din cifre nenule, mai mic sau egal decât n, care
necesit pentru a³are o putere de cel mult p mW .
Date de intrare
Prima linie a ³ierului de intrare 7segmente.in conµine dou numere naturale nenule n ³i p
(num rul n având toate cifrele nenule), desp rµite printr-un spaµiu, cu semnicaµia de mai sus.
Date de ie³ire
Fi³ierul de ie³ire 7segmente.out va conµine pe o singur linie, cele dou numere naturale
nenule k ³i t (num rul t având toate cifrele nenule), separate printr-un spaµiu, cu semnicaµia de
mai sus.
Restricµii ³i preciz ri
1 & n $ 10 ;
19
a
a 2 & p & 150;
a pentru rezolvarea primei cerinµe se va acorda 20% din punctaj, iar pentru rezolvarea celei
de-a doua cerinµe se va acorda 80% din punctaj.
Exemple:
573
CAPITOLUL 28. ONI 2012 574
7segmente.in 7segmente.outExplicaµii
7654 12 18 7511 Num rul n este 7654; puterea necesar pentru a³are este
3+6+5+4=18 mW, iar cel mai mare num r, mai mic sau egal cu
7654, format numai din cifre nenule, care necesit pentru a³are
o putere de cel mult 12 mW, este 7511.
Timp maxim de executare/test: 0.1 secunde
Memorie: total 2 MB din care pentru stiv 2 MB
Dimensiune maxim a sursei: 5 KB
Num rul de dispozitive de tip 7 segmente necesare pentru a³area num rului n este egal cu
num rul de cifre al lui n. Puterea necesar pentru a³area num rului n se calculeaz ca suma
puterilor necesare pentru a³area ec rei cifre în parte, în funcµie de num rul de segmente utilizat
la a³area ec rei cifrei, conform tabelului.
În vederea determin rii num rului t se calculeaz pentru început num rul de cifre pe care-l
poate avea acesta. Având în vedere c cifra ce consum cea mai mic putere este 1 (2 mW) ³i nu
sunt utilizate cifre de 0, determin m num rul de cifre al lui t ca ind min(num rul de cifre al lui
n, p/2).
Separ m cifrele lui n într-un vector ³i iniµializ m un alt vector, care are num rul de poziµii
egal cu num rul de cifre al lui t, cu 1. Din puterea dat sc dem puterea utilizat pentru cifrele
de 1 ³i apoi cât timp mai este putere de utilizat (putere disponibil ) ³i cifre de aat, determin m
secvenµial cifrele lui t.
Se porne³te de la vectorul care are pe toate poziµiile cifra 1 ³i se actualizeaz poziµiile acestuia
de la stânga la dreapta (de la cifra cea mai semnicativ c tre cifra cea mai puµin semnicativ ) cu
cifra ce µine cont de datele problemei pân când puterea disponibil devine nul sau se completeaz
num rul de cifre.
Pentru determinarea unei cifre se µine cont c aceasta trebuie s e cifra cea mai mare, mai
mic sau egal cu cifra de pe aceea³i poziµie a lui n ³i a c rei utilizare nu epuizeaz puterea
disponibil . La ecare selectare a unei astfel de cifre se reactualizeaz puterea r mas neutilizat .
O capcan care trebuie evitat este situaµia în care o cifr determinat pe o anumit poziµie
este strict mai mic decât cifra de pe aceea³i poziµie a lui n, situaµie în care la determinarea
urm toarelor cifre ale lui t nu trebuie s mai µinem cont de faptul c acestea trebuie s e mai
mici decât cifrele lui n de pe poziµiile corespunz toare.
22
23 prest=p;
24 ok=0;
25 ok2=1;
26 for (i=0;i<w;i++)
27 {
28 for (j=(s[i]-’0’)*ok2+9*(1-ok2);j>0;j--)
29 if (x[j]+(w-i-1)*2<=prest)
30 break;
31
32 if (j>0)
33 {
34 ok=1;
35 printf("%d",j);
36 }
37 if (j==0 && ok==1)
38 printf("%d",j);
39 if (j<s[i]-’0’)
40 ok2=0;
41 prest-=x[j];
42 }
43
44 fclose(stdin);
45 fclose(stdout);
46 return 0;
47 }
47 }
48
49 n=n/10;
50 }
51
52 v[0]=i;
53 g<<pc<<" ";
54
55 // oglindesc cifrele
56 for(i=1;i<=v[0]/2;i++)
57 {
58 aux=v[i];
59 v[i]=v[v[0]+1-i];
60 v[v[0]+1-i]=aux;
61 }
62
63 // calculez numarul de cifre(nc) maxim pe care-l poate avea t
64 nc=p/2;
65 if (nc>=v[0]) nc=v[0];
66
67 // setez toate cifrele la 1
68 for(i=1;i<=nc;i++)
69 t[i]=1;
70
71 // din puterea data scad puterea utilizata pentru cifrele de 1
72 p=p-2*nc;
73
74 t[0]=nc;cc=1;
75 egalcif=1;
76 while (p>0&&cc<=t[0])
77 {
78 dmin=10;cifra=1;dmax=0;
79
80 // caut cifra corespunzatoare
81 for(i=2;i<=9;i++)
82 {
83 if (t[0]==v[0]&&egalcif==1)
84 if (i<=v[cc]&&abs(i-v[cc])<=dmin&&p-pw[i]+pw[1]>=0)
85 {
86 cifra=i;
87 dmin=abs(i-v[cc]);
88 }
89
90 if (t[0]<v[0]||egalcif==0)
91 if (i>=dmax&&p-pw[i]+pw[1]>=0)
92 {
93 cifra=i;
94 dmax=i;
95 }
96 }
97
98 // daca am setat o cifra mai mica, restul cifrelor pot fi mai mari
99 if (v[cc]-cifra!=0)
100 egalcif=0;
101
102 // asez cifra pe pozitia corecta si recalculez puterea
103 p+=pw[1];
104 p-=pw[cifra];
105 t[cc++]=cifra;
106 }
107
108 for(i=1;i<=t[0];i++)
109 g<<t[i];
110
111 g<<"\n";
112
113 f.close();
114 g.close();
115 return 0;
116 }
3 #include <cstdio>
4
5 using namespace std;
6
7 static const int NMAX = 20;
8
9 int N, P;
10 int x[] = { 0, 2, 5, 5, 4, 5, 6, 3, 7, 6 };
11 int v[NMAX];
12
13 int cer1;
14 int rez[NMAX], nrCifre;
15
16 int main(int argc, char **argv)
17 {
18 freopen("7segmente.in", "r", stdin);
19 freopen("7segmente.out", "w", stdout);
20
21 char c = ’1’;
22 while (1)
23 {
24 scanf("%c", &c);
25 if (c == ’ ’)
26 break;
27 v[N++] = c - ’0’;
28 }
29 scanf("%d", &P);
30
31 //cerinta 1
32 for (int i = 0; i < N; cer1 += x[v[i++]]);
33 printf("%d ", cer1);
34
35 //cerinta 2
36 nrCifre = (P / 2) < N ? (P / 2) : N;
37
38 if (nrCifre < N)
39 {
40 printf("%c", P & 1 ? ’7’ : ’1’);
41 for (int i = 0; i < nrCifre - 1; printf("1"), ++i)
42 ;
43 return 0;
44 }
45
46 P -= N << 1;
47 bool miss = false;
48 int i;
49 for (i = 0; i < N; ++i)
50 {
51 P += 2;
52 int j = miss ? 9 : v[i];
53 while (x[j] > P)
54 --j;
55
56 rez[i] = j;
57 P -= x[j];
58
59 if (rez[i] != v[i])
60 miss = true;
61 }
62
63 for (int i = 0; i < N; ++i)
64 printf("%d", rez[i]);
65 printf("\n");
66
67 return 0;
68 }
28.2 copaci
Problema 2 - copaci 100 de puncte
Se consider n copaci de diferite în lµimi, aaµi în linie dreapt la distanµe egale, numerotaµi
de la 1 la n. Pentru ecare copac se cunoa³te în lµimea sa Hi . Cum ³i copacii simt nevoia s
socializeze, ecare dintre ei are prieteni printre ceilalµi copaci.
Prietenii oric rui copac i se pot aa atât la stânga, cât ³i la dreapta sa. Relaµiile de prietenie
sunt denite în felul urm tor: pentru ecare copac i consider m un ³ir d1 , d2 , ..., dx reprezentând
prietenii copacului i situaµi în dreapta sa ³i un ³ir s1 , s2 , ..., sy reprezentând prietenii copacului
i situaµi în stânga acestuia. Copacii din cele dou ³iruri corespunz toare unui copac i formeaz
împreun lista prietenilor acestuia.
irurile corespunz toare copacului i se denesc astfel:
1. a d1 i 1 (dac i n, atunci copacul i nu are niciun prieten la dreapta sa, ³irul d r mânând
vid);
a pentru ecare k ' 2, dk este cel mai mic indice (1 & dk & n) cu proprietatea c dk % dk1
³i Hdk % Hdk1 . Dac dk nu exist , atunci lista de prieteni la dreapta ai copacului i s-a
încheiat ³i construirea ³irului se opre³te la acest pas.
2. a s1 i 1 (daca i 1, atunci copacul i nu are niciun prieten la stânga sa, sirul s r mânând
vid);
a pentru ecare k ' 2, sk este cel mai mare indice (1 & sk & n) cu proprietatea c sk $ sk1
³i Hsk % Hsk1 . Dac sk nu exist , atunci lista de prieteni la stânga ai copacului i s-a
încheiat ³i construirea ³irului se opre³te la acest pas.
De exemplu, în gura de mai jos sunt reprezentaµi 7 copaci, ecare având precizat sub el
valoarea în lµimii sale. Primul copac din stânga are indicele 1, iar ultimul are indicele 7.
Copacul 1 este prieten cu copacul 2 ind vecini, cu
copacul 5 (deoarece copacul 5 este primul din dreapta
lui 2 cu în lµimea mai mare strict decât în lµimea lui
2). La dreapta copacului 5 nu exista niciun copac cu
în lµimea mai mare strict decât a sa, deci singurii prieteni
ai copacului 1 sunt 2 ³i 5.
Pentru copacul 3, prietenii la stânga sa sunt copacii 2 ³i 1, iar cei de la dreapta sa sunt copacii
4 ³i 5. Pentru copacul 6, singurul prieten la stânga este copacul 5, iar la dreapta copacul 7.
Copacul 7 poate avea prieteni doar la stânga, ace³tia sunt 6 ³i 5 (la stânga copacului 5 nu mai
exist niciun copac cu în lµimea mai mare strict decât 8).
Gr dinarul Marian vrea s aleag 3 copaci diferiµi dintre cei n pentru a-i planta în alt gr din .
El dore³te ca dintre cei 3 copaci, oricum ar alege A si B , 2 dintre ei, atunci A este prieten cu B ³i
B este prieten cu A (relaµiile de prietenie se consider cele stabilite iniµial). Marian are mai multe
opµiuni ³i se întreab în câte moduri distincte poate alege cei 3 copaci cu proprietatea cerut .
Cerinµe
Determinaµi în câte moduri se pot alege 3 copaci diferiµi dintre cei n cu proprietatea c , oricum
am alege 2 copaci dintre cei 3, e ace³tia copacul A ³i copacul B , atunci A este prieten cu B ³i B
este prieten cu A.
Date de intrare
Fi³ierul de intrare copaci.in conµine pe prima linie un num r natural n, reprezentând num rul
de copaci, iar pe a doua linie n numere naturale nenule, separate prin câte un spaµiu, reprezentând
în lµimile copacilor.
Date de ie³ire
Fi³ierul de ie³ire copaci.out va conµine pe prima linie un num r natural reprezentând num rul
de moduri în care Marian poate alege 3 copaci cu proprietatea din enunµ.
Restricµii ³i preciz ri
CAPITOLUL 28. ONI 2012 579
Exemple:
copaci.in copaci.out Explicaµii
7 4 Copacul 1 este prieten cu copacii: 2, 5
6423858 Copacul 2 este prieten cu copacii: 1, 3, 4, 5
Copacul 3 este prieten cu copacii: 1, 2, 4, 5
Copacul 4 este prieten cu copacii: 1, 2, 3, 5
Copacul 5 este prieten cu copacii: 1, 2, 4, 6, 7
Copacul 6 este prieten cu copacii: 5, 7
Copacul 7 este prieten cu copacii: 5, 6
Modurile in care Marian poate alege cei 3 copaci sunt:
(1, 2, 5), (2, 4, 5), (2, 3, 4), (5, 6, 7).
Timp maxim de executare/test: 0.7 secunde
Memorie: total 16 MB din care pentru stiv 4 MB
Dimensiune maxim a sursei: 10 KB
Se observ c dac am avea un triunghi (A, B, C) cu A < B < C, atunci copacul B trebuie s
aib în lµimea minim dintre cei 3 copaci.
O alt observaµie este c dac x m copacul B ca ind de în lµime minim dintre cei 3 copaci,
atunci exist cel mult un triunghi centrat in B.
Astfel trebuie s iter m de la 1 la N ³i x m copacul B, iar A ³i C le stabilim ca ind primii
copaci din stânga, respectiv din dreapta copacului B, cu proprietatea c au în lµimile mai mari sau
egale cu în lµimea copacului B. Acesta este un posibil triunghi, îns trebuie s veric m concret
dac A ³i C sunt prieteni reciproci. Pentru aceasta folosim 2 vectori ST i ³i DRi care semnic
pân unde în stânga, respectiv în dreapta, copacul i are în lµimea maxim . Vectorii se pot calcula
în O N Hmax sau, mai ecient, cu o stiv în complexitate O N . Ambele metode intr în
timp.
Complexitate nal : O N Hmax sau O N .
21 k=j+1;
22 while (k<=n && h[j]>h[k])k++;
23 if (i>0 && k<=n &&
24 h[i]>h[j] &&
25 h[j]<h[k]) // trebuie sa avem h[i]!=h[j] si h[j]!=h[k],
26 // putem avea insa h[i]==h[k]
27 nr++;
28 }
29
30 printf("%d",nr);
31 fclose(stdout);
32 fclose(stdin);
33 return 0;
34 }
28.3 intersecµii
Problema 3 - intersecµii 100 de puncte
Dreptunghiul ABCD are laturile de lungimi w ³i h, numere naturale pare. Acest dreptunghi
este desenat pe o foaie de matematic ³i este descompus în w h p trate de latur 1.
Vârfurile A, B , C ³i D sunt plasate în colµurile unor p trate
de latur 1. Se alege un punct P din interiorul dreptunghiului
ABCD, situat în colµul unui p trat de latur 1 ³i se une³te prin seg-
mente de dreapt cu cele patru colµuri ale dreptunghiului. Unele
segmente intersecteaz p trate de latur 1 în exact dou puncte
distincte, altele într-un singur punct.
Numim p trat 2-intersectat, un p trat de latur 1 intersectat
de un segment în exact 2 puncte distincte. în dreptunghiul din gura al turat , segmentul P A
trece prin 3 p trate 2-intersectate, segmentul P B trece prin 9 p trate 2-intersectate, segmentul
P C trece prin 13 p trate 2-intersectate, iar segmentul P D prin 7.
Cerinµe
Se dau dou numere naturale w ³i h reprezentând lungimile laturilor dreptunghiului ABCD,
un num r natural n ³i n numere naturale x1 , x2 , ..., xn . Punctul P se plaseaz , pe rând, în toate
punctele interioare dreptunghiului ABCD care sunt colµuri ale unor p trate de latur 1. Pentru
ecare valoare xi (1 & i & n), determinaµi num rul de segmente distincte care trec prin exact
xi p trate 2-intersectate.
Date de intrare
Fi³ierul de intrare intersectii.in conµine pe prima linie trei numere naturale w, h (reprezen-
tând dimensiunile dreptunghiului) ³i n. Urm toarele n linii conµin câte un num r natural xi cu
semnicaµia de mai sus.
Date de ie³ire
Fi³ierul de ie³ire intersectii.out va conµine n linii. Pe ecare linie i va scris num rul de
segmente care trec prin exact xi p trate 2-intersectate, obµinute dup plasarea punctului P în
ecare colµ al unui p trat de latur 1 din interiorul dreptunghiului ABCD.
Restricµii ³i preciz ri
a 2 & w, h & 2 000 numere naturale pare;
a 2 & n & 100 000;
a punctul P se alege doar în interiorul dreptunghiului;
a pentru 40% din teste 2 & w, n, h & 500.
Exemple:
CAPITOLUL 28. ONI 2012 583
Se observ c dimensiunile dreptunghiului sunt numere pare, dar, nu putem restrânge analiza
problemei la un sfert din dimensiunea dreptunghiului iniµial decât dac studiem unele cazuri
particulare.
Nu are importanµ cum alegem colµul x, deci putem studia doar cazul colµului A iar la
nal vom multiplica rezultatul cu patru. Putem considera c vârful A, este originea unui sistem
cartezian de coordonate.
Pentru a calcula num rul de intersecµii al unui segment P A, se observ c pentru un punct
P de coordonate x ³i y prime intre ele, din acest dreptunghi, avem intersectate exact x y 1
p trate de latura 1, iar daca x ³i y nu sunt prime între ele, atunci dac d cmmdc x, y , num rul
de intersecµii al segmentului P A va in acest caz x y d.
Pentru a reduce complexitatea algoritmului, putem face o optimizare a calculului valorii cmmdc
pentru toate posibilit µile de alegere ale coordonatelor punctului P realizând o variant 2D a
ciurului lui Eratostene. Vom folosi un vector de vizitare a coordonatelor ³i pentru un punct P xy
nevizitat, cu cmmdc x, y 1, marc m ca vizitate punctele din dreptunghi de coordonate d x
³i d y nevizitate ca având un num r de intersecµii dat de valoarea d x y 1. Astfel voi
contoriza toate valorile distincte de intersecµii, având astfel posibilitatea de a r spunde la ecare
test în timp 1.
Deci complexitatea algoritmului devine O h w n. .
30 x=W-i;
31 y=H-j;
32 while (y){r=x%y; x=y; y=r;}
33 s[W-i+H-j-x]+=4;
34 }
35
36 if (W%2==0)
37 for (j=1;j<=H12;j++)
38 {
39 x=W2;
40 y=j;
41 while (y){r=x%y; x=y; y=r;}
42 s[W2+j-x]+=4;
43
44 x=W2;
45 y=H-j;
46 while (y){r=x%y ;x=y; y=r;}
47 s[W2+H-j-x]+=4;
48 }
49
50 if (H%2==0)
51 for (i=1;i<=W12;i++)
52 {
53 x=i;
54 y=H2;
55 while (y){r=x%y; x=y; y=r;}
56 s[i+H2-x]+=4;
57
58 x=W-i;
59 y=H2;
60 while (y){r=x%y; x=y; y=r;}
61 s[W-i+H2-x]+=4;
62 }
63
64 if (W%2==0 && H%2==0)
65 {
66 x=W2;
67 y=H2;
68 while (y){r=x%y; x=y; y=r;}
69 s[W2+H2-x]+=4;;
70 }
71
72 for (i=1;i<=Q;i++)
73 {
74 scanf("%d",&k);
75 printf("%d\n",s[k]);
76 }
77
78 fclose(stdout);
79 fclose(stdin);
80 return 0;
81 }
21 }
22 }
23
24 for (i=1;i<=Q;i++)
25 {
26 scanf("%d",&k);
27 printf("%d\n",4*s[k]);
28 }
29
30 fclose(stdout);
31 fclose(stdin);
32 return 0;
33 }
5
6 int H,W,NT,i,j,n,I,J,N,c[4110],poz;
7
8 bitset<2110> v[2110];
9
10 int main()
11 {
12 freopen("intersectii.in","r",stdin);
13 freopen("intersectii.out","w",stdout);
14 scanf("%d%d%d",&W,&H,&NT);
15
16 for(i=1;i<W;i++)
17 for(j=1;j<H;j++)
18 if(!v[i][j])
19 {
20 n=i+j-1;
21 for(I=i,J=j,N=n;I<W && J<H;I+=i,J+=j,N+=n)
22 {
23 v[I][J]=1;
24 c[N]++;
25 if(poz<N) poz=N;
26 }
27 }
28
29 //for(i=1;i<=poz;++i) c[i]+=c[i-1];
30 for(;NT;NT--)
31 {
32 scanf("%d",&i);
33 if(i>poz)
34 printf("0\n");
35 else
36 printf("%d\n",4*c[i]);
37 }
38
39 return 0;
40 }
28.4 palindrom
Problema 4 - palindrom 100 de puncte
Cu mult timp în urm , într-un t râm foarte, foarte îndep rtat, a existat o µar numit Tna-
map. Locuitorii acestei µ ri puteau s aplice instantaneu transform ri asupra cifrelor unui num r,
utilizând un tablou de corespondenµe T.
O cifr c a unui num r poate înlocuit cu
cifra corespunz toare ei, T c.
Dalv ³i Sogard, doi indivizi speciali ai acestei societ µi ciudate se aau în drum spre INO când
au con³tientizat c pot transforma instantaneu, folosind num r minim de transform ri de cifre,
orice num r N într-un palindrom divizibil cu un num r natural K . Dac sunt mai multe astfel
de numere, îl determin pe cel mai mare.
Voi puteµi?
CAPITOLUL 28. ONI 2012 588
Cerinµe
Cunoscând valorile T0 , T1 , ..., T9 , num rul ce urmeaz a transformat N ³i num rul K
(divizorul palindromului), determinaµi:
1. Num rul maxim care se poate obµine aplicând transform ri succesive num rului N dat.
2. Cel mai mare dintre palindromurile divizibile cu K , ce se pot obµine din num rul N ,
efectuând un num r minim de transform ri asupra cifrelor num rului dat, respectiv asupra cifrelor
numerelor obµinute pe parcurs.
Date de intrare
Pe prima linie a ³ierului palindrom.in sunt memorate 10 cifre distincte, separate prin câte
un spaµiu, reprezentând valorile T0 , T1 , ..., T9 .
Pe a doua linie sunt memorate cifrele num rului N , iar pe cea de a treia linie un num rul
natural K .
Date de ie³ire
Fi³ierul palindrom.out va conµine pe prima linie num rul maxim care se poate obµine aplicând
transform ri succesive num rului N , iar pe a doua linie palindromul divizibil cu K , de valoare
maxim , ce se poate obµine din num rul N , efectuând un num r minim de transform ri asupra
cifrelor.
Restricµii ³i preciz ri
1 & N $ 10
1.000.000
a ;
a N are un num r par de cifre;
a 2 & K & 20;
a se garanteaz faptul c toate testele au soluµie;
a pentru rezolvarea primei cerinµe se va acorda 20% din punctaj, iar pentru rezolvarea celei
de-a doua cerinµe se va acorda 80% din punctaj.
Exemple:
palindrom.in palindrom.out Explicaµii
0465127893 4994
1234 4224 1234 4234 4634 4734 4834 4934 4954
3 4924 4964 4974 4984 4994
Num rul N trece prin urm toarele st ri înainte de a de-
veni palindrom cu valoarea maxim , divizibil cu 3: 1234
4234 4254 4224.
Timp maxim de executare/test: 0.4 secunde
Memorie: total 256 MB din care pentru stiv 64 MB
Dimensiune maxim a sursei: 10 KB
Pentru al doilea subpunct vom folosi o recurenµ începând de la jum tatea ³irului spre început,
Dij = num rul minim de aplic ri pentru care ³irul cuprins intre poziµiile i ³i N i 1 este
palindrom ³i d restul j la împ rµirea prin K . Dac pe poziµiile i, N i 1 punem cifra q , atunci
restul obµinut la pasul anterior S devine S q 10 N i 10 i 1%K . Astfel se deduce
relaµia de recurenµ :
45
46 t[0] = 1;
47 for(int i = 1; i <= n; ++i)
48 {
49 t[i] = (t[i-1] * 10) % k;
50 s[i] -= ’0’;
51 }
52
53 for(int i = 0; i < sigma; ++i)
54 {
55 for(int j = 0; j < sigma; ++j)
56 co[i][j] = inf;
57
58 int crt = i, cost = 0;
59 while(cost < co[i][crt])
60 {
61 co[i][crt] = cost++;
62 crt = p[crt];
63 }
64 }
65
66 for(int i = 1; i < k; ++i)
67 dp[(n>>1) + 1][i] = inf;
68 }
69
70 void solve()
71 {
72 for(int i = (n>>1); i >= 1; --i)
73 {
74 int first = i;
75 int last = n - i + 1;
76
77 for(int j = 0; j < k; ++j)
78 {
79 dp[i][j] = inf;
80
81 for(int d = sigma - 1; d >= 0 + (i == 1); --d)
82 {
83 int cost = co[s[first]][d] + co[s[last]][d];
84 int div = (d * t[n - first] + d * t[n - last]) % k;
85 int prvDiv = (j - div + k) % k;
86
87 if(cost >= inf || dp[i-1][prvDiv] >= inf)
88 continue;
89
90 cost += dp[i+1][prvDiv];
91 if(cost < dp[i][j])
92 {
93 dp[i][j] = cost;
94 chr[i][j] = d;
95 prv[i][j] = prvDiv;
96 }
97 }
98
99 //if(dp[i][j] != inf) printf("%d %d = %d\n", i, j, dp[i][j]);
100 }
101 }
102 }
103
104 void write()
105 {
106 printf("%d\n", dp[1][0]);
107 int last = 0;
108 for(int i = 1; i <= (n>>1); ++i)
109 {
110 sol[i] = sol[n - i + 1] = chr[i][last] + ’0’;
111 last = prv[i][last];
112 }
113
114 printf("%s\n", sol + 1);
115 }
116
117 int main()
118 {
119 freopen(infile, "r", stdin);
120 freopen(outfile, "w", stdout);
CAPITOLUL 28. ONI 2012 591
121
122 read();
123 init();
124 solve();
125 write();
126
127 fclose(stdin);
128 fclose(stdout);
129 return 0;
130 }
139 {
140 if (rez[i][restTarget] < partial[l][1])
141 {
142 costMin[k][restTarget] = costMin[1 - k][j]
143 + partial[l][0];
144 rez[i][restTarget] = partial[l][1];
145 back[i][restTarget] = j;
146 }
147 }
148 else
149 if (compar[j][restTarget] == 1)
150 {
151 costMin[k][restTarget] = costMin[1 - k][j]
152 + partial[l][0];
153 rez[i][restTarget] = partial[l][1];
154 back[i][restTarget] = j;
155 }
156 }
157 }
158 }
159
160 for (int j = 0; j < K; ++j)
161 printf("%d : %d %d %d\n", j,costMin[k][j],rez[i][j],back[i][j]);
162
163 //refac comparatiile
164 for (int j = 0; j < K; ++j)
165 for (int l = 0; l < K; ++l)
166 if (compar[j][l] == 0)
167 if (rez[i][j] > rez[i][l])
168 compar[j][l] = 1;
169 else if (rez[i][j] < rez[i][l])
170 compar[j][l] = -1;
171 }
172
173 int poz = 0;
174 int i = N / 2 - 1;
175 while (i >= 0)
176 {
177 rezFinal[cnt++] = rez[i][poz];
178 poz = back[i][poz];
179 --i;
180 }
181
182 for (int i = N / 2 - 1; i >= 0; --i)
183 printf("%d", rezFinal[i]);
184 for (int i = 0; i < N / 2; ++i)
185 printf("%d", rezFinal[i]);
186 printf("\n");
187 printf("%d\n", costMin[k][0]);
188 }
189
190 int main(int argc, char *argv)
191 {
192 citire();
193
194 preprocesareCosturiTranzitie();
195
196 cerintaA();
197 //cerintaB();
198
199 return 0;
200 }
11 #define maxcifre 10
12 #define inf 99999999
13 #define pii pair<int, int>
14 #define pb push_back
15 #define mkp make_pair
16
17 int N, K;
18 char A[maxn], sol[maxn];
19 int perm[maxcifre], put[maxn];
20 int ajunge[maxcifre][maxcifre];
21 int D[maxn][maxk];
22
23 void preproc_puteri()
24 {
25 int i;
26
27 put[0] = 1;
28 for(i=1; i<=N; i++)
29 put[i] = (put[i-1] * 10) % K;
30 }
31
32 void preproc_ajunge()
33 {
34 int i, j, p;
35
36 for(i=0; i<maxcifre; i++)
37 for(j=0; j<maxcifre; j++)
38 ajunge[i][j] = -1;
39
40 for(i=0; i<maxcifre; i++)
41 {
42 ajunge[i][i] = 0;
43 p = i;
44 for(j=1; j<=100; j++)
45 {
46 p = perm[p];
47 if(p == i) break;
48 ajunge[i][p] = j;
49 }
50 }
51 }
52
53 int main()
54 {
55 FILE *f1=fopen("palindrom.in", "r"), *f2=fopen("palindrom.out", "w");
56 int i, j, p, q;
57
58 for(i=0; i<=9; i++)
59 fscanf(f1, "%d ", &perm[i]);
60
61 fscanf(f1, "%s\n", A+1);
62 N = strlen(A+1);
63
64 fscanf(f1, "%d\n", &K);
65
66 preproc_puteri();
67 preproc_ajunge();
68
69 int jumatate = N / 2;
70
71 //prima cerinta
72 for(i=jumatate; i>=1; i--)
73 {
74 int cif1 = A[i] - ’0’;
75 int cif2 = A[N-i+1] - ’0’;
76
77 int finish = 0;
78 if(i == 1) finish = 1;
79
80 for(q=9; q>=1; q--)
81 {
82 if(ajunge[cif1][q] >= 0 && ajunge[cif2][q] >= 0)
83 {
84 sol[i] = (q + ’0’);
85 break;
86 }
CAPITOLUL 28. ONI 2012 595
87 }
88 }
89
90 for(i=1; i<=jumatate; i++)
91 fprintf(f2, "%c", sol[i]);
92
93 for(i=jumatate; i>=1; i--)
94 fprintf(f2, "%c", sol[i]);
95
96 fprintf(f2, "\n");
97
98 //a doua cerinta
99 for(i=jumatate+1; i>=1; i--)
100 for(j=0; j<K; j++)
101 D[i][j] = inf;
102
103 D[jumatate+1][0] = 0;
104
105 for(i=jumatate; i>=1; i--)
106 {
107 int cif1 = A[i] - ’0’;
108 int cif2 = A[N-i+1] - ’0’;
109
110 for(j=0; j<K; j++)
111 {
112 int start = 0;
113 if(i == 1) start = 1; //prima cifra a palindromului nu poate fi 0
114
115 for(p=start; p<=9; p++)
116 if(ajunge[cif1][p] >= 0 && ajunge[cif2][p] >= 0)
117 {
118 int nou_rest = (j + p * (put[N-i] + put[i-1])) % K;
119 D[i][nou_rest] = min(D[i][nou_rest], D[i+1][j] +
120 ajunge[cif1][p] + ajunge[cif2][p]);
121 }
122 }
123 }
124
125 int cost = D[1][0];
126 int rest = 0;
127
128 if(cost >= N * 10)
129 {
130 fprintf(f2, "-1\n");
131 fclose(f1);
132 fclose(f2);
133 return 0;
134 }
135
136 for(i=1; i<=jumatate; i++)
137 {
138 //calculez sol[i]
139 int cif1 = A[i] - ’0’;
140 int cif2 = A[N-i+1] - ’0’;
141
142 int finish = 0;
143 if(i == 1) finish = 1;
144
145 for(q=9; q>=finish; q--)
146 {
147 if(ajunge[cif1][q] >= 0 && ajunge[cif2][q] >= 0)
148 {
149 p = (q * (put[N-i] + put[i-1])) % K;
150 int nou_rest = rest - p;
151 if(nou_rest < 0) nou_rest += K;
152
153 if(D[i+1][nou_rest]+ajunge[cif1][q]+ajunge[cif2][q] == cost)
154 {
155 //este ok ok ok
156 sol[i] = (q + ’0’);
157
158 cost -= (ajunge[cif1][q] + ajunge[cif2][q]);
159 rest = nou_rest;
160
161 break;
162 }
CAPITOLUL 28. ONI 2012 596
163 }
164 }
165 }
166
167 for(i=1; i<=jumatate; i++)
168 fprintf(f2, "%c", sol[i]);
169
170 for(i=jumatate; i>=1; i--)
171 fprintf(f2, "%c", sol[i]);
172
173 fprintf(f2, "\n");
174
175 fclose(f1);
176 fclose(f2);
177 return 0;
178 }
28.5 sstabil
Problema 5 - sstabil 100 de puncte
Numim num r sstabil orice num r natural care este format dintr-o singur cifr sau care are
suma oric ror dou cifre vecine strict mai mare decât nou .
Asupra oric rui num r care nu este sstabil se pot efectua operaµii de înlocuire a oric ror dou
cifre vecine care au suma strict mai mic decât zece cu o cifr egal cu suma lor.
Operaµiile de înlocuire pot aplicate, în acela³i condiµii, ³i asupra numerelor rezultate dup
ecare înlocuire, de câte ori este nevoie, pân când se obµine un num r sstabil.
De exemplu, 291 este num r sstabil deoarece 2+9>9 ³i 9+1>9, iar 183 nu este sstabil pentru
c 1+8<10. Din num rul 2453, efectuând o singur înlocuire, putem obµine 653 sau 293 (num r
sstabil) sau 248. Num rul 653, neind sstabil, permite o nou operaµie de înlocuire, obµinând
astfel num rul 68, care este sstabil. Analog, din num rul 248 se poate obµine num rul sstabil 68.
Cerinµe
Scrieµi un program care s determine cel mai mare num r natural sstabil care se poate obµine
dintr-un num r natural dat, aplicând una sau mai multe operaµii de înlocuire de tipul menµionat.
Date de intrare
Fi³ierul de intrare sstabil.in conµine pe prima linie un num r natural n, reprezentând num rul
de cifre al num rului dat, iar pe linia a doua, separate prin câte un spaµiu, cifrele acestui num r.
Date de ie³ire
Fi³ierul de ie³ire sstabil.out va conµine pe o linie num rul sstabil maxim obµinut.
Restricµii ³i preciz ri
a 1 & n & 1 000 000
Exemple:
sstabil.in sstabil.out Explicaµii
510451 191 10451 1091 191
552832 785
52832 7832 785
Timp maxim de executare/test: 1.0 secunde
Memorie: total 16 MB din care pentru stiv 4 MB
Dimensiune maxim a sursei: 5 KB
CAPITOLUL 28. ONI 2012 597
De la dreapta la stânga se determin cifrele , cât mai mici, ale unui num r sstabil. Procedând
astfel vom obµine un num r sstabil cu num r maxim de cifre ³i care are primele cifre cele mai mari
(faµ de un alt num r sstabil care ar avea acela³i num r de cifre). Vom demonstra în continuare.
Demonstraµia soluµiei pentru problema âsstabil: ...
61 fclose(stdin);
62 return 0;
63 }
17 b[0]=9;
18 k=0;
19 r=n;
20 while (r>0)
21 {
22 j=r; s=0;
23 do
24 {
25 s=s+a[j];
26 j--;
27 } while (s<10);
28
29 p=r;
30 t=a[p];
31
32 while (s-t>9 || t+b[k]<10)
33 {
34 p--;
35 t=t+a[p];
36 }
37
38 k++;
39 b[k]=t;
40 r=p-1;
41 }
42
43 for (i=k;i>=1;i--)
44 printf("%d",b[i]);
45
46 fclose(stdout);
47 fclose(stdin);
48 return 0;
49 }
28.6 unuzero
Problema 6 - unuzero 100 de puncte
Se consider un ³ir format din N 2 cifre binare, care conµine cel puµin o cifr 1 ³i cel puµin
trei cifre 0; prima ³i ultima cifr a ³irului sunt 0.
Numim 1-secvenµ o succesiune format numai din cifre 1, aate pe poziµii consecutive în acest
³ir, delimitat de câte o cifr 0.
Corina construie³te un astfel de ³ir, în care num rul de cifre 1 ale ec rei 1-secvenµe s e
cuprins între dou numere naturale date, p ³i q (p & q ).
Cerinµe
Scrieµi un program care s determine un num r natural K , egal cu restul împ rµirii la 666013
a num rului de ³iruri distincte, de tipul celui construit de Corina.
Date de intrare
Fi³ierul de intrare unuzero.in conµine pe prima linie num rul natural N , iar pe cea de a doua
linie numerele naturale p ³i q (p & q ), separate printr-un spaµiu.
Date de ie³ire
Fi³ierul de ie³ire unuzero.out va conµine pe prima linie num rul natural K cerut.
Restricµii ³i preciz ri
a 1 & p & q $ N $ 1 000 000. a Pentru 20% din teste N & 25, iar pentru alte 40% din teste
25 $ N & 1 000.
Exemple:
CAPITOLUL 28. ONI 2012 600
Se observ c problema nu poate obµine decât 20 de puncte dac vom încerca s gener m toate
soluµiile posibile pe care apoi s contoriz m si 60 de puncte pentru lungimi mai mici de 1000.
Ideea de rezolvare se bazeaz pe observarea unei relaµii de recurenµ ce se poate deduce dup o
scurt analiz . Putem considera c utiliz m cifrele zero ³i unu iar secvenµele c utate sunt formate
din valori successive de unu. Dac presupunem c am format deja o secvenµ de 1 pentru o lungime
dat , atunci în stânga va evident 0.
Fie U i, num rul de conguraµii corecte de lungime i, terminate cu 1 ³i Z i, num rul de
conguraµii corecte de lungime i, terminate cu 0.
Atunci, avem relaµia de recurenµ urm toare:
ia
U i = Z j
j ib
25 else
26 u[i]=s[i-a];
27
28 if(u[i]<0) u[i]+=mod;
29 u[i]%=mod;
30
31 s[i]=s[i-1]+z[i];
32 s[i]%=mod;
33 }
34
35 out<<(z[n]+u[n]-1+(z[n]+u[n]-1<0?mod:0))%mod<<’\n’;
36 out.close();
37 return 0;
38 }
1 // O(n^2)
2 #include <fstream>
3
4 using namespace std;
5
6 int mod=666013,a,b;
7 int u[1000100],z[1000100],n;
8
9 int main()
10 {
11 ifstream in("unuzero.in");
12 ofstream out("unuzero.out");
13
14 in>>n>>a>>b;
15 z[0]=1;
16 z[1]=1;
17 if(a==1) u[1]=1;
18 for(int i=2;i<=n;++i)
19 {
20 z[i]=z[i-1]+u[i-1]; // daca punem 0
21 z[i]%=mod;
22 for(int j=i-b;j<=i-a;++j) // daca punem 1
23 {
24 if(j>=0)
25 {
26 u[i]+=z[j];
27 u[i]%=mod;
28 }
29 }
30 }
31
32 out<<(z[n]+u[n]-1+(z[n]+u[n]-1<0?mod : 0))%mod<<’\n’;
33 out.close();
34 return 0;
35 }
38
39 n[i] %= mod;
40 }
41
42 s[i] = (s[i-1] + n[i]) % mod;
43 }
44
45 fprintf(f2, "%d\n", (mod + n[N] - 1) % mod);
46
47 fclose(f1);
48 fclose(f2);
49 return 0;
50 }
ONI 2011
29.1 poligon
Problema 1 - poligon 100 de puncte
Poligonul de tragere este un teren special amenajat în cadrul c ruia se fac exerciµii ³i se execut
trageri cu arme de foc. Comandantul plaseaz câte o µint în toate punctele aate la distanµele
Ri , 1 & i & n faµ de punctul de tragere (origine) ³i care au coordonatele carteziene numai numere
naturale nenule.
Speciali³tii în armament români au creat recent o nou arm sub forma unui tun laser care
î³i lanseaz razele pe o traiectorie rectilinie ³i are capacitatea de a distruge toate µintele aate pe
direcµia de tragere.
Cerinµe
tiind c tunul laser se g se³te în originea sistemului de
coordonate, s se scrie un program care s determine: num -
rul de µinte, num rul minim de lovituri de tun laser necesare
pentru a distruge toate µintele precum ³i num rul de µinte
doborâte la ecare lovitur .
Spre exemplu, dac avem n 6 distanµe (5, 7, 10, 13, 15,
17) pentru care se încearc plasarea µintelor, atunci în poligon
se vor plasa 10 µinte, va nevoie de 6 lovituri pentru a doborî
toate µintele iar la ecare lovitur se vor doborî respectiv 1,
1, 3, 3, 1, 1 µinte.
Date de intrare
Fi³ierul de intrare poligon.in conµine pe prima linie num rul n de distanµe la care vor
plasate µinte, iar pe a doua linie n numere naturale nenule distincte separate printr-un spaµiu, ce
reprezint aceste distanµe.
Date de ie³ire
Fi³ierul de ie³ire poligon.out va conµine 3 linii. Pe prima linie se va scrie num rul µintelor
plasate în poligon. Pe a doua linie se va scrie num rul minim de lovituri de tun laser cu care se pot
doborî toate µintele, iar pe a treia linie se va scrie num rul de µinte doborâte la ecare lovitur ,
separate printr-un spaµiu, în ordinea cresc toare a unghiurilor direcµiilor cu axa OX .
Restricµii ³i preciz ri
a 1 & n & 1000
a 1 & Ri & 1000
a pentru ecare set de date de intrare, în poligon va exista cel puµin o µint .
a se acord :
- 20% din punctaj pentru determinarea corect a num rului de µinte.
- 40% din punctaj pentru determinarea corect a num rului minim de lovituri.
- 40% din punctaj pentru determinarea corect a num rului de µinte doborâte la ecare lovi-
tur .
604
CAPITOLUL 29. ONI 2011 605
Exemple:
poligon.in poligon.out Explicaµii
6 10 Avem 6 distante: 5,10,15,7,13,17.
5 10 15 7 13 17 6 În poligon vor plasate 10 µinte (punctele negre marcate pe
113311 gur ) care pot doborâte din 6 lovituri iar la ecare lovitur
se vor doborî câte 1, 1, 3, 3, 1, 1 µinte.
Timp maxim de executare/test: 0.4 secunde
Memorie: total 2 MB
Dimensiune maxim a sursei: 5 KB
Observ m c pentru a determina µintele active din poligon trebuie determinat num rul de
2 2 2
soluµii al ecuaµiei R x y unde R reprezint raza cercurilor de activare. în vederea rezolv rii
³i cerinµelor ulterioare, coordonatele µintelor active se vor înc rca într-o structura de date, pe care
se vor face interog ri suplimentare. Mic³orarea timpului de rezolvare a acestei ecuaµii are la baz
observaµia c soluµiile sunt simetrice faµ de prima bisectoare.
În vederea determin rii num rului minim de lovituri trebuie s determin m câte drepte dis-
tincte se formeaz unind coordonatele µintelor active cu originea sistemului de axe. Având în
vedere îns c trebuie s determin m ³i num rul de puncte coliniare de pe ecare dreapta, în
sens trigonometric, vom face sortarea coordonatelor µintelor active dup panta acestora. Se poate
utiliza relaµia conform c reia dac dou puncte A x1 , y1 ³i B x2 , y2 sunt coliniare cu originea
sistemului de axe atunci x1 y2 x2 y1 .
Dup sortare se determin câte puncte fac parte din aceea³i categorie ³i se a³eaz rezultatele.
37 {
38 aux=x[i]; x[i]=x[j]; x[j]=aux;
39 aux=y[i]; y[i]=y[j]; y[j]=aux;
40 }
41
42 x[0]=0; y[0]=1;
43 s=0;
44 for (i=1;i<=c;i++)
45 {
46 if (x[i-1]*y[i]<x[i]*y[i-1])
47 s++;
48 }
49
50 f2<<s<<"\n";
51 s=1;
52 for (i=2;i<=c;i++)
53 {
54 if (x[i-1]*y[i]==x[i]*y[i-1])
55 {
56 s++;
57 }
58 else
59 {
60 f2<<s<<" ";
61 s=1;
62 }
63 }
64
65 f2<<s;
66 f2.close();
67 f1.close();
68 return 0;
69 }
29.2 stalpi
Problema 2 - stalpi 100 de puncte
Între doi stâlpi verticali aaµi pe malurile unui râu (de o parte ³i de alta a râului) se a
legate dou cabluri bine întinse, paralele cu solul, având distanµa dintre ele egal cu d centimetri.
Cablurile sunt folosite pentru traversarea râului în caz de inundaµii. Stâlpii sunt notaµi cu A ³i B ,
iar cablurile cu 1 ³i 2 ca în gura de mai jos.
Pe cabluri exist desenate câte n puncte colorate cu diverse culori, culorile ind codicate prin
numerele 1, 2, 3,..., k . Poziµia punctelor pe ecare cablu este dat prin distanµa faµ de stâlpul
A pentru ecare punct. Punctele de pe ecare cablu sunt numerotate cu 1, 2, 3 ,..., n. Pe ecare
cablu exist cel puµin un punct colorat cu ecare culoare. Pentru a u³ura deplasarea pe cablu,
primarul hot r ³te s lege cu sârm perechi de puncte de aceea³i culoare, unul de pe primul cablu,
iar cel lalt de pe al doilea cablu, astfel încât:
- pentru ecare culoare s existe o singur pereche de puncte între care s e leg tur ;
- lungimea total de sârm folosit s e minim .
Cerinµe
S se scrie un program care determin lungimea minim a sârmei ce va folosit pentru
rezolvarea problemei ³i o mulµime de perechi de puncte ce urmeaz a legate pentru a obµine
acest minim.
Date de intrare
Fi³ierul de intrare stalpi.in va conµine:
- pe prima linie numerele naturale nenule n, d separate printr-un spaµiu;
- pe a doua linie n perechi de numere, formate din distanµa faµ de stâlpul A la ecare punct
³i culoarea asociat punctului, separate prin câte un spaµiu, aate pe cablul 1;
CAPITOLUL 29. ONI 2011 607
- pe a treia linie n perechi de numere, formate din distanµa faµ de stâlpul A la ecare punct
³i culoarea asociat punctului, separate prin câte un spaµiu, aate pe cablul 2.
Date de ie³ire
Fi³ierul de ie³ire stalpi.out va conµine pe prima linie valoarea minim cerut , iar pe urm toa-
rele k linii numerele de ordine ale punctelor ce vor legate cu sârm , separate printr-un spaµiu,
întâi cele de pe cablu 1, urmate de cele de pe cablu 2, în ordinea cresc toare a culorilor.
Restricµii ³i preciz ri
a 1 & n & 10 000
a 1 & k & 100
a 1 & d & 1 000
a Distanµa dintre cei doi stâlpi A ³i B este 30 000.
a Distanµele de la stâlpul A la puncte sunt numere naturale.
a Distanµa minim va a³at trunchiat la primele 3 zecimale.
a Toate punctele de pe un cablu sunt distincte.
a Se acord 40% din punctaj pentru determinarea corect a minimului din cerinµ .
Exemple:
stalpi.in stalpi.out Explicaµii
3 100 211.803 Sunt n 3 perechi de puncte, k 2 culori, codicate cu 1 ³i 2.
50 1 200 2 100 1 32 Necesarul minim de sârm este 211.803.
250 2 100 1 300 2 21 Se leag punctul P3 de punctul Q2 (ambele au culoarea 1).
Se leag punctul P2 de punctul Q1 (ambele au culoarea 2).
Timp maxim de executare/test: 0.2 secunde
Memorie: total 4 MB
Dimensiune maxim a sursei: 5 KB
Folosind datele de intrare, pentru ecare culoare c din mulµimea r1, 2, ..., k x se construiesc doi
vectori:
a a0 , a1 , ..., a30000 , unde ai este codul punctului aat la distanµa i de stâlpul A de pe
primul cablu (0 dac nu exist punct).
b b0 , b1 , ..., b30000 , unde bi este codul punctului aat la distanµa i de stâlpul A de pe al
doilea cablu (0 dac nu exist punct).
Parcurgem folosind acela³i indice i (0, 1, 2, ..., 30 000) ambii vectori a ³i b ³i actualiz m trei
variabile xa, xb ³i min (iniµial min este 20 000), astfel:
dac ai j 0 si xa=0, atunci xa=i
daca bi j 0 si xb=0, atunci xb=i
dac ai j 0 si xb j 0 si |i-xb|<min, atunci xa=i; min=|i-xb|
dac bi j 0 si xa j 0 si |i-xa|<min, atunci xb=i; min=|i-xb|
CAPITOLUL 29. ONI 2011 608
Õ
S d2 xa xb2
Introducem xa ³i xb în doi vectori x ³i y .
A³ m s ³i elementele vectorilor x ³i y .
În algoritm am folosit:
Se construiesc tablourile cablu1[ ] ³i cablu2[ ], ecare de câte 30 000 de elemente de tip int.
Pentru ecare punct de pe ecare cablu, poziµia i din ³irul de date citit ³i perechea (distanµ ,
culoare) specice ec rui punct le-am memorat prin
cablu1[distanµ ] = i*100+culoare-1, respectiv
cablu2[distanµ ] = i*100+culoare-1
În procesul de citire a datelor ³i construire a tablourilor cablu1[ ] ³i cablu2[ ] am calculat
num rul de culori k ca ind valoarea maxim a valorilor culorilor citite.
Pentru ecare culoare cul, în ordinea 1,2, ..., k , am utilizat tablourile cablu1[ ] ³i cablu2[ ]
pentru sortarea în complexitate O n a punctelor de aceea³i culoare de pe ecare cablu, preluând
distanµa faµ de cap tul stâng al cablului pe care se a ³i poziµia din ³irul datelor de intrare în
tablourile x1[] ³i z1[] cu n1 elemente, respectiv x2[] ³i z2[] cu n2 elemente.
Folosind un algoritm asem n tor cu cel de la interclasarea a doi vectori ordonaµi am determinat
în complexitate O n diferenµa cea mai mic dif t, în valoare absolut , dintre distanµele faµ de
capetele din stânga ale cablurilor, ale celor dou puncte de aceea³i culoare cul aate pe cabluri
diferite, x1i ³i x2j , 1 & i & n1 ³iÔ1 & j & n2.
Apoi am calculat, cu formula dif t dif t d d, lungimea sârmei care va uni cele dou
puncte, ca lungime a ipotenuzei într-un triunghi dreptunghic de catete dif t ³i d ³i am ad ugat-o
sumei dmin. Am memorat prin xcul i1 ³i y cul i2 perechea de poziµii i1 ³i i2, din ³irul de
date de intrare, corespunz toare celor dou puncte alese.
La nal am a³at cu trei zecimale exacte valoarea dmin ³i apoi cele k perechi xi, y i,
1 & i & k.
10 double dmin;
11
12 ifstream f1("stalpi.in");
13 ofstream f2("stalpi.out");
14
15 int main()
16 {
17
18 f1>>n>>d;
19 k=0;
20 d1=0;
21 for (i=1;i<=n;i++)
22 {
23 f1>>poz>>cul;
24 cablu1[poz]=i*100+cul-1;
25 if (cul>k) k=cul;
26 if (poz>d1)d1=poz;
27 }
28
29 d2=0;
30 for (i=1;i<=n;i++)
31 {
32 f1>>poz>>cul;
33 cablu2[poz]=i*100+cul-1;
34 if (poz>d2)d2=poz;
35 }
36
37 dmin=0;
38 for (cul=1;cul<=k;cul++)
39 {
40 n1=0;
41 m1=0;
42 for (i=0;i<=d1;i++)
43 {
44 if (cablu1[i])
45 {
46 m1++;
47 if (cablu1[i]%100+1 == cul)
48 {
49 n1++;
50 x1[n1]=i;
51 z1[n1]=cablu1[i]/100;
52 }
53 }
54 }
55
56 n2=0;
57 m2=0;
58 for (i=0;i<=d2;i++)
59 {
60 if (cablu2[i])
61 {
62 m2++;
63 if (cablu2[i]%100+1 == cul)
64 {
65 n2++;
66 x2[n2]=i;
67 z2[n2]=cablu2[i]/100;
68 }
69 }
70 }
71
72 i=1;
73 j=1;
74 dift=x1[i]-x2[j];
75 i1=z1[i];
76 i2=z2[j];
77 if (dift<0) dift=-dift;
78 while (i<=n1 && j<=n2 && dift!=0)
79 {
80 dif=x1[i]-x2[j];
81 if (dif<0)dif=-dif;
82 if (dif<dift)
83 {
84 dift=dif;
85 i1=z1[i];
CAPITOLUL 29. ONI 2011 610
86 i2=z2[j];
87 }
88
89 if (x1[i]<x2[j])
90 i++;
91 else
92 j++;
93 }
94
95 x[cul]=i1;
96 y[cul]=i2;
97 dmin=dmin+sqrt((double)dift*dift+d*d);
98 }
99
100 w1=(int)floor(dmin);
101 w2=(int)floor((dmin-w1)*1000);
102 f2<<w1<<".";
103 if (w2<10)
104 f2<<"00"<<w2;
105 else
106 if (w2<100)
107 f2<<"0"<<w2;
108 else
109 f2<<w2;
110
111 f2<<"\n";
112 for (cul=1;cul<=k;cul++)
113 {
114 f2<<x[cul]<<" "<<y[cul]<<"\n";
115 }
116
117 f2.close();
118 f1.close();
119 return 0;
120 }
29.3 tort
Problema 3 - tort 100 de puncte
De ziua lui, Gigel a primit un tort de form dreptunghiular , ornat cu un caroiaj ce împarte
tortul în m n p trate, în ecare p trat aându-se câte o cirea³ sau o c p³un . Caroiajul cu
fructe este reprezentat printr-o matrice cu 0 ³i 1, 0 însemnând cirea³ ³i 1 c p³un .
S rb toritul are dreptul s taie k felii de tort. O felie se poate obµine prin t ierea dup liniile
caroiajului, dintr-un cap t în cel lalt, având l µimea egal cu 1, de pe oricare latur a tortului,
codicate cu N, E, S, V. Gigel ind mare amator de c p³uni vrea s taie cele k felii astfel încât
num rul c p³unilor din aceste felii s e cât mai mare.
Spre exemplu, dac tortul iniµial este reprezentat ca o matrice având 6 6 linii ³i coloane,
dup 3 t ieturi N, E, V bucata r mas ³i feliile obµinute vor conform gurii al turate.
Cerinµe
S se scrie un program care s determine num rul de posibilit µi de t iere a k felii de tort,
pentru a obµine un num r maxim de c p³uni. Dou variante în care difer doar ordinea de t iere,
CAPITOLUL 29. ONI 2011 611
dar r mâne aceea³i bucat de tort, nu sunt considerate distincte. De exemplu, dac num rul
maxim de c p³uni se poate obµine prin una din variantele : VSNNV sau VVNSN, acestea nu sunt
considerate distincte.
Date de intrare
Pe prima linie a ³ierului de intrare tort.in sunt scrise dimensiunile tortului, m ³i n ³i num rul
k al feliilor de tort t iate de Gigel, separate prin câte un spaµiu. Pe urm toarele m linii e descris
caroiajul cu fructe printr-o matrice cu valori de 0 ³i 1.
Date de ie³ire
Prima linie a ³ierului tort.out va conµine num rul maxim de c p³uni care poate obµinut
din cele k felii de tort. Pe linia a doua se va g si num rul de posibilit µi distincte de a obµine
num rul maxim de c p³uni.
Restricµii ³i preciz ri
a 2 & m, n & 500
a 1 & k $ min m, n
Exemple:
tort.in tort.out Explicaµii
6 6 3 10 Tortul este format dintr-un caroiaj cu m 6 linii ³i n 6
0 1 1 1 0 1 5 coloane ³i se pot t ia k 3 felii.
1 0 0 0 0 1 Se pot obµine maxim 10 c p³uni.
0 0 0 1 0 0 Cele 5 posibilit µi de a t ia cele 3 felii sunt: NNS, NSE, NSV,
0 1 0 1 0 1 VEV ³i NEV
1 0 0 0 0 0
1 1 1 0 0 1
Timp maxim de executare/test: 0.2 secunde
Memorie: total 4 MB
Dimensiune maxim a sursei: 5 KB
Dup t ierea celor k felii din tort, r mâne un dreptunghi de dimensiuni m m1 n n1,
unde m1 ³i n1 reprezint numarul feliilor orizontale, respectiv verticale (n1 n2 k ). Trebuie ca
acest dreptunghi s conµin cât mai puµine valori 1 (capsuni). Construim o matrice în care pentru
1 & i & m ³i 1 & j & n memoram num rul de cap³uni din dreptunghiul cu vârfurile opuse 1, 1
³i i, j , dup care num rul de cap³uni din orice submatrice se gase³te în O 1. Vom determina
pentru ecare k1 cu valori de la 0 la k toate submatricele de dimensiuni m k1 n k k1 cu
num r minim de 1 printr-o singura parcurgere a matricei obµin nd o complexitate O m n k ,
sucient pentru dimensiunile date.
Algoritm tort
citeste m,n,k
pt. i=1,m
pt. j=1,n citeste Aij sf.
sf.
B[1,1]=A[1,1]; min=m*n+1;
pt. i=2,m B[i,1]=B[i-1,1]+A[i,1] sf.
pt. j=2,n B[1,j]=B[1,j-1]+A[1,j] sf.
pt. i=2,m
pt. j=2,n Bij=B[i,j-1]+B[i-1,j]-B[i-1,j-1] sf.
sf.
pt. k1=0,k1
pt. i=m-k1,m
pt. j=n-k+k1,n
S=Bij-B[i-m+k1,j]-B[i,j-n+k-k1]+B[i-m+k1,j-n+k-k1]
CAPITOLUL 29. ONI 2011 612
29.4 ape
Problema 4 - ape 100 de puncte
CAPITOLUL 29. ONI 2011 613
Mihai crede c m pricep la informatic ³i m roag s îl ajut la efectuarea unor calcule. Mi-a
povestit c în vacanµ a fost la µar la bunici. Bunicii lui se ocup de piscicultur ³i au preluat
spre utilizare o zon de teren unde se a lacuri, hele³tee ³i b lµi. Sunt pl tite taxe speciale în
funcµie de suprafeµele acestor ape. Bunicului i se pare c cei de la ociul unde se pl tesc taxele au
date gre³ite în dosare, despre ariile acestor suprafeµe de ap ³i l-a rugat pe Mihai s îi calculeze cu
aproximaµie aceste arii. Mihai a studiat problema ³i s-a hot rât s înconjoare ecare ap , mergând
pe conturul acesteia. Pasul lui are lungimea de 1 metru. La ecare pas Mihai folose³te o busol
³i î³i noteaz într-un carneµel direcµia înspre care a fost efectuat pasul Nord, Sud, Est sau Vest.
Dup ecare pas Mihai actualizeaz ³i num rul de pa³i pe care i-a f cut.
Cerinµe
Se dore³te s se ae, pentru ecare traseu:
a) Dimensiunile pe direcµiile Vest-Est ³i respectiv Nord-Sud ale unei suprafeµe dreptunghiulare
de arie minim care cuprinde în interior sau pe margini suprafaµa apei.
b) Sensul în care a fost parcurs traseul: 0- pentru sens orar, respectiv 1- pentru sens invers
orar;
c) Aria suprafeµei apei înconjurate, din interiorul traseului.
Date de intrare
Fi³ierul de intrare ape.in are pe prima linie num rul P de pa³i ai traseului. în linia 2 se a
un ³ir de P litere mari, f r spaµii între ele, din mulµimea {N, S, E, V} reprezentând traseul.
Date de ie³ire
Fi³ierul de ie³ire ape.out va conµine patru numere naturale separate prin câte un spaµiu: pri-
mul num r reprezint dimensiunea pe direcµia Vest-Est ³i al doilea num r reprezint dimensiunea
pe direcµia Nord-Sud a suprafeµei dreptunghiulare de arie minim care cuprinde în interior sau pe
margini suprafaµa apei delimitat de traseu; al treilea num r reprezint sensul parcurgerii, iar al
patrulea num r reprezint aria.
Restricµii ³i preciz ri
a 1 & P & 10 000
a Pentru 30% din teste traseele vor avea lungimea maxim 2 000.
a Dac dimensiunile suprafeµei dreptunghiulare de arie minim sunt corecte, atunci se va
acorda 10% din punctaj/test.
a Dac sensul traseului este determinat corect, atunci se vor primi 10% puncte/test.
a Aria suprafeµei apei este un num r natural nenul.
Exemple:
ape.in ape.out Explicaµii
16 3315 C suµele marcate cu '-' reprezint traseul, iar p tratele
NNVVSVSSESEEENNV negre reprezint apa.
Zona m rginit de linia îngro³at
reprezint suprafaµa dreptunghiu-
lar minimal ce conµine p tratele
negre, care reprezint apa.
C suµa marcat cu * este poziµia
de pornire.
Timp maxim de executare/test: 0.1 secunde
Memorie: total 2 MB
Dimensiune maxim a sursei: 5 KB
29.5 ec
Problema 5 - ec 100 de puncte
Alexandru are la dispoziµie un tablou p tratic de dimensiune n cu numere întregi ³i k ecuaµii
de tipul I ³i II. Ecuaµiile de tipul I sunt de forma: ax b c, cu a, b, c numere naturale, iar
2
ecuaµiile de tipul II sunt de forma: ax bx c d, cu a, b, c, d numere naturale.
Alexandru î³i propune s determine pentru ecare tip de ecuaµie: num rul lor ³i câte dintre
ele au r d cinile în tabloul dat.
Cerinµe
S se scrie un program care determin num rul de ecuaµii de tipul I, câte dintre acestea au
exact o r d cin în tablou, respectiv num rul de ecuaµii de tipul II ³i câte dintre acestea au exact
ambele r d cini în tablou.
Date de intrare
Fi³ierul de intrare ec.in va conµine: pe prima linie numerele naturale n ³i k separate printr-un
spaµiu, pe urm toarele n linii elementele tabloului separate prin câte un spaµiu, iar pe urm toarele
k linii ecuaµiile în forma din enunµ, câte una pe ecare linie.
Date de ie³ire
Fi³ierul de ie³ire ec.out va conµine pe prima linie dou numere separate printr-un spaµiu re-
prezentând num rul de ecuaµii de tipul I, respectiv num rul de ecuaµii de tipul I care au exact o
r d cin , aat în tablou, iar pe a doua linie tot dou numere separate printr-un spaµiu repre-
zentând num rul de ecuaµii de tipul II, respectiv num rul de ecuaµii de tipul II cu exact dou
r d cini, ambele r d cini în tablou.
CAPITOLUL 29. ONI 2011 616
Restricµii ³i preciz ri
a 1 & n & 500
a 1 & k & 1000
a Elementele tabloului sunt numere întregi cu maxim 4 cifre ecare;
a La ecare ecuaµie de tipul I a, b, c vor precizate, chiar dac acestea au valoarea 0 sau 1,
(de exemplu x 2 3 va apare 1x 2 3).
a La ecare ecuaµie de tipul II a, b, c, d vor precizate, chiar dac acestea au valoarea 0 sau 1,
2
(de exemplu x2 1 3 va apare 1x 0x 1 3).
a Pentru ecuaµiile de tipul I a, b, c sunt numere naturale cu maxim 4 cifre;
a Pentru ecuaµiile de tipul II a, b, c, d sunt numere naturale cu maxim 4 cifre;
a Se va acorda: 10% din punctaj pentru num rul de ecuaµii de tipul I, 30% din punctaj pentru
câte dintre ele au exact o r d cin în tablou, 20% din punctaj pentru num rul de ecuaµii de tipul
II ³i 40% din punctaj pentru câte dintre ele au exact ambele r d cini în tablou.
Exemple:
ec.in ec.out Explicaµii
25 21 Prima ecuaµie este de tipul I si are r d cina 0, care nu se g se³te
12 31 în tablou.
2 -1 A doua ecuaµie este de tipul II ³i are dou r d cini egale cu -1,
1x+0=0 care se g sesc în tablou.
20x2+40x+20=0 A treia ecuaµie este de tipul I ³i are r d cina 2, care se g se³te
101x+200=402 în tablou.
2x2+1x+4=0 A patra ecuaµie este de tipul II ³i nu are r d cinile în tablou.
1x2+1x+3=5 A cincea ecuaµie este de tipul II ³i are r d cinile -2 ³i 1, dar nu
sunt amândou în tablou.
Timp maxim de executare/test: 0.8 secunde
Memorie: total 4 MB
Dimensiune maxim a sursei: 5 KB
8
9 using namespace std;
10
11 int N, M, L, nr_ec1, nr_ec2, sol_ec1, sol_ec2;
12 int v[Nmax];
13 char line[Lmax];
14
15 inline bool is_int(long double x)
16 {
17 return abs((int)x - x) < 0.000000000001L;
18 }
19
20 int main()
21 {
22 freopen("ec.in", "r", stdin);
23 freopen("ec.out", "w", stdout);
24
25 scanf("%d %d\n", &N, &M);
26
27 L = N*N;
28 for (int i = 0; i < L; ++i)
29 {
30 int x;
31 scanf("%d ",&x);
32 v[x+10000] = 1;
33 }
34
35
36 int coef[4], nr_coef;
37 for (int i = 0; i < M; ++i)
38 {
39 scanf("%s\n", line);
40 nr_coef = 0;
41 int val = 0;
42 for (int j = 0, size = strlen(line); j < size; ++j)
43 {
44 if (line[j] <= ’9’ && line[j] >= ’0’)
45 val = val * 10 + line[j] - ’0’;
46
47 if (line[j] == ’x’)
48 {
49 coef[nr_coef++] = val;
50 val = 0;
51 if (line[j + 1] == ’^’)
52 j+=3;
53 else
54 ++j;
55 }
56
57 if (line[j] == ’=’)
58 {
59 coef[nr_coef++] = val;
60 val = 0;
61 }
62 }
63
64 coef[nr_coef++] = val;
65
66 long double sol;
67
68 if (nr_coef == 3)
69 {
70 //ec gr1
71 ++nr_ec1;
72 if (coef[0] == 0) continue;
73 sol = ((long double)(coef[2] - coef[1])) / coef[0];
74 if (is_int(sol) && v[(int)sol+10000])
75 ++sol_ec1;
76 }
77 else
78 {
79 //ec gr 2
80 ++nr_ec2;
81 bool ok = true;
82 int delta = coef[1]*coef[1] - 4*coef[0]*(coef[2] - coef[3]);
83 if (coef[0] == 0)
CAPITOLUL 29. ONI 2011 618
84 {
85 if (coef[1] == 0)
86 continue;
87 sol = ((long double)(coef[3] - coef[2])) / coef[1];
88 if (is_int(sol) && v[(int)sol+10000])
89 ++sol_ec2;
90 continue;
91 }
92
93 if (delta < 0) continue;
94
95 sol = (long double)(-coef[1] + sqrtl(delta)) / (2*coef[0]);
96 if (!(is_int(sol) && v[(int)sol+10000]))
97 ok = false;
98
99 sol = (long double)(-coef[1] - sqrtl(delta)) / (2*coef[0]);
100 if (is_int(sol) && v[(int)sol+10000] && ok)
101 ++sol_ec2;
102 }
103 }
104
105 printf("%d %d\n%d %d\n", nr_ec1, sol_ec1, nr_ec2, sol_ec2);
106 return 0;
107 }
29.6 furnici
Problema 6 - furnici 100 de puncte
La Institutul de cercetare al insectelor s-a descoperit c dac furnicile sunt puse pe o bar
metalic , ele au un comportament bine denit dup urm toarele reguli:
1. Imediat cum a fost pus pe bar ea î³i începe deplasarea în sensul în care a fost orientat ,
cu viteza constant de 1cm/s. Furnica nu se opre³te cât timp se a pe bara metalic chiar
dac se ciocne³te cu alt furnic .
2. Dac pe drum nu se întâlne³te cu alt furnic ea î³i va continua deplasarea pân când va
c dea de pe bar .
3. Când dou furnici se întâlnesc, ele î³i schimb amândou instantaneu sensul de deplasare.
Cerinµe
tiind c pe o bar metalic de lungime L cm se plaseaz exact N furnici în poziµii cunoscute ³i
cu sensul iniµial de deplasare cunoscut, s se scrie un program care calculeaz num rul de secunde
dup care va c dea de pe bar ³i ultima furnic de la momentul iniµial. Toate furnicile î³i încep
deplasarea concomitent.
Date de intrare
Fi³ierul de intrare furnici.in conµine pe prima linie dou numere naturale L ³i N separate
printr-un spaµiu. Apoi urmeaz N linii cu câte 2 valori: pozi ³i sensi separate printr-un spaµiu,
pozi este un num r natural care reprezint coordonata la care se a furnica i la momentul iniµial,
iar sensi este un caracter din mulµimea {'S ', 'D'} ce arat sensul de deplasare iniµial pe care îl
are furnica i (S pentru stânga ³i D pentru dreapta).
Date de ie³ire
Fi³ierul de ie³ire furnici.out va conµine un singur num r care reprezint timpul la care a c zut
ultima furnic .
Restricµii ³i preciz ri
a 1 $ L $ 10 000 000
a 0 $ N $ 100 000
a 0 & pozi & L
CAPITOLUL 29. ONI 2011 619
Exemple:
furnici.in furnici.out Explicaµii
10 3 8 Bara are lungimea de 10 cm ³i pe bar vor plasate 3 furnici
4D la distanµele de 4, 8, 1 faµ de cap tul din stânga al barei ³i vor
8S avea urm toarele sensuri de deplasare: dreapta, stânga respectiv
1S stânga.
Primele dou furnici se vor întâlni dup 2 secunde în punctul
de coordonat 6 ³i î³i vor schimba sensul de deplasare.
Dup schimbarea de sens a doua furnic va parcurge înc 4cm
c tre dreapta ³i va c dea, în timp ce prima furnic dup schim-
barea de sens va parcurge înc 6 cm c tre stânga, pân la c dere.
În acest timp a treia furnic a c zut de pe bara dup 1 secund .
Pe bar nu vor mai furnici dup 8 secunde.
Soluµia 1: 20 puncte
Se memoreaz într-un vector de lungime L (lungimea barei metalice) pe poziµia k direcµia
în care se deplaseaz furnica ce se aa pe bara la punctul de coordonata k . Apoi se simuleaz
deplas rile cu pasul o unitate de timp pana când tot vectorul devine nul. Rezultatul este numarul
de pa³i. Pentru a evita ciocnirile în coordonate raµionale este sucient s se observe c cioncirile în
aceste coordonate sunt de forma k 0.5. Lungimea vectorului se dubleaz ³i direcµia de deplasare
a furnicilor care se a la coordonata k va salvat pe poziµia 2 k . Rezultatul este num rul de
pa³i / 2.
Complexitate : O(L*timpul_de_c dere_al_ultimei_furnici)
Soluµia 2: 50-60 puncte
Se observ c dac sort m furnicile cresc tor dup coordonata la care se a iniµial pe bar ,
furnica aat pe poziµia k în vectorul sortat va r mâne pe poziµia k tot timpul simul rii. (cu alte
cuvinte: dac are x furnici în stânga ³i y în dreapta, x ³i y r mân constante. Furnicile care cad
se consider prezente ³i ele).
În vectorul de furnici sortat memor m ca valoare real coordonata la care se a ecare furnic .
Parcurgem vectorul ³i calcul m timpul maxim în care furnicile se pot deplasa f r s se ciocneasc ,
La o nou parcurgere actualiz m coordonatele ³i schimb m sensurile la eventualele ciocniri (cel
puµin una).
CAPITOLUL 29. ONI 2011 620
Se observ c dac la pasul curent nu este nici o furnic orientat spre exteriorul barei, la pasul
viitor cel puµin una va orientat spre exterior ³i o scoatem din calcul µinând cont de timpul care
s-a scurs pân aceasta a c zut. Repet m pân când bara se elibereaz . Rezultatul este maximul
dintre ace³ti timpi.
2
Complexitate : O N
Soluµie 3: 100 puncte
Trebuie s se observe urm torul lucru :
În desen sunt dou furnici în punctele A ³i B care se deplaseaz în dreapta respectiv în stânga.
Deplasarea furnicii A : L©2 L©2 Y L Y
Deplasarea furnicii B : L©2 L©2 X L X
Se observ c dup L secunde furnicile sunt în acela³i loc ca la început dar cu sensuri de
deplasare inversate. S consideram scenariul în care furnicile trec una prin alta atunci când se
intalnesc:
Dup L secunde furnica A se va aa în punctul B iar furnica B în punctul A. Dac nu µinem
cont de notarea furnicilor (fapt care nu conteaz ) suntem în acela³i caz ca în regulile din enunµ
dup L secunde.
Aceasta proprietate este adevarat doar în cazul in care furnicile au aceea³i vitez (1cm/s
specicat în enunµ).
Proprietatea este adevarat ³i pentru N furnici.
Deci problema cere s se calculeze maximul dintre distanµele pe care le au de parcurs furnicile
neµinand cont de ciocnirile dintre ele.
Complexitate O N
33 }
34
35 printf("%d\n", rez);
36 return 0;
37 }
ONI 2010
30.1 cern
Problema 1 - cern 100 de puncte
CERN este un acronim folosit pentru a desemna Laboratorul Eu-
ropean pentru Fizica Particulelor Elementare. Acronimul s-a p strat
de la vechea denumire în limba francez , ³i anume Conseil Européen
pour la Recherche Nucléaire. Acesta este cel mai mare laborator de
cercetare a particulelor elementare din lume, situat în suburbia nord-
vestic a Genevei, chiar pe graniµa dintre Elveµia ³i Franµa. Funcµia
primar a complexului CERN este de a furniza acceleratoare de par-
ticule elementare ³i alte tipuri de infrastructuri necesare zicii parti-
culelor de energii înalte.
Acceleratorul de particule CERN este dispus sub forma a 3 cercuri cu aceea³i raz , tangente
exterioare dou câte dou , numerotate pe gur cu 1, 2, 3. Traiectoria unei particule elementare
porne³te din unul din punctele marcate pe gur cu A, B, C, D, E, F ³i se deplaseaz cu vitez
constant de 10/unitatea de timp numai pe circumferinµa cercurilor.
La trecerea printr-un punct de tangenµ dintre dou cercuri particula î³i schimb atât sensul
de deplasare, cât ³i cercul pe care se deplaseaz .
Astfel, dac sensul de deplasare a fost la un moment dat trigonometric,
la trecerea printr-un punct de tangenµ devine invers trigonometric ³i dac
sensul de deplasare a fost invers trigonometric, la trecerea printr-un punct
de tangenµ devine trigonometric.
Cerinµe
o
tiind c cercurile ce formeaz acceleratorul sunt marcate din grad în grad începând cu 0 , în
sens trigonometric (a³a cum se indic în gura al turat ), s se scrie un program, care, cunoscând
punctul iniµial ³i sensul de deplasare al unei particule, s determine poziµia particulei în accelerator
dup un num r dat de unit µi de timp.
Date de intrare
Prima linie a ³ierului de intrare cern.in conµine un caracter p ce indic punctul de plecare al
particulei.
A doua linie a ³ierului de intrare conµine dou numere întregi s ³i t, separate printr-un spaµiu,
ce indic sensul de deplasare (1 pentru sens trigonometric ³i -1 pentru sens invers trigonometric),
respectiv num rul de unit µi de timp cât dureaz deplasarea.
Date de ie³ire
Pe prima linie a ³ierului de ie³ire cern.out se vor scrie dou numere naturale g ³i c, se-
parate printr-un spaµiu, ce reprezint num rul de grade, în sens trigonometric, respectiv cercul,
corespunz toare poziµiei nale unde se va g si particula dup trecerea celor t unit µi de timp.
Restricµii ³i preciz ri
622
CAPITOLUL 30. ONI 2010 623
a p " {'A','B','C','D','E','F'}
a s " {-1, 1}
a 0 & t & 1.000.000.000
a 0 & g & 359
a c " {1, 2, 3}
a pentru toate seturile de date de intrare, poziµia nal a particulei nu coincide cu unul dintre
punctele de tangenµ dintre cercuri.
Exemple:
cern.in cern.out Explicaµii
A 200 3 Particula pleac din punctul A în sens trigonometric ³i are traseul:
o
1 320 a 180 pe cercul 1 în sens trigonometric
o
a 60 pe cercul 2 în sens invers trigonometric
o
a 80 pe cercul 3 în sens trigonometric
o
Poziµia nal este la 200 pe cercul 3
Timp maxim de executare/test: 0.1 secunde
Memorie: total 2 MB din care pentru stiv 1 MB
Dimensiune maxim a sursei: 20 KB
Deoarece toate cercurile au aceea³i raz , triunghiul format cu centrele celor 3 cercuri este
o
echilateral ³i va avea în consecinµ toate unghiurile de 60 . În felul acesta punctele de plecare ale
particulei sunt a³ezate dup cum urmeaz :
o
a 'A' - 0 pe cercul 1
o
a 'B' - 60 pe cercul 1
o
a 'C' - 120 pe cercul 2
o
a 'D' - 180 pe cercul 2
o
a 'E' - 240 pe cercul 3
o
a 'F' - 300 pe cercul 3
Urm toarea observaµie legat de rezolvarea problemei este c dup
o
un num r de 6π unit µi de timp (1080 ) particula va trece din nou prin
punctul de plecare, indiferent care este acesta. Problema nu necesit tipuri de date structurate
îns presupune o analiza atent a tuturor situaµiilor în care apar treceri de la un cerc la altul ³i
o o
respectiv în care se fac treceri de la 360 la 0 în concordanµ cu sensul de deplasare.
Aceste situaµii sunt:
1. cercul 1 tangenµ cu cercurile 2 ³i 3
2. cercul 2 tangenµ cu cercurile 3 ³i 1
3. cercul 3 tangenµ cu cercurile 1 ³i 2
o
4. trecerea prin 360 pentru cercurile 1 ³i 3
Se analizeaz toate aceste situaµii ³i se stabile³te modul de trecere de la un cerc la altul µinând
cont desigur ³i de sensul de deplasare al particulei. Problema poate abordat iterativ, recursiv
sau cel mai interesant numai prin tratarea punctelor de tangenµ (soluµia cea mai rapid , ce nu
necesit instrucµiuni repetitive ci numai instrucµiuni de decizie).
7 ofstream fo("cern.out");
8
9 long t;
10 int g,s,cerc;
11 char p;
12
13 int main()
14 { fi>>p>>s>>t;
15 t=t%1080;
16
17 switch(p)
18 { case ’A’:
19 if (s==1)
20 if(t<180) fo<<t<<" 1\n", t=0; else t=t-180,cerc=2,p=’G’;
21 else
22 if(t<120) fo<<360-t<<" 1\n",t=0; else t=t-120,cerc=3,p=’I’;
23 break;
24 case ’B’:
25 if (s==1)
26 if(t<120) fo<<t+60<<" 1\n", t=0; else t=t-120,cerc=2,p=’G’;
27 else
28 if(t<180) fo<<(360-(t-60))%360<<" 1\n",t=0;
29 else t=t-180,cerc=3,p=’I’;
30 break;
31 case ’C’:
32 if (s==1)
33 if(t<180) fo<<t+120<<" 2\n", t=0; else t=t-180,cerc=3,p=’H’;
34 else
35 if(t<120) fo<<120-t<<" 2\n",t=0; else t=t-120,cerc=1,p=’G’;
36 break;
37 case ’D’:
38 if (s==1)
39 if(t<120) fo<<t+180<<" 2\n", t=0; else t=t-120,cerc=3,p=’H’;
40 else
41 if(t<180) fo<<180-t<<" 2\n",t=0; else t=t-180,cerc=1,p=’G’;
42 break;
43 case ’E’:
44 if (s==1)
45 if(t<180) fo<<(240+t)%360<<" 3\n", t=0;
46 else t=t-180,cerc=1,p=’I’;
47 else
48 if(t<120) fo<<240-t<<" 3\n",t=0; else t=t-120,cerc=2,p=’H’;
49 break;
50
51 case ’F’:
52 if (s==1)
53 if(t<120) fo<<(300+t)%360<<" 3\n", t=0;
54 else t=t-120,cerc=1,p=’I’;
55 else
56 if(t<180) fo<<300-t<<" 3\n",t=0; else t=t-180,cerc=2,p=’H’;
57 break;
58 }
59
60 s=-s;
61
62 while(t)
63 { switch(p)
64 { case ’G’:
65 if(s==1)
66 if(cerc==1)
67 if (t>60)t=t-60,p=’I’; else fo<<180+t<<" 1\n",t=0;
68 else
69 if (t>300) t=t-300,p=’H’; else fo<<t<<" 2\n",t=0;
70 else
71 if(cerc==1)
72 if(t>300) t=t-300,p=’I’;else fo<<(540-t)%360<<" 1\n",t=0;
73 else
74 if(t>60) t=t-60,p=’H’; else fo<<360-t<<" 2\n",t=0;
75
76 cerc=3;
77 break;
78 case ’H’:
79 if(s==1)
80 if(cerc==3)
81 if (t>300)t=t-300,p=’I’; else fo<<120+t<<" 3\n",t=0;
82 else
CAPITOLUL 30. ONI 2010 625
42 pozitie=0;
43 sens=1;
44 cerc=2;
45 }
46 break;
47 case 0 : if (cerc==2)
48 {
49 pozitie=180;
50 sens=sens*(-1);
51 cerc=1;
52 }
53 // trecerea prin 0 pentru cercurile 1 si 3
54 if (cerc==1&&sens==-1) pozitie=360;
55 if (cerc==3&&sens==-1) pozitie=360;
56 break;
57 case 300 : if (cerc==2)
58 {
59 pozitie=120;
60 sens=sens*(-1);
61 cerc=3;
62 }
63 break;
64 case 120 : if (cerc==3)
65 {
66 pozitie=300;
67 sens=sens*(-1);
68 cerc=2;
69 }
70 break;
71 case 60 : if (cerc==3)
72 {
73 pozitie=240;
74 sens=sens*(-1);
75 cerc=1;
76 }
77 break;
78 case 240 : if (cerc==1)
79 {
80 pozitie=60;
81 sens=sens*(-1);
82 cerc=3;
83 }
84 break;
85
86 case 360 : if (cerc==2&&sens==1)
87 {
88 pozitie=180;
89 cerc=1;
90 sens=sens*(-1);
91 }
92 // situatia cand trecem prin 360 grade
93 // pe cercurile 1 si 3
94 if (cerc==1&&sens==1) pozitie=0;
95 if (cerc==3&&sens==1) pozitie=0;
96 break;
97 }
98 pozitie=pozitie+sens;
99 }
100
101 g<<pozitie%360<<" "<<cerc<<"\n";
102 f.close();
103 g.close();
104
105 return 0;
106 }
30.2 cmmmc
Problema 2 - cmmmc 100 de puncte
CAPITOLUL 30. ONI 2010 627
Cerinµe
S se determine pentru ecare dintre numerele ni (i = 1, 2, ..., k ):
a) câte perechi ordonate au cel mai mic multiplu comun egal cu ni .
b) dintre acestea, perechea ordonat care are suma minim .
Date de intrare
Prima linie a ³ierului cmmmc.in conµine un num r natural k . Urm toarele k linii din acest
³ier vor conµine câte un num r natural; linia i 1 va conµine num rul ni (i 1, 2, ..., k ) .
Date de ie³ire
Fi³ierul cmmmc.out va conµine k linii. Pe ecare dintre acestea se vor aa trei numere. Cele
trei numere de pe linia i vor reprezenta:
- primul, num rul de perechi ordonate care au cel mai mic multiplu comun egal cu ni ;
- urm toarele dou , numerele care alc tuiesc perechea ordonat care are cel mai mic multiplu
comun egal cu ni ³i a c ror sum este minim , a³ate în ordine cresc toare.
Restricµii ³i preciz ri
a 1 & k & 100
a 1 & ni & 2 000 000 000
a Pentru 20% dintre teste, k & 100 ³i ni & 1 000
a Fiecare dintre cele k linii ale ³ierului cmmmc.out trebuie s conµin exact trei numere
separate prin câte un spaµiu; în caz contrar, soluµia se consider gre³it ³i se obµin 0 puncte
pentru testul respectiv. Rezolvarea corect a cerinµei a) valoreaz 40% din punctajul unui test iar
rezolvarea corect a cerinµei b) 60%.
Exemple:
cmmmc.in cmmmc.out Explicaµii
2 525 Exist cinci perechi distincte care au cel mai mic multiplu comun
10 2 1 11 egal cu 10: (1,10), (2,10), (5,10), (2,5) (10,10). Dintre acestea
11 perechea cu cea mai mic sum este (2,5).
Pentru n=11 exist dou perechi ordonate care au cel mai mic
multiplu comun 11: (1,11), (11,11). Dintre acestea perechea cu
cea mai mic sum este (1,11).
Timp maxim de executare/test: 0.2 secunde
Memorie: total 2 MB din care pentru stiv 1 MB
Dimensiune maxim a sursei: 10 KB
Observ m, c am num rat perechile formate din numere distincte de dou ori ³i perechea n, n
o singur dat , a³a c ad ug m unu ³i împ rµim la doi, pentru a r spunde la subpunctul a).
Pentru a rezolva subpunctul b), observ m c pentru a obµine suma minim , trebuie s consi-
der m ecare pi la puterea qi într-unul din numere, iar la puterea 0 în cel lalt num r. Încerc m
toate cele 2k perechi ce se pot forma astfel ³i alegem perechea cu suma minim .
Pentru a genera aceste perechi, iter m cu o variabil de la 0 la 2k 1, pe care o convertim în
baza doi. Dac cifra i în baza doi este egal cu 0, vom considera c pi apare în primul num r la
puterea qi ³i în al doilea num r la puterea 0, iar dac cifra i este egal cu 1, pi va ap rea în primul
num r la puterea 0 ³i în al doilea num r la puterea qi .
Pentru a implementa un algoritm cât mai rapid pentru descompunerea în factori primi, se reco-
mand generarea numerelor prime folosind Ciurul lui Eratostene. Aceast abordare implementat
cu grij duce la obµinerea punctajului maxim.
O alt soluµie posibil este determinarea tuturor divizorilor lui n ³i vericarea pentru ecare
pereche de divizori, dac are cel mai mare divizor comun egal cu n. Pentru a determina divizorii
unui num r este de ajuns s veric m divizorii pân la radicalul num rului ³i când am g sit
divizorul d, acesta va implica c am g sit ³i divizorul n©d. Cazul p tratelor perfecte trebuie tratat
separat.
Aceast abordare obµine 60 de puncte.
122 return 0;
123 }
71 VI primes;
72 VLL compacted;
73
74 void Erast()
75 {
76 int gyok = sqrt(double(MAX));
77 isPrime.RS(gyok + 1, true);
78 FOR(i, 2, gyok >> 1)
79 if (isPrime[i])
80 for(int j=i+i; j<=gyok; j+=i) isPrime[j]=false;
81 FOR(i, 2, gyok)
82 if (isPrime[i]) primes.PB(i);
83 }
84
85 void BuildFactors()
86 {
87 factors.CL, compacted.CL;
88 LL aux = n;
89 int iPrime = 0, gyok = sqrt(double(n));
90 while (iPrime < primes.SZ && aux > 1)
91 {
92 int exponent = 0, prime = primes[iPrime];
93 if (prime > gyok) break;
94 while (!(aux % prime))
95 {
96 ++exponent;
97 aux /= prime;
98 }
99 if (exponent) factors.PB(MP(prime, exponent));
100 if (aux < isPrime.SZ && isPrime[aux]) break;
101 ++iPrime;
102 }
103 if (aux > 1) factors.PB(MP(aux, 1));
104 FORN(i, factors.SZ)
105 {
106 LL factor = factors[i].X;
107 FOR(j, 2, factors[i].Y) factor *= factors[i].X;
108 compacted.PB(factor);
109 }
110 }
111
112 PLL Solve()
113 {
114 nSol = 1;
115 FORN(i, factors.SZ) nSol *= (2*factors[i].Y + 1);
116 nSol = nSol / 2 + 1;
117 PLL ans;
118 LL minSum = (LL)MAX + MAX + 1;
119 FORN(i, 1 << factors.SZ)
120 {
121 LL x = 1, y = 1;
122 FORN(j, factors.SZ)
123 if (i & (1 << j)) x *= compacted[j];
124 else y *= compacted[j];
125 if (minSum > x + y)
126 {
127 minSum = x + y;
128 ans = MP(x, y);
129 }
130 }
131 if (ans.X > ans.Y) swap(ans.X, ans.Y);
132 return ans;
133 }
134
135 int main()
136 {
137 Erast();
138
139 fin >> test;
140 FORN(t, test)
141 {
142 fin >> n;
143 BuildFactors();
144 PII sol = Solve();
145 fout << nSol << " " << sol.X << " " << sol.Y << endl;
146 }
CAPITOLUL 30. ONI 2010 632
147 fin.close();
148 fout.close();
149
150 return 0;
151 }
30.3 simetric
Problema 3 - simetric 100 de puncte
O matrice p tratic A care are P linii ³i P coloane este simetric dac ³i numai dac pentru
orice indici i ³i j între 1 ³i P avem c Ai,j Aj,i . Astfel, matricea din gura 1 este simetric , iar
cea din gura 2 nu este, deoarece exist cel puµin o pereche de indici (de exemplu i 2 ³i j 3),
pentru care Ai,j este diferit de Aj,i .
Exemple:
simetric.in simetric.out Explicaµii
4 5 20 Exist 20 de submatrici simetrice de latur 1 (ecare celul este
5 1 3 6 9 3 considerat submatrice), 3 submatrici simetrice de latur 2 ³i 2
1 6 2 8 9 2 de latur 3. Submatricile simetrice de latur 3 sunt:
3 2 7 5 1
9 8 5 3 8 5 1 3 6 2 8
1 6 2 2 7 5
3 2 7 8 5 3
CAPITOLUL 30. ONI 2010 633
13 return 0;
14 return 1;
15 }
16
17 int main()
18 {
19 freopen("simetric.in","r",stdin);
20 freopen("simetric.out","w",stdout);
21
22 memset( nr, 0, sizeof( nr ));
23
24 scanf("%d %d", &N, &M);
25
26 for( int i = 1; i <= N; ++i)
27 for( int j = 1; j <= M; ++j)
28 scanf("%d", &V[ i ][ j ]);
29 int optim = 1;
30 for( int i = 1; i <= N; ++i)
31 for( int j = 1; j <= M; ++j)
32 for( int l = 1; l + i - 1 <= N && l + j - 1 <= M; ++l)
33 if( simetric( i, j, l) )
34 {nr[ l ]++; if( l > optim) optim = l;}
35 else break;
36 for( int i = 1; i <= optim; i++)
37 printf("%d\n", nr[i]);
38
39 return 0;
40 }
45 }
30.4 pesti
Problema 4 - pesti 100 de puncte
Nicu³or trebuie s aib grij , pe perioada vacanµei, de cei n pe³ti aaµi în acvariile de la Muzeul
de ³tiinµe ale Naturii din Constanµa. Pe³tii sunt numerotaµi cu numerele distincte de la 1 la n ³i
sunt asezaµi în n acvarii identice, câte un pe³ti³or în câte un acvariu. Iniµial, pe³ti³orul numerotat
cu num rul 1 st în acvariul etichetat cu num rul 1, pe³ti³orul numerotat cu num rul 2 st în
acvariul etichetat cu num rul 2, ..., pe³ti³orul numerotat cu num rul n st în acvariul etichetat
cu num rul n. Cele n acvarii sunt a³ezate unul lâng altul, în ordinea cresc toare a etichetelor.
Cele n acvarii formeaz o grup .
Pentru ca pe³tii s se dezvolte frumos ³i s nu se plictiseasc , ei trebuie rea³ezaµi zilnic în
acvarii.
Astfel, în prima zi, Nicu³or formeaz dou subgrupe de acvarii.
În subgrupa din stânga a³eaz , în ordine, pe³tii din acvariile aate pe poziµii impare în grup
(primul acvariu din grup , al treilea, al cincilea etc).
În subgrupa din dreapta
a³eaz , în ordine, pe³tii din
acvariile aate pe poziµii pare
în grup (al doilea acvariu din
grup , al patrulea, al ³aselea
etc).
CAPITOLUL 30. ONI 2010 636
Cerinµe
Scrieµi un program care s citeasc dou numere naturale nenule n ³i x, n reprezentând num rul
de pe³ti³ori ³i x reprezentând num rul unui pe³ti³or, ³i care s determine:
- num rul z de zile în care Nicu³or î³i desf ³oar activitatea;
- eticheta y a acvariului în care se g se³te pe³ti³orul cu num rul x la încheierea activit µii lui
Nicu³or;
- prima zi, u, în care în pe³ti³orul cu num rul x a ajuns în acvariul etichetat cu num rul y ³i
nu a mai fost mutat.
Date de intrare
Fi³ierul de intrare pesti.in conµine o singur linie pe care sunt scrise cele dou numere naturale
n ³i x, separate printr-un spaµiu.
Date de ie³ire
Fi³ierul de ie³ire pesti.out conµine o singur linie pe care sunt scrise cele trei numere naturale
z , y ³i u (în aceast ordine), separate prin câte un spaµiu.
Restricµii ³i preciz ri
a 3 & n & 2 000 000 000;
a 1 & x & n.
a Dac un pe³te nu este mutat deloc atunci r spunsul la a treia cerinµ este 1.
a Evaluare: dac se r spunde corect la prima cerinµ se obµine 20% din punctaj. Dac se
r spunde corect la primele dou cerinµe se obµine 60% din punctaj. Dac se r spunde corect la
toate cele trei cerinµe se obµine 100% din punctaj.
Exemple:
pesti.in pesti.out Explicaµii
96 372 Nicu³or î³i desf ³oar activitatea timp de z 3 zile. Pe³ti³orul cu
num rul x 6 se va aa în ziua a treia în acvariul cu num rul y 7
³i ajunge în acest acvariu în ziua u 2.
Timp maxim de executare/test: 1.0 secunde
Memorie: total 64 MB din care pentru stiv 32 MB
Dimensiune maxim a sursei: 10 KB
Cerinµa a) num rul z de zile pân la încheierea activit µii desf µurat de Nicu³or este cel mai
mare num r natural care veric inecuaµia 2 $ n, v ' 3.
z
Dac , la un moment dat pe³tele se a în acvariul x în cadrul unei grupe ce conµine acvariile
etichetate cu a, a 1, ..., b, pe o poziµie par în cadrul grupei, atunci el va ajunge în acvariul
a b©2 x a 1©2 din subgrupa din dreapta, iar dac se a pe o poziµie impar în cadrul
grupei, atunci el va ajunge în acvariul a x a©2 din subgrupa din stânga.
Cerinµa c) prima zi, u, în care în pe³ti³orul cu num rul x a ajuns în acvariul etichetat cu
num rul y ³i nu a mai fost mutat
Este sucient s utiliz m o singur variabil pe care s o actualiz m de ecare dat când
poziµia curent a pe³telui este diferit de poziµia anterioar .
Aceast abordare ruleaz în timp O log n ³i folose³te memorie O 1.
Aproximativ 60-70% din punctaj se poate obµine ³i prin simularea efectiv a mi³c rii pe³tilor.
Observ m c , pentru a genera poziµia pe³tilor dintr-o zi, avem nevoie doar de poziµia acestora din
ziua anterioar , ³i m rimea grupelor din ziua anterioar . Aceast observaµie duce la ideea de a
reµine dou matrici de câte dou linii a ³i groupSize, în care o linie va codica starea pentru ziua
curent , iar cealalt pentru ziua anterioar . Menµion m c , num rul de elemente dintr-o linie a
matricii groupSize se modic dinamic de la o zi la alta, în schimb o linie din matricea a are
întotdeauna n elemente. Aceast abordare ruleaz în timp O n log n ³i folose³te memorie O n.
Dac se reµin st rile pentru ecare din zile, memoria folosit se modic la O n log n ³i se pot
obµine 40-50 puncte.
46 f.close();
47 g.close();
48 return 0;
49 }
30.5 plaja
Problema 5 - plaja 100 de puncte
Prim ria ora³ului Constanµa reamenajeaz plaja din staµiunea Mamaia. Aceasta este repre-
zentat ca o zon dreptunghiular cu l µimea de a unit µi ³i lungimea de b unit µi. Pe plaj
sunt trasate linii paralele cu laturile dreptunghiului astfel încât s formeze p trate cu latura de o
unitate, numite zone.
Pe plaj se vor pune obiecte: umbrele ³i prosoape. Se consider c dac un obiect intr în
interiorul unei zone, o ocup în întregime. Se poziµioneaz u umbrele de soare. într-o zon se
poate a³eza cel mult o umbrel .
N turi³ti vin ³i î³i a³eaz prosoapele pe plaj . Un prosop are form dreptunghiular ³i va
a³ezat paralel cu laturile dreptunghiului. Turi³tii î³i pot a³eza prosoapele pe zone libere sau
peste prosoape deja a³ezate. Un turist nu î³i poate a³eza îns prosopul pe plaj dac suprafaµa
acoperit de acesta include cel puµin o zon în care se a o umbrel .
M localnici au suprafeµe favorite pentru a³ezarea prosoapelor. O suprafaµ favorit are forma
unui dreptunghi cu laturile paralele cu laturile dreptunghiului care marcheaz plaja. Dup ce
turi³tii termin a³ezarea prosoapelor, localnicii veric dac zonele din suprafaµa favorit sunt
libere (neacoperite de prosoape a³ezate de turi³ti sau de umbrele).
Cerinµe
Scrieµi un program care s determine:
a num rul de turi³ti care au reu³it s î³i a³eze prosoapele pe plaj ;
a num rul de localnici ale c ror zone favorite sunt libere.
Date de intrare
Fi³ierul de intrare plaja.in conµine pe prima linie trei numere naturale, separate prin câte un
spaµiu, a, b ³i u, având semnicaµia din enunµ.
Fiecare din urm toarele u linii conµine o pereche de numere naturale x y , reprezentând o zon
în care se g se³te o umbrel .
Urm toarea linie din ³ier conµine un num r natural N , reprezentând num rul de turi³ti.
Urm toarele N linii descriu prosoapele turi³tilor. Fiecare linie conµine 4 numere naturale x1
y1 x2 y2 , ce reprezint colµurile unui prosop. Linia urm toare conµine o singur valoare, M ,
reprezentând num rul de localnici.
¬ ¬ ¬ ¬
Pe urm toarele M linii se a câte 4 numere, separate prin câte un spaµiu, x1 y1 x2 y2 , ce
reprezint colµurile unei suprafeµe favorite.
Date de ie³ire
Fi³ierul de ie³ire plaja.out conµine pe prima linie dou numere naturale separate printr-un
spaµiu. Primul num r reprezint num rul de turi³ti care ³i-au a³ezat prosoapele pe plaj , iar cel
de-al doilea num r reprezint num rul de localnici ale c ror zone favorite sunt libere.
Restricµii ³i preciz ri
a Colµul din stânga sus al zonei dreptunghiulare are coordonatele (1,1)
a 3 & a, b & 2 000
a 0 & u & 100
a 3 & m, n & 100 000
a Un prosop descris de x1 , y1 , x2 , y2 va avea 1 & x1 & x2 & a ³i 1 & y1 & y2 & b
O suprafaµ favorit descris de x1 , y1 , x2 , y2 va avea 1 & x1 & x2 & a ³i 1 & y1 & y2 & b
¬ ¬ ¬ ¬ ¬ ¬ ¬ ¬
a
CAPITOLUL 30. ONI 2010 639
a Pentru lucrul în C/C++, se recomand citirea folosind scanf sau fscanf, deoarece sunt mai
rapide decât cin.
a Evaluare: dac se r spunde corect la prima cerinµ se obµine 40% din punctaj. Dac se
r spunde corect la ambele cerinµe se obµine 100% din punctaj.
Exemple:
plaja.in plaja.out Explicaµii
12 13 1 32 Ultimul turist nu î³i poate a³eza prosopul.
6 11
4
3477
5688
9 2 10 3
5 10 8 12
3
1 8 3 13
10 3 12 4
2 10 5 12
Zona favorit al celui de-al 2-lea localnic nu este liber .
Timp maxim de executare/test: 1.0 secunde
Memorie: total 64 MB din care pentru stiv 1 MB
Dimensiune maxim a sursei: 10 KB
Prima cerinµ cere determinarea num rului de dreptunghiuri care nu conµin în interiorul lor
nicio zon în care se g se³te o umbrel .
Rezolvarea pentru acest pas are complexitate O N U , testând pentru ecare dreptunghi din
cele N dac exist o umbrel pe care s o includ . Testarea se va face parcurgând efectiv lista de
umbrele. Aceast abordare garanteaz obµinerea a 40 de puncte.
Pentru a rezolva ecient ³i cea de-a doua cerinµ , proced m
în felul urm tor: atunci când avem un dreptunghi de coordonate
x1 y1 x2 y2 pe care trebuie s îl a³ez m pe plaj , increment m cu
1 valoarea din celulele x1 , y1 si x2 1, y2 1 ³i sc dem cu 1
valoarea din celulele x1 , y2 1 ³i x2 1, y1 , dup cum se observ
în desenul al turat.
Atunci când facem suma elementelor pe orice submatrice de
colµuri 1, 1 ³i i, j , observ m c se va aduna o unitate în orice
celul care aparµine dreptunghiului considerat. Astfel, de ecare dat când avem un dreptunghi
care trebuie a³ezat, adun m sau sc dem 1 în celulele menµionate. Dup amplasarea tuturor
celor N dreptunghiuri, calcul m suma Si,j pe orice submatrice de colµuri 1, 1 ³i i, j , folosind
urm toarea relaµie:
Si,j Si1,j Si,j 1 Si1,j 1 Vi,j , unde Vi,j este valoarea de pe poziµia i, j .
Dac Si,j % 0, atunci i, j este acoperit de cel puµin un prosop. Facem din nou sume parµiale
pe aceast matrice nou obµinut , în care consider m Si,j 1 dac ³i numai dac i, j este acoperit
¬ ¬ ¬ ¬
de cel puµin un prosop. Pentru a testa în O 1 dac o suprafaµ x1 , y1 , x2 , y2 din cele M este
în întregime liber , calcul m suma Sx¬2 ,y2¬ Sx¬2 ,y1¬ 1 Sx¬1 1,y2¬ Sx¬1 1,y1¬ 1 . Dac aceast sum
este 0, înseamn c suprafaµa este liber , iar în caz contrar va exista cel puµin o zon în înteriorul
suprafeµei care este acoperit .
Complexitatea nal este O N U A B M N .
CAPITOLUL 30. ONI 2010 640
30.6 tango
Problema 6 - tango 100 de puncte
CAPITOLUL 30. ONI 2010 641
Un tango este format din fraze muzicale, ecare dintre acestea având 8 timpi muzicali. Timpii
muzicali au aceea³i durat .
La fel de important ca melodia unui tango este ³i dansul asociat ei. Mi³c rile efectuate în
timpul dansului se numesc guri. Succesiunea de guri efectuate în timpul dansului formeaz o
coregrae. Dou coregrai se consider diferite dac succesiunea gurilor care le alc tuiesc este
diferit . O coregrae frumoas asociat unui tango are particularitatea urm toare: atunci când
se termin o fraz muzical trebuie s se termine ³i o gur .
D ³i S se preg tesc pentru primul lor concurs de dans ³i ei lucreaza momentan la coregraa
de tango. Chiar dac va primul lor concurs, ei deja ³tiu n guri de dans ³i au calculat pentru
ecare dintre aceste guri câµi timpi muzicali dureaz . Fiindc le place foarte mult s danseze
împreun , ei vor s preg teasc o coregrae frumoas pentru o pies care dureaz exact k timpi
muzicali.
Cerinµe
Determinaµi num rul coregrailor frumoase modulo 999983 pentru o pies , care: dureaza exact
k timpi muzicali, respect condiµiile de mai sus ³i sunt formate doar din cele n guri cunoscute
de D ³i S (mai este prea puµin timp pân la concurs, ca ei s inveµe ³i guri noi).
Date de intrare
Pe prima linie a ³ierului de intrare tango.in se a numerele naturale nenule n ³i k , separate
printr-un singur spaµiu. Pe a doua linie se a exact n numere separate prin câte un spaµiu,
reprezintând lungimile gurilor.
Date de ie³ire
În ³ierul de ie³ire tango.out se va a³a num rul de coregrai posibile modulo 999983.
Restricµii ³i preciz ri
a n & 100 000
a k & 2 000 000 000
a k va întotdeauna divizibil cu 8
a 1 & lungimea unei guri & 8
a pentru 30% din teste va exista o singur gur de o anumit lungime
a pentru 50% din teste n & 30
a pentru 70% din teste lungimile gurilor vor numai valori din mulµimea {2, 4, 6, 8}
a Prin a modulo b se înµelege restul împ rµirii lui a la b.
Exemple:
tango.in tango.out Explicaµii
3 16 66049 Sunt 16 timpi muzicali deci o coregrae frumoas se va dansa pe
118 16 / 8 = 2 fraze muzicale.
Dac not m gurile cu litere, avem gura A de lungime 1, gura B
de lungime 1 ³i gura C de lungime 8. Prima fraz muzical poate
alc tuit din orice secvenµ alc tuit din opt buc µi de A sau B,
deci în total 28 = 256 posibilit µi. înc o posibilitate de alc tuire
a primei fraze este printr-un singur C. Rezult un total de 257
posibilit µi. Pentru a doua fraz avem tot atâtea posibilit µi, deci
în total exist 257 * 257 = 66049 coregrai frumoase posibile.
Cum 66049 modulo 999983 = 66049, se obµine rezultatul 66049.
Primul pas va s calcul m num rul de posibilit µi pentru a dansa guri care acoper exact
o fraz muzical . Trat m cazul în care gurile au lungime par ³i acestea sunt unice (acest caz
apare în 20% din teste). Vom încerca s descompunem o fraz în toate modurile posibile în guri.
Avem doar urm toarele posibilit µi:
1)8=2+2+2+2
2)8=2+2+4
3)8=2+4+2
4)8=2+6
5)8=4+2+2
6)8=4+4
7)8=6+2
8)8=8
În funcµie de ce guri avem disponibile, o parte din aceste posibilit µi pot disp rea. De exemplu
dac avem doar 2 ³i 6 atunci putem forma doar variantele 1), 4) ³i 7).
Trat m acum cazul în care avem doar timpi pari, dar nu sunt unici. S exemplic m c avem
2 guri de lungime 2 ³i 3 de lungime 6. Atunci pentru cazul 1) vor 24 moduri de a dansat
(pentru ecare gur de lungime 2 avem 2 posibilit µi), iar pentru cazurile 4) ³i 7) vor 6 moduri
de a dansate (2 * 3).
S extindem la cazul în care gurile au ³i timpi impari. în acest caz sunt mai multe moduri
de a descompune o fraz în guri:
8=1+1+1+1+1+1+1+1
8=1+1+1+1+1+1+2+0
...........................
8 = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8
Cum aceste cazuri sunt prea multe pentru a calculate de mân , se pot folosi 8 foruri imbricate
pentru a selecta valorile pentru x1, x2, ..., x8 (de la 0 la 8) astfel încât x1 + x2 .... + x8 = 8.
Pentru a nu num ra o posibilitate de mai multe ori, trebuie avut grij s nu gener m cazuri de
forma 8 = 1 + 2 + 0 + 2 + 3 + 0 + 0, ci doar cazuri în care 0-urile sunt la coad (vezi soluµia
ocial ). Alte metode mai elegante pentru a genera num rul de posibilit µi sunt programarea
dinamic specic problemei rucsacului, sau metoda backtracking.
Al doilea pas este s calcul m num rul de moduri de a dansa întreg tangoul.
Pentru a aa aceast valoare, trebuie s calcul m num rul de posibilit µi de a dansa o fraz
muzical la puterea (k / 8). Pentru a obµine punctaj maxim, acest calcul trebuie f cut folosind
exponenµiere logaritmic .
95 }
ONI 2009
31.1 joc
Problema 1 - joc 100 de puncte
Pentru un concurs de design de jocuri, Gigel vrea s construiasc un joc. La joc particip n
concurenµi numerotaµi de la 1 la n. Fiecare concurent are la dispoziµie câte un ³ir de m înc peri,
numerotate de la 1 la m. Scopul jocului este de a g si o comoar ascuns în una din aceste
înc peri. Fiecare înc pere conµine un cod, num r natural, e egal cu 0, e având cel puµin 2 cifre.
Ultima cifr indic num rul de etape de penalizare, adic num rul de etape în care concurentul nu
are voie s p r seasc înc perea. Num rul obµinut prin eliminarea ultimei cifre a codului indic
num rul înc perii în care se va deplasa acesta la urm toarea etap sau la expirarea penaliz rii.
Exist dou excepµii de la regula de denire a codului: num rul 9999 codic o înc pere conµinând
o comoar , iar num rul 0 o înc pere conµinând o capcan .
În etapa 1 ecare juc tor intr în înc perea 1 din ³irul s u de înc peri. În funcµie de codul
g sit în înc pere sunt posibile urm toarele situaµii:
- codul g sit este 9999 ceea ce înseamn c juc torul este câ³tig tor ³i jocul se încheie la nalul
acestei etape;
- codul g sit este 0 ceea ce duce la eliminarea sa din joc;
- pentru celelalte coduri, dup efectuarea etapelor de penalizare, juc torul efectueaz o depla-
sare în înc perea indicat de cod. De exemplu la întâlnirea codul 157, dup efectuarea celor 7
etape de penalizare juc torul se va deplasa în camera 15.
Trecerea de la o etap la alta se realizeaz simultan pentru toµi concurenµii.
Cerinµe
Fiind dat num rul n de concurenµi, num rul m de înc peri alocate ec rui concurent, ³i codu-
rile din cele n m înc peri s se determine câ³tig torul jocului, num rul înc perii în care a g sit
comoara, num rul de etape parcurse pân când câ³tig torul g se³te comoara precum ³i num rul
de concurenµi eliminaµi din joc pân la etapa respectiv (inclusiv).
Date de intrare
Prima linie a ³ierului de intrare joc.in conµine dou numere naturale n ³i m, separate printr-
un spaµiu, reprezentând num rul concurenµilor, respectiv num rul înc perilor.
Urm toarele n linii conµin câte m numere naturale, separate prin câte un spaµiu, reprezentând
codurile din ecare înc pere.
Date de ie³ire
Prima linie a ³ierului de ie³ire joc.out va conµine patru numere naturale separate prin câte
un spaµiu, reprezentând indicele câ³tig torului, num rul înc perii unde a g sit comoara, num rul
etapei în care a câ³tigat ³i respectiv num rul de concurenµi eliminaµi din joc.
Restricµii ³i preciz ri
a 1 & n & 400
a 1 & m & 900
a Pentru toate testele de intrare se garanteaz c exist exact un câ³tig tor.
645
CAPITOLUL 31. ONI 2009 646
Exemple:
joc.in joc.out Explicaµii
48 2571Câ³tig juc torul al 2-lea, dup 7 etape, iar înc perea
0 9999 41 50 61 70 80 30 în care a g sit comoara este înc perea 5. în cele 7
30 80 60 60 9999 21 40 50 etape a fost eliminat un singur concurent ³i anume
20 30 40 50 61 71 81 9999 primul concurent.
20 30 50 0 61 71 9999 41 Înc perile prin care trece juc torul câ³tig tor pân
la nal sunt:
1 3 6 2 8 5
Timp maxim de executare/test: 0.2 secunde
Memorie: total 2 MB din care pentru stiv 1 MB
Se citesc din ³ier numerele n (num rul de juc tori) ³i m (num rul de înc peri pentru ecare
concurent). Pentru ecare juc tor i (1 & i & n) se execut urm toarea secvenµ de pa³i:
- se cite³te în vectorul a ³irul s u de înc peri.
- se începe de la înc perea 1 (a1) ³i etapa 1
- pentru ecare înc pere la care a ajuns, se marcheaz înc perea ca ind vizitat , iar valoarea
din înc pere poate :
` 0 - juc torul este eliminat - se reµine într-un vector, pe poziµia i num rul etapei în care
a fost eliminat; se încheie analiza ³irului s u de înc peri
` 9999 - juc torul a câ³tigat; se compar num rul etapei cu un minim ³i se retine valoarea
minim , indicele juc torului ³i num rul înc perii în care a ajuns; se încheie analiza
³irului s u de înc peri
` o valoare nenul ³i < 9999; se calculeaz indicele j al înc perii în care urmeaz s se
catapulteze; sunt posibile dou cazuri:
t dac acest indice este egal cu înc perea în care a ajuns sau înc perea în care
urmeaz s ajung a mai fost vizitat , se încheie analiza ³irului de înc peri, deoarece
juc torul intr într-un ciclu innit de mut ri.
t indicele reprezint o înc pere nevizitat , se m re³te num rul etapei cu ultima cifr
a valorii codului ³i se reia vizitarea cu înc perea j .
Dup executarea secvenµei descrise pentru toµi juc torii, se num r câµi juc tori au fost pîn
în etapa în care a fost stabilit câ³tig torul (minimul calculat), inclusiv acea etapa ³i se scriu în
³ier numerele cerute.
22 }
23
24 etapa=1;
25 j=1;
26 viz[1]=1;
27 castigator=0;
28 while(!castigator&&t[i]!=-1)
29 {
30 x=a[j];
31 viz[j]=1;
32
33 if(x==0)
34 {
35 t[i]=-1;
36 v[i]=etapa;
37 }
38 else
39 if(x==9999)
40 {
41 if(etapa<e_min)
42 {
43 c_min=i;
44 e_min=etapa;
45 i_min=j;
46 }
47 castigator=1;
48 }
49 else
50 {
51 if(j==x/10) break;
52 j=x/10;
53 if(viz[j]==1)
54 break;
55 else
56 etapa=etapa+x%10+1;
57 }
58 }
59 }
60
61 nrp=0;
62 for(i=1;i<=n;i++)
63 if(t[i]==-1&&v[i]<=e_min)
64 nrp++;
65 g<<c_min<<" "<<i_min<<" "<<e_min<<" "<<nrp<<endl;
66 f.close();
67 g.close();
68 return 0;
69 }
31.2 perspic
Problema 2 - perspic 100 de puncte
Se consider o matrice p tratic cu N linii ³i N coloane ce conµine toate numerele naturale de
la 1 la N N . Asupra matricei se denesc trei tipuri de operaµii codicate astfel:
a C i j - interschimbarea coloanelor i ³i j ale matricei
a R i j - interschimbarea liniilor i ³i j ale matricei
a E i j x y - interschimbarea elementului de pe linia i ³i coloana j cu elementul de pe linia x
³i coloana y .
Asupra matricei se efectueaz un set de M astfel de operaµii.
Cerinµe
Se cere s se determine num rul minim de aplic ri complete ale acestui set de operaµii dup
care se ajunge din nou în starea iniµial . În cadrul setului operaµiile se efectueaz mereu în aceea³i
ordine ³i nu se poate s ri peste o operaµie. Deoarece num rul acesta poate foarte mare se cere
restul împ rµirii sale la 13007.
CAPITOLUL 31. ONI 2009 648
Date de intrare
Fi³ierul perspic.in conµine pe prima linie numerele naturale N ³i M , separate printr-un spaµiu,
reprezentând dimensiunea matricei ³i respectiv num rul de operaµii dintr-un set. Pe urm toarele
M linii se descriu operaµiile setului.
Date de ie³ire
Fi³ierul perspic.out va conµine restul împ rµirii la 13007 al num rului minim determinat.
Restricµii ³i preciz ri
a 1 & N & 100
a 1 & M & 10.000
a Pentru 60% din teste num rul minim de aplic ri ale setului de operaµii necesare va mai
mic decât 2.000.000.000.
Exemple:
perspic.in perspic.out Explicaµii
22 2 Matricea iniµial :
C12 12
R12 34
Matricea dup prima operaµie:
21
43
Matricea dup a doua operaµie (terminarea primului set):
43
21
Matricea dup a treia operaµie:
34
12
Matricea dup a patra operaµie(terminarea celui de al doilea set):
12
34
33 4
E1122
R12
C23
Timp maxim de executare/test: 0.1 secunde
Memorie: total 2 MB din care pentru stiv 1 MB
La un moment dat se va ajunge ca P aplicat de k ori lui i s dea din nou i. Practic, acest num r
k va reprezenta num rul minim de aplic ri ale setului dup care i se va aa din nou în poziµia
iniµial . Pentru orice multiplu al lui k acest lucru va de asemenea adevarat.
CAPITOLUL 31. ONI 2009 649
Vom avea
H i - num rul minim de aplic ri ale setului de operaµii pentru care i s se ae din nou în
poziµia iniµial .
Pentru c vrem ca toate numerele i s ajung din nou în poziµiile lor iniµiale vom c uta un
multiplu comun al tuturor valorilor H i, deci trebuie s calcul m
unde cmmdc a, b se calculeaz cu algorimul lui Euclid. Acest calcul va trece doar 60% din teste
deoarece rezultatul poate deveni foarte mare.
În general se pot parcurge toate numerele prime de la 1 la N N ³i, pentru ecare num r prim
p, se determin care este puterea cea mai mare e astfel încât s existe un i pentru care H i sa
e e
e divizibil cu p . Soluµia se va înmulµi cu p , obµinând în nal cmmmc dorit.
49 break;
50 case ’E’:
51 scanf("%d%d", &c, &d);
52 --c, --d;
53 sw(pos(a, b), pos(c, d));
54 break;
55 default:
56 //printf("ERROR: %s\n", op);
57 break;
58 }
59 }
60 }
61
62 void cycles()
63 {
64 int i, len, j, d, pow, x;
65
66 memset(B, 0, MAXN * MAXN);
67 memset(E, 0, MAXN * MAXN);
68
69 for (i = 0; i < n * n; ++i)
70 {
71 for (len = 0, j = i; !B[j]; ++len)
72 {
73 // printf("c: \t%d\n", j);
74 B[j] = 1;
75 j = A[j];
76 }
77
78 if (len)
79 {
80 // printf("<<< %d\n", len);
81 for (x=len, d=0; x>1 && P[d]*P[d] <= x && d < np; ++d)
82 {
83 // printf("e: %d, %d, %d\n", d, P[d], x);
84 for (pow = 0; x % P[d] == 0; ++pow)
85 x /= P[d];
86 if (E[P[d]] < pow)
87 E[P[d]] = pow;
88 }
89
90 if (x > 1 && !E[x])
91 E[x] = 1;
92 // dump_exp();
93 }
94 }
95 }
96
97 void gen_primes()
98 {
99 int a, j, i;
100 P[np++] = 2;
101 for (a = 3; a < n * n; a += 2)
102 {
103 char prim = 1;
104 for (j = 0; prim && (P[j] * P[j] <= a) && j < np; ++j)
105 prim = ((a % P[j]) != 0);
106 if (prim)
107 P[np++] = a;
108 }
109 }
110
111 void dump_exp()
112 {
113 int i;
114 printf("exp:\n");
115 for (i = 0; i < n * n; ++i)
116 if (E[P[i]])
117 printf(" %d^%d", P[i], E[P[i]]);
118
119 printf("\n");
120 }
121
122 void dump_primes()
123 {
124 int i;
CAPITOLUL 31. ONI 2009 651
125 printf("primes:\n");
126 for (i = 0; i < np; ++i)
127 printf(" %d", P[i]);
128
129 printf("\n");
130 }
131
132 int cmmmc()
133 {
134 int i, res, j;
135 for (res = 1, i = 1; i < n * n; ++i)
136 for (j = 0; j < E[i]; ++j)
137 res = (((long long)res * (i % MOD)) % MOD);
138
139 return res;
140 }
141
142 int main(void)
143 {
144 freopen("perspic.in", "rt", stdin);
145 freopen("perspic.out", "wt", stdout);
146
147 read_eval();
148 // dump();
149 gen_primes();
150 // dump_primes();
151 cycles();
152 printf("%d\n", cmmmc());
153 return 0;
154 }
31.3 rafturi
Problema 3 - rafturi 100 de puncte
Într-o bibliotec se a C dulapuri identice a³ezate unul lâng altul pe peretele unei înc peri,
dulapurile ind numerotate de la stânga spre dreapta cu numerele naturale de la 1 la C . Fiecare
dulap conµine 1000 de rafturi, situate vertical unul deasupra altuia, rafturile ec rui dulap ind
numerotate de la 1 la 1000 de jos în sus.
Fiecare dulap este prev zut cu o scar cu care se poate ajunge la orice raft. Dac bibliotecara
urc scara unui anumit dulap D pân la un anumit nivel k , ea va putea aduna orice carte de pe
rafturile 1 pân la k inclusiv, din dulapul D ³i din dulapurile învecinate (dulapul D 1 ³i dulapul
D 1).
Cunoscând dulapurile ³i rafturile de unde trebuie luate c rµi, bibliotecara dore³te s adune
toate c rµile cerute, dar suma în lµimilor pân la care trebuie s urce s e minim .
Cerinµe
Scrieµi un program care s determine suma minim a în lµimilor pân la care trebuie s urce
bibliotecara pentru a aduna toate c rµile cerute.
Date de intrare
Prima linie a ³ierului de intrare rafturi.in conµine dou numere naturale C ³i N , separate
printr-un spaµiu, reprezentând num rul dulapurilor ³i respectiv num rul c rµilor pe care bibliote-
cara trebuie s le adune.
Urm toarele N linii conµin câte dou numere naturale a b, separate printr-un spaµiu, repre-
zentând num rul dulapului, respectiv num rul raftului de unde trebuie luat o carte.
Date de ie³ire
Fi³ierul de ie³ire rafturi.out va conµine un singur num r natural reprezentând suma minim
a în lµimilor pân la care trebuie s urce bibliotecara pentru a aduna toate c rµile cerute.
CAPITOLUL 31. ONI 2009 652
Restricµii ³i preciz ri
a 1 & C & 10.000
a 1 & N & 50.000
Exemple:
rafturi.in rafturi.out Explicaµii
10 4 11 Bibliotecara urc astfel:
54 -pe dulapul 1 la raftul 1
11 -pe dulapul 4 la raftul 8
62 -pe dulapul 6 la raftul 2
38
Timp maxim de executare/test: 0.1 secunde
Memorie: total 2 MB din care pentru stiv 1 MB
La citirea datelor reµinem în vectorul carti, pentru ecare dulap, în lµimea cea mai mare de
pe care trebuie luat cartea.
Construim un vector inaltimi în care la ecare pas vom calcula suma minim a în lµimilor
rafturilor de pe care sunt coborîte c rµile pân în acel moment.
Aceasta se obµine astfel:
inaltimi[0]=0
inaltimi[1]=carti[1]
inaltimi[2]=carti[2]
21 {
22 FILE *f;
23 int x,y;
24 long i;
25
26 f=fopen("rafturi.in","r");
27 fscanf(f,"%d%ld",&C,&N);
28 for (i=1;i<=N;i++)
29 {
30 fscanf(f,"%d%d",&y,&x);
31 if (carti[y]<x) carti[y]=x;
32 }
33 carti[0]=0;
34 // afisare(carti);
35 fclose(f);
36 }
37
38 void calcul(void)
39 {
40 long h;
41 int i,j;
42 inaltime[0]=0;
43 for (i=1;i<=C;i++)
44 {
45 inaltime[i]=MAXV+1;
46 h=carti[i];
47 if (inaltime[i-1]+h<inaltime[i])
48 inaltime[i]=inaltime[i-1]+h;
49 for (j=i-1; j>i-3 && j>0 ;j--)
50 {
51 if (h<carti[j])
52 h=carti[j];
53 if (inaltime[j-1]+h<inaltime[i])
54 inaltime[i]=inaltime[j-1]+h;
55 }
56 }
57 }
58
59 void afisare(void)
60 {
61 FILE *g;
62 g=fopen("rafturi.out","w");
63 fprintf(g,"%ld\n",inaltime[C]);
64 //printf("%ld\n",inaltime[C]);
65 fclose(g);
66 }
67
68 int main()
69 {
70 citire();
71 calcul();
72 afisare();
73 return 0;
74 }
31.4 br
Problema 4 - br 100 de puncte
N prieteni, numerotaµi de la 1 la N , beau bere f r alcool la o mas rotund . Pentru ecare
prieten i se cunoa³te Ci - costul berii lui preferate. Din când în când, câte un prieten, e el k ,
cump r câte o bere pentru o secvenµ de prieteni aaµi pe poziµii consecutive la mas , inclusiv
lui, în sensul acelor de ceasornic. El este dispus s cheltuiasc x bani ³i dore³te s fac cinste la
un num r maxim posibil de prieteni.
Cerinµe
CAPITOLUL 31. ONI 2009 654
Se cere num rul de beri pe care le va cump ra ecare prieten k în limita sumei x de bani de
care dispune. în caz c x este mai mare decât costul berilor pentru toµi prietenii de la mas , se
vor achiziµiona maxim N beri.
Date de intrare
Prima linie a ³ierului de intrare br.in conµine dou numere naturale N ³i T separate printr-un
spaµiu reprezentând num rul de prieteni ³i respectiv num rul de prieteni care doresc s fac cinste
prietenilor s i.
A doua linie a ³ierului de intrare conµine N numere naturale C1 , C2 ..., CN , separate prin câte
un spaµiu, reprezentând costurile berilor preferate de ecare prieten. Berea pentru prietenul i are
costul Ci .
Fiecare din urm toarele T linii conµine câte dou numere separate printr-un spaµiu:
k1 x1
k2 x2
...
kT xT
precizând indicele câte unui prieten care face cinste ³i respectiv suma de bani de care acesta
dispune.
Date de ie³ire
Fi³ierul de ie³ire br.out va conµine T linii, ecare cu un singur num r Di reprezentând num rul
de beri pe care le va cump ra prietenul ki cu suma de bani xi in condiµiile problemei.
Restricµii ³i preciz ri
a 1 & N & 15.000
a 1 & T & 10.000
a 1 & Ci & 100
a 1 & ki & N
a 1 & xi & 3.000.000
a Un program corect, care se încadreaz în timp pentru T & 4000, va obµine cel puµin 30 de
puncte
a Un program corect, care se încadreaz în timp pentru N & 2000, va obµine cel puµin 60 de
puncte
a Prietenii beau numai berea lor preferat .
Exemple:
br.in br.out Explicaµii
54 3 Prietenul 1 cump r câte o bere pentru el ³i pentru prietenii 2, 3.
10 5 15 22 13 4 Costul celor 3 beri este 30.
1 32 0 Prietenul 4 cump r 4 beri: câte una pentru el ³i pentru prietenii
4 50 5 5, 1, 2. Costul celor 4 beri este 50.
19 Cu 9 bani prietenul 1 nu poate cump ra nici m car berea lui.
4 200 Prietenul 4 cump r 5 beri. Costul celor 5 beri este sub limita de
cost 200.
Timp maxim de executare/test: 0.1 secunde
Memorie: total 16 MB din care pentru stiv 1 MB
31.5 origami
Problema 5 - origami 100 de puncte
Costel este pasionat de arta oriental a confecµion rii obiectelor de hârtie, origami, dar este
abia la început ³i trebuie s se familiarizeze cu operaµiile de îndoire corect a hârtiei. El are la
dispoziµie o foaie de hârtie p trat , rupt dintr-un caiet de matematic , având dimensiunea de
exact N N p tr µele. îndoiturile trebuie realizate exact pe o linie orizontal sau vertical .
Sunt permise dou tipuri de îndoituri:
- îndoitura de tipul 1, îndoitur vertical executat la X p tr µele faµ de marginea stâng
a foii: partea din stânga a foii se pliaz c tre dreapta, de-a lungul liniei verticale aate la
distanµa de X p tr µele faµ de marginea stâng ;
- îndoitura de tipul 2, îndoitur orizontal executat la X p tr µele faµ de marginea supe-
rioar a foii: partea de sus a foii se pliaz în jos, de-a lungul liniei aate la distanµa de X
p tr µele faµ de marginea de sus a hârtiei.
În urma realiz rii unei succesiuni de îndoituri, din foaia iniµial de hârtie se va obµine un obiect,
care va avea o form dreptunghiular , cu în lµimea H , l µimea M ³i având grosimea egal cu
num rul maxim de foi care se suprapun în cadrul obiectului obµinut.
Cerinµe
Dat ind o succesiune de îndoituri aplicat unei foi de dimensiune N N , scrieµi un program
care s determine în lµimea, l µimea ³i grosimea obiectului obµinut.
Date de intrare
Fi³ierul de intrare origami.in are urm toarea structur :
- prima linie a ³ierului conµine un num r natural N , reprezentând dimensiunea iniµial a
hârtiei;
- a doua linie conµine un num r natural K , reprezentând num rul îndoiturilor;
- pe urm toarele K linii se g sesc perechi de numere naturale nenule, A B , separate printr-un
spaµiu, reprezentând tipul îndoiturii (A este 1 dac se realizeaz o îndoitur vertical sau
A este 2 dac se realizeaz o îndoitur orizontal ), respectiv la ce distanµ se realizeaz
îndoitura;
Date de ie³ire
Fi³ierul de ie³ire origami.out va conµine, pe o singur linie, trei numere naturale nenule H , L,
G, separate prin câte un spaµiu, reprezentând în lµimea, l µimea ³i respectiv grosimea obiectului
obµinut.
Restricµii ³i preciz ri
a 2 & N & 170
a 1 & K & 2N 2
a A 1 sau A 2
a 1 & B $ în lµimea sau l µimea hârtiei la momentul respectiv (funcµie de tipul îndoiturii)
Exemple:
origami.in origami.out Explicaµii
4 326 Hârtia are 4 unit µi în lµime ³i 4 unit µi l µime. Prima îndoitur
3 se realizeaz de la stânga la dreapta, de-a lungul celei de-a treia
13 linii verticale faµ de marginea stâng a foii. Se obµine o foaie de
23 în lµime 4, l µime 3 ³i grosime 2. A doua îndoitur se realizeaz
11 îndoind partea superioar a foii, în jos, de-a lungul celei de-a
treia linii orizontale faµ se marginea de sus a foii. Se obµine
un obiect de în lµime 3, l µime 3 ³i grosime 4. Dup a treia
îndoitur se obµine obiectul nal, având în lµimea 3, l µimea 2
³i grosimea 6.
Timp maxim de executare/test: 0.1 secunde
Memorie: total 16 MB din care pentru stiv 1 MB
CAPITOLUL 31. ONI 2009 657
Reprezentarea foii de hârtie se va realiza cu ajutorul unui tablou bidimensional F , având iniµial
N linii ³i N coloane ³i elementele egale cu zero.
Deoarece îndoiturile se pot realiza doar pe liniile dintre elementele tabloului, F ij va repre-
zenta grosimea foii în zona p tr µelei de pe linia i ³i coloana j .
Matricea F va reecta modic rile aduse foii iniµiale dup ecare îndoitur din ³ierul de
intrare, astfel:
- Pentru îndoitura de tip 1:
` Cazul 1: Distanta faµ de marginea st ng a foii a liniei de-a lungul c reia se realizeaz
îndoitura (Lin) este mai mic decât jumatatea l µimii hârtiei, adic 2 Lin & M .
în acest caz, realizez îndoitura suprapunând primele Lin linii, oglindite, peste urm toa-
rele Lin linii, însumând elementele corespunz toare din F .
Mut apoi toate elementele matricei c tre stânga.
` Cazul 2: Distanta faµ de marginea st ng a foii a liniei de-a lungul c reia se realizeaz
îndoitura (Lin) este mai mare decât jumatatea l µimii hârtiei, adic 2 Lin % M .
Putem reduce acest caz la cazul precedent, mutând coloanele care, prin îndoire, dep ³esc
marginea dreapt a foii la sfâr³itul tabloului, oglindite.
Se aplic apoi procedeul de la cazul precedent, îndoind foaia la distanµa M Lin
elemente.
- Pentru îndoitura de tip 2 se procedeaz asem n tor.
3
Algoritmul are, în cazul cel mai defavorabil, complexitatea O N r N .
39
40 // indoi
41 for(j=1;j<=CatIndoi;j++)
42 for(i=1;i<=N;i++) F[i][2*CatIndoi-j+1] += F[i][j];
43
44 // mut elementele tabloului cu CatIndoi elemente la stanga
45 for(i=1;i<=N;i++)
46 for(j=1;j<=M-CatIndoi;j++) F[i][j] = F[i][j+CatIndoi];
47 M = M - CatIndoi;
48 }
49 else
50 {
51 //daca indoitura depaseste cumva marginea de jos a foii
52 if(2*Lin>N)
53 {
54 CatIndoi = N - Lin; // numarul de coloane ale indoiturii
55 Rest = Lin - CatIndoi; // cate coloane mut la sfarsit
56 }
57 else
58 {
59 CatIndoi = Lin;
60 Rest = 0;
61 }
62
63 // copiez primele Rest linii, oglindite, la sfarsitul tabloului,
64 // deplasand liniile in sus
65 for(k=Rest;k>=1;k--)
66 for(i=1;i<=M;i++)
67 {
68 tmp = F[k][i];
69 for(j=k;j<N;j++) F[j][i] = F[j+1][i];
70 F[N][i] = tmp;
71 }
72
73 // indoi
74 for(i=1;i<=CatIndoi;i++)
75 for(j=1;j<=M;j++) F[2*CatIndoi-i+1][j] += F[i][j];
76
77 // mut elementele tabloului cu CatIndoi elemente in sus
78 for(i=1;i<=N-CatIndoi;i++)
79 for(j=1;j<=M;j++)F[i][j] = F[i+CatIndoi][j];
80 N = N - CatIndoi;
81 }
82 }
83
84 int main()
85 {
86 ifstream f(Fin);
87 int N; // dimensiunea initiala a hartiei
88 int M; // latimea hartiei, initial = N
89 int Nr; // numarul indoiturilor
90
91 int Tip; // Tipul indoiturii: 1 verticala spre dreapta;
92 // 2 - orizontal de sus in jos
93 int Lin; // Linia de-a lungul careia facem indoitura
94 int Max; // Grosimea maxima
95 int i,j;
96
97 //citesc datele de intrare si indoi
98 f>>N>>Nr;
99 M = N; // initial hartia e patrata, pe urma nu
100
101 //initializez hartia
102 for(i=1;i<=N;i++) for(j=1;j<=M;j++) F[i][j] = 1;
103 for(i=1;i<=Nr;i++)
104 {
105 f>>Tip>>Lin;
106 indoaie(N,M,Tip,Lin);
107 }
108 f.close();
109
110 // aflu grosimea maxima si afisez datele de iesire
111 Max = 0;
112 for(i=1;i<=N;i++)
113 for(j=1;j<=M;j++)
114 if(F[i][j]>Max) Max = F[i][j];
CAPITOLUL 31. ONI 2009 659
115
116 ofstream g(Fou);
117 g<<N<<" "<<M<<" "<<Max<<’\n’;
118 /*
119 for(i=1;i<=N;i++)
120 {
121 for(j=1;j<=M;j++) g<<F[i][j]<<" ";
122 g<<’\n’;
123 }
124 */
125 g.close();
126 return 0;
127 }
31.6 patrate
Problema 6 - patrate 100 de puncte
Fiind date dou numere naturale n ³i p se cere s se g seasc un num r natural m & 350.000
cu proprietatea c el poate scris atât ca sum de p p trate perfecte nenule, cât ³i ca sum de
p 1 p trate perfecte nenule, ..., cât ³i ca sum de n p trate perfecte nenule.
Cerinµe
Date de intrare
Prima linie a ³ierului de intrare patrate.in conµine dou numere naturale n ³i p separate
printr-un spaµiu, având semnicaµia de mai sus.
Date de ie³ire
Prima linie a ³ierului de ie³ire patrate.out va conµine num rul natural m c utat.
Urmeaz n p 1 linii. Linia i a ³ierului, pentru i 2, 3, ..., n p 2, va conµine p i 2
numere naturale separate prin câte un spaµiu, cu proprietatea c suma p tratelor acestora este m.
Restricµii ³i preciz ri
a2 & n & 1000
a2&p&n
a Soluµia nu este unic , se va accepta orice soluµie corect ;
a Un program corect, care se încadreaz în timp pentru n & 30, va obµine cel puµin 30 de
puncte.
a Un program corect, care se încadreaz în timp pentru n & 150, va obµine cel puµin 70 de
puncte.
Exemple:
patrate.in patrate.out Explicaµii
2 2 2
43 18 18 1 1 4
2 2 2 2
114 18 2 1 2 3
2123
Timp maxim de executare/test: 0.4 secunde
Memorie: total 16 MB din care pentru stiv 1 MB
CAPITOLUL 31. ONI 2009 660
O prim idee, greu de implementat, este de a genera toate submulµimile de 2, 3, ..., n elemente
ale mulµimii numerelor naturale ³i apoi de ale c uta pe acelea cu proprietatea c dau aceea³i
sum a p tratelor. Acesta idee este inutilizabil din punct de vedere practic deoarece num rul de
submulµimi este foarte mare.
Soluµia se bazeaz pe o idee constructiv , mai precis pe construirea din aproape în aproape a
soluµiei.
S demonstr m pentru început, din punct de vedere matematic, c exist un num r natural
m care se poate scrie, simultan ca suma de 2, 3, ..., n p trate perfecte nenule, de numere întregi.
Vom demonstra prin inducµie aceast proprietate.
P(1):
2 2
Pentru n 2 se g se³te m2 1 1 2
2 2 2 2 2
Pentru n 3 se g se³te m3 1 4 2 2 3 17
P(k): Presupunem relaµia adev rat pentru n k , cu alte cuvinte exist un num r m care se
2 2 2 2 2
scrie ca suma de 2, 3, ..., k p trate de numere întregi nenule. A³adar mk a1 a2 b1 b2 b3
2 2 2
... l1 l2 ... lk
P(k+1): Vom demonstra acum ca ³i relaµia P(k+1) este adev rat .
Mai întâi vom utiliza un alt rezultat, u³or de demonstrat, ³i anume c orice num r natural
p ' 7 poate scris sub forma p a b c . Vom aplica acest rezultat pentru mk ³i vom obµine
2 2 2
2 2 2
3 numere întregi a, b, c, astfel încât mk a b c .
Odat mk scris sub acesta form avem :
2 2 2 2 2 2 2 2 2 2 2 2
mk1 mk c a2 b2 a1 a2 c b1 b2 b3 c ... l1 l2 ... lk c .
2 2 2
Exemplu m3 17 3 3 1 ,
2 2 2 2 2 2 2 2 2 2
de unde m4 17 1 3 3 1 4 1 2 2 3 1 18
A³adar P(k+1) este adev rat deci P(n) este adev rat pentru orice n natural.
Soluµia urm re³te mecanismul descris anterior, cu observaµia c pentru a genera un num r m
2 2 2
cât mai mic, f r a avea pretenµia c este cel mai mic, facem descompunerea mk a b c în
a³a fel încât c s e minim.
29 {
30 c = i;
31 return x + i * i;
32 }
33 return -1;
34 }
35
36 int main()
37 {
38 int i,j,l,k;
39 freopen("patrate.in","r",stdin);
40 freopen("patrate.out","w",stdout);
41
42 scanf("%d", &n);
43 scanf("%d", &p);
44
45 j = 2;
46 A[0] = B[0] = 1;
47 C[0] = 0;
48 l = 1;
49 FOR(i, 3, n + 1)
50 {
51 j = doit(j);
52 A[l] = a ;
53 B[l] = b ;
54 C[l] = c ;
55 l++;
56 }
57 printf("%d\n", j);
58
59 FOR(i,p,n+1)
60 {
61 k = n - i;
62 printf("%d %d",A[k],B[k]);
63 FOR(j,k+1, l) printf(" %d",C[j]);
64 printf("\n");
65 }
66
67 return 0;
68 }
ONI 2008
32.1 ab
Problema 1 - ab 100 de puncte
Una din cele mai noi pasiuni ale lui Z h rel este s studieze diverse propriet µi ale permut rilor.
De exemplu, este interesat de permut rile în care cel mai lung sub³ir cresc tor ³i cel mai lung sub³ir
descresc tor au lungimi date.
Cerinµe
S se scrie un program care determin o permutare de lungime N în care cel mai lung sub³ir
cresc tor are lungime A ³i cel mai lung sub³ir descresc tor are lungime B .
Date de intrare
Fi³ierul de intrare ab.in va conµine pe prima linie numerele N A B .
Date de ie³ire
Fi³ierul de ie³ire ab.out va conµine pe prima linie N numere separate prin câte un spaµiu,
reprezentând o permutare care respect condiµiile de mai sus. Dac exist mai multe soluµii, se
va a³a cea minim din punct de vedere lexicograc.
Restricµii ³i preciz ri
a 1 & N, A, B & 30.000
a Se garanteaz c mereu exist soluµie pentru datele de intrare
a Se nume³te sub³ir al ³irului X x1 , x2 , ..., xN , un ³ir Y xi1 , xi2 , ..., xiM cu proprietatea
1 & i1 $ i2 $ ... $ iM & N
a Un ³ir x1 , x2 , ..., xK este mai mic din punct de vedere lexicograc decat un alt ³ir
y1 , y2 , ..., yK dac exist o poziµie p & K , astfel încat xp $ yp ³i x1 y1 , x2 y2 , ..., xp1 yp1
a Pentru un test se va acorda 70% din punctaj dac permutarea a³at are cel mai lung sub³ir
cresc tor de lungime A ³i cel mai lung sub³ir descresc tor de lungime B , dar nu este minim
lexicograc.
Exemple:
ab.in ab.out Explicaµii
423 1432 Cel mai lung sub³ir cresc tor are lungime 2 (1 4, 1 3 sau 1 2), iar cel
mai lung sub³ir descresc tor are lungime 3 (4 3 2).
O alt soluµie posibil este 2 4 3 1, dar aceasta nu este minim din punct
de vedere lexicograc.
Timp maxim de executare/test: 0.1 secunde
662
CAPITOLUL 32. ONI 2008 663
Mircea Pa³oi
Vom prezenta un algoritm prin care se poate obµine o permutare de lungime N cu cel mai lung
sub³ir cresc tor de lungime A ³i cel mai lung sub³ir descresc tor de lungime B :
1) Se împart numerele de la 1 la N (luate în ordinea asta) în A grupuri de lungime cel mult B
ecare. Deasemenea, trebuie s existe cel puµin un grup de lungime x B .
2) Se inverseaz elementele din ecare grup
Orice sub³ir descresc tor va face parte dintr-un grup, iar cum lungimea unui grup este maxim
B (³i exist unul cu x B ), cel mai lung sub³ir descresc tor va avea lungime B .
Orice sub³ir cresc tor va format cu câte un element din ecare grup. Cum sunt A grupuri,
cel mai lung sub³ir cresc tor va avea lungime A.
Pentru a obµine o soluµie minim lexicograc trebuie ca grupurile de la început s e cât mai
mici ca m rime.
Exemplu pentru N 10, A 4, B 3
Se împarte în 4 grupuri, ecare de lungime maxim 3 astfel încât grupurile de la început s e
cât mai mici:
1 | 2 3 4 | 5 6 7 | 8 9 10
Se inverseaz elementele din ecare grup ³i se obµine permutarea:
1 4 3 2 7 6 5 10 9 8
32.2 iepuras
Problema 2 - iepuras 100 de puncte
Un iepura³ se g se³te într-o gr din plin de surprize. Harta gr dinii poate reprezentat sub
forma unei table dreptunghiulare cu m linii, numerotate de la 1 la m de sus în jos, ³i n coloane,
numerotate de la 1 la n de la stânga la dreapta. în ecare celul a acestei gr dini se poate g si
cel mult una dintre urm toarele surprize: s geat , pom, zid, trap , morcov, bomb .
O s geat indic una din direcµiile nord, sud, est, vest. Odat ajuns într-o celul conµinând
o astfel de s geat iepura³ul î³i va continua deplasarea în sensul indicat de s geat , iar aceasta
dispare.
Într-o celul în care se g se³te un pom sau un zid iepura³ul nu poate s p trund , îns dac
se love³te de un pom, el î³i p streaz direcµia, îns schimb sensul (dac se deplasa spre nord,
î³i va schimba sensul spre sud, dac se deplasa spre est, se va deplasa dup aceea spre vest etc).
Dac iepura³ul intr într-o celul conµinând o trap , toate zidurile aate pe teren dispar ³i vor
ap rea alte ziduri, în poziµii precizate. Dac iepura³ul va trece din nou printr-o celul conµinând o
trap , zidurile nou construite dispar ³i vor reap rea zidurile iniµiale. Mai exact exist dou grupe
de ziduri care comut la ecare trecere printr-o celul care conµine o trap .
Dac iepura³ul va trece de dou ori prin vecin tatea unei celule conµinând o bomb (adic
prin celulele învecinate la sud, nord, est sau vest cu celula conµinând bomb ), bomba va exploda
iar iepura³ul se transform instantaneu în îngera³. De asemenea, dac iepura³ul într într-o celul
conµinând o bomb se transform instantaneu în ingeras.
Iepura³ul va ronµ i toµi morcovii care îi ies în cale. Evident c dac trece a doua oar prin
aceea³i celul , la a doua trecere nu va mai g si morcov.
Surprizele din gr din sunt codicate astfel: 1 pentru s geat spre nord, 2 pentru s geat spre
vest, 3 pentru s geat spre sud, 4 pentru s geat spre est, 5 pentru pom, 6 pentru bomb , 7
pentru morcov, 8 pentru zid, 9 pentru trap . C suµele libere de pe harta gr dinii se codic cu
0.
Iniµial, se cunosc poziµia ³i sensul de deplasare ale iepura³ului. Expediµia acestuia se termin
în urm toarele situaµii:
- la explozia unei bombe, caz în care se transform în îngera³;
- la p r sirea gr dinii (adic la ie³irea în afara zonei dreptunghiulare date), caz în care se
r t ce³te;
- în momentul în care reu³e³te s ronµ ie toµi morcovii, caz în care este fericit.
Cerinµe
Fiind data harta gr dinii se cere s se determine starea nal a iepura³ului (îngera³, r t cit
respectiv fericit), num rul de morcovi ronµ iµi pân în momentul termin rii expediµiei, precum ³i
num rul de pa³i pe care îi face iepura³ul pân la acest moment.
Date de intrare
Pe prima linie a ³ierului de intrare iepuras.in se g sesc dou numere întregi m ³i n, separate
printr-un spaµiu, reprezentând num rul de linii, respectiv num rul de coloane ale h rµii.
Linia a doua a ³ierului conµine trei numere naturale, separate prin câte un spaµiu, reprezentând
linia si coloana poziµiei iniµiale a iepura³ului pe hart precum ³i direcµia spre care acesta este
orientat. Direcµia este codicat astfel: 1 pentru nord, 2 pentru vest, 3 pentru sud, 4 pentru est.
Urm toarele m linii conµin câte n numere întregi separate prin câte un spaµiu, reprezentând
codicarea h rµii gr dinii, conform celor precizate mai sus.
Urm toarea linie conµine un singur num r natural t reprezentând num rul de celule ce vor
conµine ziduri dup prima trecere printr-o celul conµinând o trap . Urm toarele t linii conµin
câte dou numere naturale i ³i j , separate printr-un spaµiu, reprezentând coordonatele câte unei
celule ce va conµine zid dup o prim trecere printr-o celul conµinând o trap .
Date de ie³ire
CAPITOLUL 32. ONI 2008 665
Fi³ierul de ie³ire iepuras.out va conµine pe prima sa linie unul dintre cuvintele INGERAS,
RATACIT respectiv FERICIT, corespunz tor st rii nale a iepura³ului.
A doua linie a ³ierului va conµine dou numere întregi separate printr-un spaµiu, reprezentând
linia ³i coloana ultimei poziµii de pe teren a iepura³ului, adic poziµia în care a murit, sau în care
a devenit fericit, respectiv ultima poziµie a sa de pe teren, înainte de a se r t ci.
A treia linie a ³ierului va conµine dou numere întregi separate printr-un spaµiu, reprezentând
num rul de morcovi cule³i pân în momentul termin rii expediµiei, respectiv num rul de pa³i pe
care îi face iepura³ul pân ajunge în starea nal .
Restricµii ³i preciz ri
a poziµia iniµial a iepura³ului este una valid , adic este o celul liber din interiorul terenului;
a pentru datele de test, se asigur c iepura³ul va face un num r nit de pa³i pân la terminarea
expediµiei sale;
a 1 & m, n & 200
a 0 & t & 20
a num rul maxim de ziduri aate la un moment dat pe teren este de cel mult 50, ³i este posibil
ca la un moment dat s nu existe niciun zid pe teren.
a Se garanteaz c pentru datele de intrare iepura³ul nu poate ajunge simultan în dou din
cele trei st ri.
a Pomii ³i trapele sunt obiecte care r mân permanent în teren, în poziµiile lor iniµiale.
a într-o celul a gr dinii se poate g si la un moment dat o singur surpriz (pom, zid, trap ,
morcov, s geat , bomb )
Exemple:
53
54 nrm=0;
55 f>>m>>n;
56 f>>i0>>j0>>d;
57
58 for (i=1;i<=m;i++)
59 for (j=1;j<=n;j++)
60 {
61 f>>a[i][j];
62 if (a[i][j]==’7’) nrm++;
63 if (a[i][j]==’8’)
64 {
65 z1[n1].i=i;
66 z1[n1].j=j;
67 n1++;
68 }
69 }
70
71 f>>n2;
72 for (i=0;i<n2;i++)
73 f>>z2[i].i>>z2[i].j;
74 f.close();
75
76 i=i0;
77 j=j0;
78 while (1)
79 {
80 i=i+di[d-1];
81 j=j+dj[d-1];
82 p++;
83
84 if (i==3 && j==190)
85 cout<<"bla";
86
87 // afara
88 if (afara(i,j))
89 {
90 g<<"RATACIT"<<endl;
91 g<<i-di[d-1]<<" "<<j-dj[d-1]<<endl;
92 g<<q<<" "<<p;
93 break;
94 }
95
96 // morcov
97 if (a[i][j]==’7’)
98 {
99 q++;
100 a[i][j]=’0’;
101 }
102
103 // e bomba sau in vecinatatea unei bombe pregatita sa explodeze
104 if (explod(i,j))
105 {
106 g<<"INGERAS"<<endl;
107 g<<i<<" "<<j<<endl;
108 g<<q<<" "<<p;
109 break;
110 }
111
112 // a cules toti morcovii
113 if (q==nrm)
114 {
115 g<<"FERICIT"<<endl;
116 g<<i<<" "<<j<<endl;
117 g<<q<<" "<<p;
118 break;
119 }
120
121 if (a[i][j]==’9’)
122 {
123 if (pz==1)
124 {
125 for (k=0;k<n1;k++)
126 a[z1[k].i][z1[k].j]=’0’;
127
128 for (k=0;k<n2;k++)
CAPITOLUL 32. ONI 2008 668
129 a[z2[k].i][z2[k].j]=’8’;
130
131 pz=2;
132 }
133 else
134 {
135 for (k=0;k<n2;k++)
136 a[z2[k].i][z2[k].j]=’0’;
137
138 for (k=0;k<n1;k++)
139 a[z1[k].i][z1[k].j]=’8’;
140
141 pz=1;
142 }
143 }
144
145 // sageata, schimba directia
146 if (a[i][j]==’1’) { d=1; a[i][j]=’0’; }
147 if (a[i][j]==’2’) { d=2; a[i][j]=’0’; }
148 if (a[i][j]==’3’) { d=3; a[i][j]=’0’; }
149 if (a[i][j]==’4’) { d=4; a[i][j]=’0’; }
150
151 // pom sau zid, schimba directia
152 if (a[i+di[d-1]][j+dj[d-1]]==’5’ || a[i+di[d-1]][j+dj[d-1]]==’8’)
153 if (d==1)
154 d=3;
155 else
156 if (d==2)
157 d=4;
158 else
159 if (d==3)
160 d=1;
161 else
162 d=2;
163 }
164
165 g.close();
166 }
32.3 palind
Problema 3 - palind 100 de puncte
Ana a descoperit c are o adev rat pasiune pentru palindroame. Un ³ir de numere este
palindrom dac se cite³te la fel de la stânga la dreapta ³i de la dreapta la stânga (primul num r
este egal cu ultimul, al doilea cu penultimul etc). Ea are un ³ir cu N numere naturale ³i vrea ca
orice subsecvenµ de lungime impar a ³irului s e palindrom. Pentru a-³i îndeplini dorinµa ea
poate efectua asupra ³irului mai multe operaµii. O operaµie const în alegerea unui element din
³ir ³i incrementarea sau decrementarea lui cu o unitate. Bineînµeles, Ana dore³te s utilizeze un
num r minim de operaµii pentru ca ³irul obµinut s respecte proprietatea amintit mai sus (orice
subsecvenµ de lungime impar s e palindrom).
Cerinµe
Determinaµi pentru Ana num rul minim de operaµii pe care trebuie s -l efectueze pentru
ca orice subsecvenµ de lungime impar a ³irului obµinut în urma efectu rii operaµiilor s e
palindrom. De asemenea aaµi ³i num rul de ³iruri nale distincte pe care le poate obµine efectuând
acest numar minim de operaµii.
Date de intrare
Fi³ierul de intrare palind.in va conµine pe prima linie num rul T , reprezentând num rul de
seturi de date de intrare care urmeaz . în continuare urmeaz seturile de date de intrare, ecare
pe câte dou linii. Pe prima linie a unui set de date se a num rul N , având semnicaµia din
enunµ. Pe urm toarea linie se a elementele ³irului iniµial, separate prin câte un spaµiu.
CAPITOLUL 32. ONI 2008 669
Date de ie³ire
Fi³ierul de ie³ire palind.out va conµine T linii, pe linia i aându-se dou numere, reprezentând
raspunsul pentru al i-lea set de date de intrare. Primul numar este numarul minim de operaµii,
iar al doilea num rul de ³iruri distincte nale care se pot obµine efectuând num rul minim de
operaµii.
Restricµii ³i preciz ri
a 1 & T & 20
a 1 & N & 10.000
a Elementele ³irului sunt numere naturale din intervalul 1, 7.000
a subsecvenµ a unui ³ir este un sub³ir de numere care apar pe poziµii consecutive
a Toate testele folosite la corectare vor avea T 20
a Pentru 20% din teste 1 & N & 100
a Pentru 20% din teste valoarea maxim din oricare ³ir este cel mult 500 ³i N ' 101
Exemple:
palind.in palind.out Explicaµii
2 23 Pentru primul test, cele trei ³iruri posibile sunt:
3 01 1 2 1, 2 2 2 si 3 2 3.
123 Pentru al doilea test, singurul ³ir posibil este format din
1 elementul 3
3
Timp maxim de executare/test: 0.5 secunde pe Windows, 0.2 secunde pe Linux
Adrian Airinei
9 int sol[2][2];
10
11 void baga(int t)
12 {
13 int i, nr, val, x, mmin = INF;
14 memset(cnt, 0, sizeof(cnt));
15 for(val = nr = 0, i = 1; i < MAXN; i++)
16 val += nr, val += A[t][i-1], nr += A[t][i-1], cnt[i] += val;
17 for(nr = val = 0, i = MAXN-2; i >= 1; i--)
18 val += nr, val += A[t][i+1], nr += A[t][i+1], cnt[i] += val;
19 for(nr = 0, i = 1; i < MAXN; i++)
20 {
21 if(cnt[i] == mmin) nr++;
22 if(cnt[i] < mmin) mmin = cnt[i], nr = 1;
23 }
24 sol[t][0] = mmin, sol[t][1] = nr;
25 }
26
27 void solve(void)
28 {
29 int i, val, x;
30
31 memset(A, 0, sizeof(A));
32
33 scanf("%d", &N);
34 for(i = 1; i <= N; i++)
35 scanf("%d", &x), A[i&1][x]++;
36
37 baga(0), baga(1);
38 printf("%d %d\n", sol[0][0]+sol[1][0], sol[0][1]*sol[1][1]);
39 }
40
41 #define VMAX 7000
42
43 void brute(void)
44 {
45 int p[2][2], i, j, x, nr, val, t, mmin;
46
47 for(t = 0; t <= 1; t++)
48 {
49 nr = 0, mmin = INF;
50 for(i = 1; i <= VMAX; i++)
51 {
52 for(val = 0, j = 1; j <= VMAX; j++)
53 val += ABS(j-i)*A[t][j];
54 if(val == mmin) nr++;
55 if(val < mmin) mmin = val, nr = 1;
56 }
57 p[t][0] = mmin, p[t][1] = nr;
58 }
59 fprintf(stderr, "%d %d\n", p[0][0]+p[1][0], p[0][1]*p[1][1]);
60 }
61
62 int main(void)
63 {
64 freopen("palind.in", "rt", stdin);
65 freopen("palind.out", "wt", stdout);
66
67 int teste;
68
69 scanf("%d ", &teste);
70 while(teste--)
71 solve();//, brute();
72
73 return 0;
74 }
7
8 int N, A[2][MAXN], cnt[2];
9 int sol[2][2];
10
11 void solve(void)
12 {
13 int i, val, t, x, j, nr, mmin = INF;
14
15 memset(A, 0, sizeof(A)), cnt[0] = cnt[1] = 0;
16
17 scanf("%d", &N);
18 for(i = 1; i <= N; i++)
19 scanf("%d", &x), A[i&1][ ++cnt[i&1] ] = x;
20
21 for(t = 0; t <= 1; t++)
22 {
23 nr = 0, mmin = INF;
24 for(i = 1; i < MAXN; i++)
25 {
26 for(val = 0, j = 1; j <= cnt[t]; j++)
27 val += ABS(i-A[t][j]);
28 if(val == mmin) nr++;
29 if(val < mmin) mmin = val, nr = 1;
30 }
31 sol[t][0] = mmin, sol[t][1] = nr;
32 }
33
34 printf("%d %d\n", sol[0][0]+sol[1][0], sol[0][1]*sol[1][1]);
35 }
36
37 int main(void)
38 {
39 freopen("palind.in", "rt", stdin);
40 freopen("palind.out", "wt", stdout);
41
42 int teste;
43
44 scanf("%d ", &teste);
45 while(teste--)
46 solve();//, brute();
47
48 return 0;
49 }
32.4 auto
Problema 4 - auto 100 de puncte
Se consider o autostrad dispus în linie dreapt având N puncte de acces (intrare ³i ie³ire). în
ecare punct de acces exist containere pentru colectarea de³eurilor, toate containerele au aceea³i
capacitate ³i în ecare punct de acces pot mai multe astfel de containere.
Firma care asigur cur µenia dispune de un singur mijloc de transport al containerelor. Acest
mijloc de transport poate înc rca exact un num r K de containere. Accesul mijlocului de transport
pe autostrad se face cu restricµii pentru a nu perturba tracul ³i din acest motiv trebuie ca la
ecare acces pe autostrad s e colectate exact atâtea containere cât este capacitatea ma³inii,
dar dintr-un punct de colectare trebuie s ia exact un container, deci dac se intr pe autostrad
la punctul de acces P , unde P & N K 1, atunci trebuie s ia containere de la punctele de
acces numerotate cu P, P 1, P 2, ..., P K 1, în aceste puncte de acces scade cu 1 num rul
containerelor r mase.
Firma trebuie s g seasc toate valorile posibile pentru K astfel încât s poat colecta toate
containerele.
Cerinµe
Se cere s se g seasc toate valorile posibile pentru K astfel încât s e adunate toate contai-
nerele.
Date de intrare
Fi³ierul de intrare auto.in va conµine pe prima linie num rul natural T , reprezentând num rul
de seturi de date de intrare. În continuare urmeaz seturile de date de intrare, ecare pe cate dou
linii. Pe prima linie a unui set se a num rul N , având semnicaµia din enunµ. Pe urm toarea
linie se a N numere naturale separate printr-un spaµiu, reprezentând num rul de containere din
ecare punct de acces.
Date de ie³ire
Fi³ierul de ie³ire auto.out va conµine T linii, pe linia i aându-se r spunsul pentru al i-lea set
de date de intrare. Valorile posibile pentru K se vor a³a în ordine crescatoare, separate printr-un
spaµiu.
Restricµii ³i preciz ri
CAPITOLUL 32. ONI 2008 673
a 2 & T & 30
a 2 & N & 9 000
a 1&K&N
a 0 & num rul de containere din ecare punct de acces & 10 000
Exemple:
auto.in auto.out Explicaµii
2 12
8 13
12342000
3
111
Timp maxim de executare/test: 0.8 secunde pe Windows, 0.2 secunde pe Linux
Pentru un K xat, putem calcula u³or în O N K dac reprezint soluµie sau nu. Aceast
3
abordare are complexitate O N ³i obµine aproximativ 30 puncte.
Putem folosi o stiv în care avem la un moment dat invervalele sortate cresc tor dup cap tul
dreapta. Când suntem la al i-lea punct de intrare scoatem din stiv intervalele care nu conµin
punctul acesta ³i eventual introducem dac este nevoie intervalul i, i k 1. Aceast soluµie are
2
complexitate O N ³i obtine 70 puncte.
Pentru a optimiza aceast soluµie observ m c dac suma tuturor valorilor este SU M este
necesar s consider m valorile posibile pentru K care este divizor al lui SU M . Astfel complexitatea
devine O N _DIV N , unde N _DIV este num rul de divizori ai lui SU M mai mici sau egali
cu N .
34
35 for(i = 1; i <= N; i++) scanf("%d ", &A[i]), d += (long)A[i],
36 assert(A[i] >= 0 && A[i] <= 10000);
37
38 for(i = 1; i <= N; i++)
39 if(d % i == 0 && check(i)) sol[++NR] = i;
40
41 for(i = 1; i <= NR; i++)
42 for(j = i+1; j <= NR; j++)
43 if(sol[i] > sol[j]) k = sol[i], sol[i] = sol[j], sol[j] = k;
44
45 for(i = 1; i <= NR; i++) printf("%d ", sol[i]);
46 printf("\n");
47 }
48
49 int main(void)
50 {
51 int teste, start, end;
52
53 freopen("auto.in", "rt", stdin);
54 freopen("auto.out", "wt", stdout);
55
56 start = clock();
57
58 scanf("%d ", &teste);
59 while(teste--)
60 read_and_solve();
61
62 fprintf(stderr, "%ld\n", steps);
63
64 end = clock();
65
66 fprintf(stderr, "%lf\n", (double)(end-start)/CLOCKS_PER_SEC);
67
68 return 0;
69 }
37
38 int main(void)
39 {
40 int teste;
41
42 freopen("auto.in", "rt", stdin);
43 freopen("auto2.out", "wt", stdout);
44
45 scanf("%d ", &teste);
46 while(teste--)
47 read_and_solve();
48
49 fprintf(stderr, "%ld\n", steps);
50
51 return 0;
52 }
32.5 div
Problema 5 - div 100 de puncte
Se citesc dou numere naturale M ³i N .
Cerinµe
S se elimine o secvenµ de cifre din num rul N pentru a obµine un num r divizibil cu M de
valoare maxim .
Date de intrare
Fi³ierul de intrare div.in conµine pe prima linie num rul natural nenul M iar pe a doua linie
num rul natural N .
Date de ie³ire
Fi³ierul de ie³ire div.out va conµine dou numere întregi i1 ³i i2 separate prin câte un spaµiu,
reprezentând indicii primei, respectiv ultimei cifre care vor ³terse. Cifrele lui N se indexeaz de
la 1, de la stânga la dreapta. Dac sunt mai multe soluµii se va scrie cea pentru care primul indice
este cel mai mic. Dac nu trebuie eliminat nici o cifr se vor scrie dou cifre de 0.
Restricµii ³i preciz ri
a 2 & M & 30000
a N are cel mult 5 000 cifre
a prima cifr a lui N este nenul
a o secvenµ este format din cifre aate pe poziµii consecutive în num rul N .
Exemple:
div.in div.out Explicaµii
2 1 10 ...
3333333333
7 00 ...
33332222
7 56 ...
3333322222
Timp maxim de executare/test: 1.0 secunde pe Windows, 0.3 secunde pe Linux
CAPITOLUL 32. ONI 2008 676
32.6 teatru
Problema 6 - teatru 100 de puncte
Alina este mare iubitoare de teatru. Directorul teatrului i-a oferit ³ansa s joace în mai multe
spectacole, ca gurant, deocamdat . Costumiera de scen a decis s -i dea C costume diferite
dintre cele care sunt destinate acestei stagiuni. Alina va duce costumele acas ³i le va ajusta ca
s -i vin bine. Stagiunea dureaz N zile consecutive ³i în ecare zi se joac câte o pies . Aceea³i
pies se va juca, desigur în una sau mai mai multe zile ale stagiunii. Fiec rei piese i se asociaz un
unic costum de gurant, deci pentru ecare pies în care joac , Alina trebuie s îmbrace un singur
costum, acela asociat piesei respective. Costumele de guranµi sunt identicate prin literele mari
ale alfabetului englez: A, B, C, ..., X, Y, Z. Alina are voie s -³i aleag cele C costume diferite.
Cerinµe
CAPITOLUL 32. ONI 2008 678
Cunoscând costumul asociat ec rei zile a stagiunii, ajutaµi-o pe Alina s -³i aleag cele C
costume diferite, în a³a fel încât s poat juca într-un num r cât mai mare de piese consecutive.
Date de intrare
Fi³ierul de intrare teatru.in conµine pe prima linie dou numere naturale Z ³i C desp rµite
printr-un spaµiu. Z este num rul de zile din stagiune iar C este num rul de costume diferite pe
care Alina le poate primi. Pe linia a doua, se g sesc Z caractere, litere mari ale alfabetului englez.
Caracterul al i-lea identic costumul de gurant care trebuie îmbr cat în spectacolul din ziua i.
Date de ie³ire
În ³ierul de ie³ire teatru.out se va scrie pe prima linie un num r natural N , reprezentând
num rul maxim de spectacole consecutive în care Alina poate juca. Pe linia a doua se scriu N
caractere, f r spaµii între ele, corespunz toare costumelor care vor îmbr cate în cele N piese
de teatru alese, în ordinea spectacolelor în care va juca. Dac exist mai multe soluµii de lungime
N atunci se a³eaz cea c reia îi corespunde o zi de început mai aproape de începutul stagiunii.
Restricµii ³i preciz ri
a 1 & Z & 55 000
a 1 & C & 26
a C&Z
a Pentru 20% dintre teste Z & 350
Exemple:
teatru.in teatru.out Explicaµii
10 3 5 ...
XKUFKFEGXG KUFKF
15 4 6 ...
IAJRAMRCZJJCDNS AJRAMR
25 5 8 ...
LDSDGIFAURLPTZLDLPNLEGFRN LPTZLDLP
Timp maxim de executare/test: 0.2 secunde Windows, 0.1 secunde Linux
9 void Calculeaza();
10
11 int main()
12 {
13 freopen("teatru.in", "r", stdin);
14 freopen("teatru.out", "w", stdout);
15 Citeste();
16 Calculeaza();
17 Afis();
18 return 0;
19 }
20
21 void Citeste()
22 {
23 scanf("%d%d", &n, &k);
24 scanf("%c", &s[0]); // citeste ’\n’
25 for (long int i = 0; i < n; i++ )
26 scanf("%c", s + i);
27 }
28
29 void Afis()
30 {
31 printf("%d\n", Lmax);
32 for (long int i = imax; i <= jmax; i++ )
33 printf("%c", s[i]);
34 printf("\n");
35 }
36
37 void Calculeaza()
38 {
39 long int i = 0, j = 0, nr = 0;
40 f[s[0]]++; nr++;
41 do
42 {
43 while (nr <= k && j < n)
44 {
45 j++;
46 if ( j >= n ) break;
47 if (f[s[j]] == 0)
48 {
49 f[s[j]]++;
50 nr++;
51 }
52 else f[s[j]]++;
53 }
54
55 if (j - i > Lmax)
56 {
57 Lmax = j - i;
58 imax = i; jmax = j - 1;
59 }
60
61 while ( nr > k )
62 {
63 f[s[i]]--;
64 if ( f[s[i]] == 0 ) nr--;
65 i++;
66 }
67
68 } while (i < n && j < n);
69 }
12 {
13 int i, j, k;
14
15 freopen(FIN, "r", stdin);
16 freopen(FOUT, "w", stdout);
17
18 scanf("%d %d %s", &N, &C, S);
19
20 for (i = 0; i < N; ++i)
21 {
22 memset(cnt, 0, sizeof(cnt));
23 for (j = i, k = 0; j < N && k <= C; ++j)
24 {
25 if (!cnt[S[j]-’A’]) { ++k; cnt[S[j]-’A’] = 1; }
26 if (k == C && bst_len < j-i+1)
27 {
28 bst_len = j-i+1;
29 start = i;
30 }
31 }
32 }
33
34 printf("%d\n", bst_len);
35 for (i = start; i < start+bst_len; ++i)
36 printf("%c", S[i]);
37 printf("\n");
38
39 return 0;
40 }
ONI 2007
33.1 Agitaµie
O rm produc toare de software organizeaz un interviu pentru ocuparea unui post de pro-
gramator, la care s-au prezentat N candidaµi. Ace³tia sunt ordonaµi în funcµiie de momentul la
care ³i-au trimis CV-ul ³i numerotaµi cu numere consecutive de la 1 la N .
Fiec rui candidat i-a fost realizat în prealabil un prol psihologic ³i i s-a determinat nivelul
de agitaµie provocat de interviul care urmeaz s aib loc, precum ³i un sens (cresc tor sau
descresc tor) de modicare a acestui nivel. Astfel, la ora la care s-a anunµat începerea interviului
(pe care o vom considera momentul 0), ecare candidat are un nivel de agitaµie iniµial. Pentru
ecare unitate de timp dup momentul 0 ³i pân în momentul în care candidatul este invitat
pentru interviu (pân atunci el trebuind s a³tepte), nivelul s u de agitaµie se modic cu 1:
pentru o parte din candidaµi nivelul cre³te cu 1 unitate, iar pentru ceilalµi nivelul scade cu 1
unitate. Dac nivelul de agitaµie a unui candidat ajunge la 0, din acel moment, pentru ecare
unitate de timp urm toare, nivelul de agitaµie va cre³te cu 1 (se schimb sensul de modicare a
nivelului de agitaµie).
Firma va invita candidaµii la interviu în grupuri, în ordinea numerot rii (toµi candidaµii având
numere de ordine mai mici decât un candidat K vor invitaµi într-un grup anterior sau în acela³i
grup cu candidatul K ). Înainte de a invita un grup, comisia ce conduce interviul poate decide
s a³tepte un num r întreg de unit µi de timp (zero sau mai multe). Pentru un grup, durata
interviului se consider neglijabil (ecare candidat trebuie doar s r spund la câteva întreb ri
de tip gril ). Din momentul în care un candidat este invitat la interviu, nivelul de agitaµie a
acestuia r mâne constant.
Deoarece rma dore³te ca, indiferent de rezultatul interviului, toµi candidaµii s r mân cu o
p rere bun , comisia va forma grupurile ³i va alege timpii de a³teptare în a³a fel încât suma total
a nivelelor de agitaµie a candidaµilor la sfâr³itul interviului s e minim .
Cerinµ
S se scrie un program care s determine suma total minim a nivelelor de agitaµie a candi-
daµilor la sfâr³itul interviului.
682
CAPITOLUL 33. ONI 2007 683
Date de intrare
Fi³ierul de intrare agitatie.in are pe prima linie num rul natural N , reprezentând num rul
de candidaµi. Pe urm toarele N linii se a câte dou numere întregi A ³i B , separate printr-un
spaµiu. A reprezint nivelul iniµial de agitaµie a candidatului, iar B reprezint sensul de modicare
a agitaµiei pentru ecare unitate de timp în care acesta a³teapt (dac B este 1, atunci nivelul
de agitaµie cre³te, iar dac B este 1, nivelul de agitaµie scade). Linia k 1 din ³ier va conµine
valorile corespunz toare candidatului cu num rul k .
Date de ie³ire
Fi³ierul de ie³ire agitatie.out va conµine pe prima (³i singura) linie suma total minim a
nivelelor de agitaµie a candidaµilor la sfâr³itul interviului.
Restricµii ³i preciz ri
a 1 & N & 3000
a 1 & nivelul iniµial de agitaµie a ec rui candidat & 3000
Exemplu
agitatie.in agitatie.out
6 23
10 1
3 -1
2 -1
1 -1
91
6 -1
Explicaµie:
Suma total minim este 23.
O posibil soluµie este urm toarea: Se formeaz 3 grupuri.
Primul grup este format doar din candidatul 1 ³i a³teapt 0 unit µi de timp. Prin urmare,
nivelul nal de agitaµie a candidatului 1 va 10.
Al doilea grup va a³tepta 2 unit µi de timp din momentul în care a terminat interviul primul
grup (deci va începe interviul la momentul 2), iar din grup vor face parte candidaµii 2, 3, 4 ³i 5.
Nivelele nale de agitaµie a acestor candidaµi vor : 1, 0, 1 ³i 11. Observaµi c nivelul de agitaµie
a candidatului 4 a sc zut întâi pân la 0, apoi a crescut la 1.
Al 3-lea grup va mai a³tepta 4 unit µi de timp (deci va începe interviul la momentul 6), iar
din grup va face parte doar candidatul 6. Nivelul nal de agitaµie a acestuia va 0.
Timp maxim de execuµie/test(Windows/Linux): 0.6 secunde
S presupunem c aceast valoare se obµine pentru poziµia k din vector. Dac SU M k este mai
mic decât 0, atunci introducând o perioad de a³teptare mai mare decât 0 înaintea candidatului
k , suma total a nivelelor de agitaµie va sc dea.
Perioada de timp cu care se m re³te timpul de a³teptare dinaintea candidatului k este m rit
cu valoarea minim a nivelului de agitaµie dintre toµi candidaµii j ' k având sensuri negative de
modicare a agitaµiei. Se modic corespunz tor valorile nivelelor de agitaµie a tuturor candi-
daµilor j ' k , iar pentru toµi candidaµii care ating nivelul de agitaµie 0, se schimb ³i sensul de
modicare a nivelului de agitaµie (din 1 în 1).
Acest algoritm se repet pân în momentul în care valoarea minim din vectorul SU M este
2
mai mare sau egal cu 0. Complexitatea acestei soluµii este O N .
53 {
54 int i,t;
55 for(i=0;i<=n;i++)
56 {
57 for(t=0;t<=tmax;t++) System.out.print(smin[i][t]+"\t");
58 System.out.println();
59 }
60 System.out.println();
61 }// afissmin(...)
62 }// class
33.2 Coduri
Întorcându-se de la ³coal în ziua în care a aat cum se face înmulµirea numerelor, Gigel a
auzit la televizor urm toarea armaµie: "Pentru a face avere, nu trebuie s aduni bani în viaµ ,
ci trebuie s-i înmulµe³ti".
Toate acestea l-au pus pe gânduri, a³a c s-a hot rât s inventeze propriul "sistem de codicare"
pentru numere reale mai mari decât 0 care s aib urm toarele propriet µi:
- ecare num r va codicat sub forma unui ³ir de valori întregi (pozitive ³i/sau negative)
- dac un num r real x are codul cx ³i un num r real y are codul cy , atunci num rul real
rezultat prin înmulµirea lui x ³i y trebuie s aib codul obµinut prin "adunarea" codurilor c x ³i
cy .
- dac un num r real x se poate scrie ca produs de numere y1 , y2 , ..., yk , atunci codul lui x se
obµine prin "adunarea" codurilor numerelor y1 , y2 , ..., yk .
Consider m un cod c1 format din n1 valori an1 ...a1 ³i un cod c2 format din n2 valori bn2 ...b1,
atunci codul c3 obµinut prin "adunarea" codurilor c1 ³i c2 va avea n3 valori dn3 ...d1 , cu propriet µile
urm toare:
an3 este maximul dintre n1 ³i n2
~
ai bi pentru i 1, ..., min n1 , n2
adi
ai pentru i minim n1 , n2 1, ..., n1 dac minim n1 , n2 n2
bi pentru i minim n1 , n2 1, ..., n2 dac minim n1 , n2 n1
Cerinµ
Dându-se N numere reale mai mari strict decât 0, s se scrie codicarea acestora în sistemul
inventat de Gigel.
Date de intrare
Fi³ierul de intrare coduri.in va conµine:
- pe prima linie din ³ier se a num rul N de numere reale
- pe urm toarele N linii cele N numere reale, ecare pe câte o linie.
Date de ie³ire
Fi³ierul de ie³ire coduri.out va conµine N linii:
- pe linia i (i între 1 ³i N ) : num rul de valori folosite pentru codicarea num rului cu indicele
i din ³ierul de intrare, urmat de un spaµiu ³i apoi valorile ce alc tuiesc codul num rului, separate
dou câte dou printr-un singur spaµiu.
Restricµii ³i preciz ri
2 & N & 18
a
Separatorul între partea întreag ³i partea zecimal este virgula.
a
a Orice num r are dup virgul cel mult 5 cifre.
a Valorile din codurile numerelor din ³ierele de test trebuie s e cuprinse în intervalul
106, 106.
a Partea întreag a ec rui num r real este o valoare mai mic sau egal cu 20000.
a Toate numerele din ³ierele de test sunt strict pozitive ³i distincte dou câte dou .
a Num rul maxim de valori utilizat pentru codicarea unui num r este 2500.
a Dac exist mai multe soluµii de codicare, se va a³a una singur .
a Nu trebuie s existe dou numere diferite cu aceea³i codicare.
CAPITOLUL 33. ONI 2007 686
a 40% din teste vor conµine numai numere întregi, 30% din teste vor conµine numere întregi ³i
numere reale f r perioad ³i 30% din teste vor conµine numere întregi ³i numere reale cu ³i f r
perioad .
Exemplu
coduri.in coduri.out Explicaµii
8 2 11
10 3 -1 0 1 10=2*5 iar suma codurilor pentru 2 ³i 5
2 3 110 determin codul lui 10
5 3 210
0,3 3 -1 2 1 2,1=7*0,3 iar suma codurilor pentru 7 ³i 0,3
7 3 131 determin codul lui 2,1
2,1 2 1 11
1,(7) 2 12
1,2(34)
Timp maxim de execuµie/test(Windows/Linux): 0.2 secunde
26 nr1=0;
27 for(j=0;j<nr.length();j++)
28 if(nr.charAt(j)==’,’) break;
29 else nr1=nr1*10+nr.charAt(j)-’0’;
30
31 //System.out.print(i+" : "+nr+" --> ");
32
33 if(j==nr.length()) // intreg
34 {
35 x=nr1;
36 y=1;
37
38 //System.out.println("x = "+x+" y = "+y);
39
40 if(x==1) // 1 nu se mai desxcompune ... are codul "0"
41 {
42 out.println("1 0");
43 continue;
44 }
45
46 descfact(x,f1);
47 iuf1=iuf;
48
49 out.print(iuf1+" ");
50 for(k=iuf1;k>=2;k--) out.print(f1[k]+" ");
51 out.println(f1[1]);
52
53 continue;
54 }// if intreg
55
56 nr2=0;
57 for(k=j+1;k<nr.length();k++)
58 if(nr.charAt(k)==’(’) break;
59 else nr2=nr2*10+nr.charAt(k)-’0’;
60
61 if(k==nr.length()) // real neperiodic
62 {
63 x=nr1;
64 y=1;
65 aux=nr2;
66 while(aux!=0) { x*=10; y*=10; aux/=10;}
67 x+=nr2;
68
69 descfact(x,f1);
70 iuf1=iuf;
71
72 descfact(y,f2);
73 iuf2=iuf;
74
75 iuf=max(iuf1,iuf2);
76 out.print(iuf+" ");
77 for(k=iuf;k>=2;k--)
78 {
79 if(k<=iuf1 && k<=iuf2) out.print((f1[k]-f2[k])+" "); else
80 if(k<=iuf1)
81 out.print(f1[k]+" ");
82 else
83 out.print(-f2[k]+" ");
84 }
85 out.println(f1[1]-f2[1]);
86
87 continue;
88 }// if real neperiodic
89
90 // real periodic (nr1-nr2)/nr3
91 aux=nr2;
92 n10=1;
93 while(aux!=0) {nr1*=10; aux/=10; n10=n10*10;}
94 nr1+=nr2;
95 nr2=nr1;
96 nr3=0;
97 for(j=k+1;j<nr.length()-1;j++)
98 {
99 nr1=nr1*10+nr.charAt(j)-’0’;
100 nr3=nr3*10+9;
101 }
CAPITOLUL 33. ONI 2007 688
102 nr3=nr3*n10;
103 x=nr1-nr2;
104 y=nr3;
105
106 descfact(x,f1);
107 iuf1=iuf;
108 descfact(y,f2);
109 iuf2=iuf;
110
111 iuf=max(iuf1,iuf2);
112 out.print(iuf+" ");
113 for(k=iuf;k>=2;k--)
114 {
115 if(k<=iuf1 && k<=iuf2) out.print((f1[k]-f2[k])+" "); else
116 if(k<=iuf1)
117 out.print(f1[k]+" ");
118 else
119 out.print(-f2[k]+" ");
120 }
121 out.println(f1[1]-f2[1]);
122
123 }// for i
124
125 out.close();
126 }// main(...)
127
128 static void descfact(int nr, int[] f)
129 {
130 int i;
131 i=1;
132 f[1]=0;
133 while(nr>1)
134 {
135 while(nr%p[i]==0) {f[i]++; nr/=p[i];}
136 i++;
137 f[i]=0;
138 }
139 iuf=i-1;
140 }// descfact(...)
141
142 static void nrprime()
143 {
144 int i,j;
145 boolean ok;
146 int k;
147 p[1]=2; p[2]=3; p[3]=5; p[4]=7; p[5]=11;
148 p[6]=13; p[7]=17; p[8]=19; p[9]=23; // gata ...
149 k=9;
150 for(i=29;i<=99999;i=i+2)
151 {
152 ok=true;
153 for(j=2; j<=k && p[j]*p[j]<=i && ok; j++)
154 if(i%p[j]==0) ok=false;
155 if(ok)
156 {
157 p[++k]=i;
158 }
159 }// for
160 }// nrprime(...)
161
162 static int max(int a, int b)
163 {
164 if(a>b) return a; else return b;
165 }// max(...)
166 }// class
33.3 Lacuri
Pe un teren de form p trat sunt zone de uscat ³i lacuri. Harta terenului este memorat
într-un tablou bidimensional n n cu valori 1 (ap ) sau 0 (uscat). Liniile sunt numerotate de la
1 la n, de sus în jos ³i coloanele de la 1 la n, de la stânga la dreapta. Fiecare lac este înconjurat
CAPITOLUL 33. ONI 2007 689
de o suprafaµ de teren uscat. Excepµie fac doar lacurile situate la marginea terenului care sunt
înconjurate de uscat doar prin interiorul terenului nu ³i prin afara acestuia.
Cerinµ
Se dore³te s se traverseze terenul pe uscat, de la poziµia 1, 1 la poziµia n, n, pe un drum
de lungime minim , mergând pas cu pas. La un pas, se ajunge de la un p tr µel la altul învecinat
cu el spre nord, est, sud sau vest.
S se scrie un program care:
a Determin num rul lacurilor care sunt de form p trat ³i în acela³i timp sunt "pline de
1".
b În cazul în care toate lacurile sunt de form p trat ³i în acela³i timp "pline de 1", deter-
minaµi un drum cu proprietatea de mai sus.
Date de intrare
Fi³ierul de intrare lacuri.in are pe prima linie num rul n, iar pe urm toarele n linii este harta
terenului (ecare linie are n valori 0 sau 1, separate de câte un spaµiu).
Date de ie³ire
Fi³ierul de ie³ire lacuri.out va conµine:
a pe prima linie: num rul de lacuri ce sunt de form p trat ³i în acela³i timp "pline de 1";
a în cazul în care toate lacurile sunt de form p trat ³i în acela³i timp "pline de 1", urmeaz
liniile ce descriu drumul de lungime minim ales. Fiecare linie din ³ier conµine câte o pereche de
coordonate ale poziµiilor succesive prin care trece drumul (linia ³i coloana, separate cu un spaµiu),
începând cu 1, 1 ³i terminând cu n, n.
Restricµii ³i preciz ri
a 2 & n & 100
a Poziµiile 1, 1 ³i n, n sunt sigur libere (cu valoarea 0).
a Dac exist mai multe soluµii se va a³a oricare dintre ele.
a Pot cel mult 100 de lacuri ³i cel puµin unul; dac un lac este de form p trat , atunci
1 & latura & n 1.
a Indiferent de forma lor, lacurile sunt sigur "izolate", adic nu se "ating" deloc de alt lac. De
exemplu, dac un lac conµine poziµia 3, 3, atunci un alt lac nu poate conµine vreuna din poziµiile
învecinate cu 3, 3, adic : 2, 3, 2, 4, 3, 4, 4, 4, 4, 3, 4, 2, 3, 2 ³i 2, 2.
a Pentru cerinµa a se acord 30% din punctaj, iar pentru cerinµa b) se acord 70% din punctaj.
Exemplu
lacuri.in lacuri.out
6 4
0 0 0 0 0 0 1 1
0 1 0 1 1 1 1 2
0 0 0 1 1 1 1 3
0 0 0 1 1 1 2 3
1 1 0 0 0 0 3 3
1 1 0 0 1 0 4 3
5 3
5 4
5 5
5 6
6 6
Explicaµie:
a Prima linie conµine 4 (sunt 4 lacuri de form p trat ³i "pline de 1")
b Deoarece toate cele 4 lacuri sunt de form p trat ³i "pline de 1", se scrie ³i drumul ales:
de la 1, 1, 1, 2, 1, 3, 2, 3, 3, 3, ...., (6, 6.
Observaµii:
1 Dac în poziµia 3, 5 ar fost un 0, atunci lacul cu latura 3 nu ar mai fost "plin de 1" ³i
atunci prima linie ar conµinut doar valoarea 3 (ar fost doar 3 lacuri p trate ³i "pline de 1").
2 în exemplul iniµial, dac în poziµia 6, 1 ar fost valorea 0, atunci nu ar fost toate lacurile
p trate (cel din stânga-jos nu ar fost p trat) ³i s-ar a³at doar un 3 în ?ierul de ie³ire.
3 în exemplul iniµial, dac în poziµia 5, 2 ar fost valoarea 0, atunci s-ar a³at doar un
3, pentru c lacul din stânga-jos nu ar un lac p trat ³i "plin de 1".
CAPITOLUL 33. ONI 2007 690
36 else
37 {
38 out.println(np);
39 System.out.println("DA ... "+np);
40 out.println("1 1");
41 i=1; // casuta pusa
42 j=2; // prima casuta mai departe (libera sau ocupata)
43 while(j<=n)
44 {
45 while(b[j][j]==1) j++;
46 System.out.println("i = "+i+" j = "+j);
47
48 if(j==i+1) // casute apropiate
49 {
50 if(b[i][i+1]==0)
51 out.println(i+" "+(i+1));
52 else
53 out.println((i+1)+" "+i);
54 out.println(j+" "+j);
55 i=j;
56 j=i+1;
57 }
58 else // casute departate i=pus j=nepus
59 {
60 if(b[i+1][i]==0) // in jos, apoi dreapta
61 {
62 for(k=i+1;k<=j;k++) out.println(k+" "+i);
63 for(k=i+1;k<=j;k++) out.println(j+" "+k);
64 }
65 else // dreapta, apoi in jos
66 {
67 for(k=i+1;k<=j;k++) out.println(i+" "+k);
68 for(k=i+1;k<=j;k++) out.println(k+" "+j);
69 }
70 i=j;
71 j=j+1;
72 }// else casute departate
73 }// while
74 }// else, toate patratele sunt pline de 1
75 out.close();
76 }// main
77
78 static boolean suntnumaipatrate()
79 {
80 int i,j,i0,j0,i1,j1;
81 boolean ok,okfin;
82
83 okfin=true;
84 for(i0=1;i0<=n;i0++)
85 for(j0=1;j0<=n;j0++)
86 if(a[i0][j0]==1)
87 {
88 ok=true;
89 for(j1=j0+1;j1<=n+1;j1++) if(a[i0][j1]==0) break;
90 j1--;
91 for(i1=i0+1;i1<=n+1;i1++) if(a[i1][j0]==0) break;
92 i1--;
93 System.out.print("patrat posibil: "+i0+" "+j0+" "+i1+" "+j1);
94
95 // verificare interior
96 for(i=i0+1;i<=i1-1 && ok;i++)
97 for(j=j0+1;j<=j1-1 && ok;j++)
98 if(a[i][j]==0) ok=false;
99
100 // verificare stanga
101 for(i=i0;i<=i1 && ok;i++)
102 if(a[i][j0-1]==1) ok=false;
103
104 // verificare dreapta
105 for(i=i0;i<=i1 && ok;i++)
106 if(a[i][j1+1]==1) ok=false;
107
108 // verificare sus
109 for(j=j0;j<=j1 && ok;j++)
110 if(a[i0-1][j]==1) ok=false;
111
CAPITOLUL 33. ONI 2007 692
33.4 Secv
Se d un ³ir de N numere întregi A1 , A2 , ..., AN . Asupra acestui ³ir se poate efectua urm toarea
operaµie: se împarte ³irul în 3 secvenµe nevide, se calculeaz valoarea maxim din ecare secvenµ
³i apoi se face suma acestor valori. Cu alte cuvinte se aleg doi indici 0 $ i $ j $ N ³i se calculeaz
valorile
X maxrAk ¶1 & k & ix,
Y maxrAk ¶i 1 & k & j x,
Z maxrAk ¶j 1 & k & N x
³i suma S X Y Z .
Cerinµ
Calculaµi valoarea minim a lui S care se poate obµine în urma unei astfel de operaµii ³i
determinaµi cei doi indici care separ secvenµele pentru a obµine aceast valoare.
Date de intrare
Prima linie a ³ierului de intrare secv.in conµine un num r natural N reprezentând num rul
de elemente al ³irului de intrare, iar a doua linie conµine numerele întregi A1 , A2 , ..., AN separate
prin câte un spaµiu.
Date de ie³ire
Fi?³erul de ie³ire secv.out va conµine:
- pe prima linie: valoarea minim a sumei;
- pe a doua linie: dou numere naturale i, j separate printr-un spaµiu, reprezentând indicii
pentru care se obµine valoarea minim pentru S prin aplicarea operaµiei descrise mai sus.
Restricµii ³i preciz ri
a 3 & N & 30000
a A1 , A2 , ..., AN sunt numere întregi din intervalul 10000, 10000
CAPITOLUL 33. ONI 2007 693
a în cazul în care exist mai multe soluµii se poate a³a oricare dintre ele.
Exemplu
secv.in secv.out Explicaµii
7 10 Prima secvenµ : 3 2 - maximul este 3
3215632 23 A doua secvenµ : 1 - maximul este 1
A treia secvenµ : 5 6 3 2 - maximul este 6
Suma: 10
Timp maxim de execuµie/test: 0.1 secunde
33 s1=oo; // minim
34 for(i=imax+1;i<=n-1;i++)
35 {
36 y=a[i];
37 z=-oo;
38 for(j=i+1;j<=n;j++) if(a[j]>z) { z=a[j]; j1=j;}
39 if(x+y+z<s1) { s1=x+y+z; i1=i; j1=i1+1;}
40 }// for
41 }// if
42
43 // x in a doua secventa
44 if((imax>1)&&(imax<n))
45 {
46 s2=max+a[1]+a[n];
47 i2=1;
48 j2=n-1;
49 }
50
51 // max in a treia secventa
52 if(imax>=3)
53 {
54 z=max;
55 s3=oo; // minim
56 for(j=2;j<=imax-1;j++)
57 {
58 y=a[j];
59 x=0;
60 for(i=1;i<=j;i++) if(a[i]>x) {x=a[i]; i3=i;}
61 if(x+y+z<s3) { s3=x+y+z; j3=j;}
62 }// for
63 i3=j3-1;
64 }// if
65
66 smin=min(min(s1,s2),s3);
67 out.println(smin);
68 if(smin==s1) out.println(i1+" "+j1); else
69 if(smin==s2) out.println(i2+" "+j2); else
70 out.println(i3+" "+j3);
71 out.close();
72 }// main
73
74 static int min(int a, int b)
75 {
76 if(a<b) return a; else return b;
77 }// min(...)
78 }// class
33.5 otron
Pe asfalt este desenat cu cret un ³otron, caroiaj format din n n c suµe având acelea³i
dimensiuni (câte n c suµe pe ecare din cele n rânduri).
În ecare c suµ este scris câte un num r întreg din intervalul 100, 100. Fiecare juc tor are
câte o piatr pe care o arunc într-o c suµ a ³otronului, ³i s rind într-un picior, împinge piatra
din c suµ în c suµ , pe un anumit traseu astfel încât punctajul obµinut din suma numerelor de
pe traseul parcurs s e cât mai mare.
Numerele din c suµele ³otronului sunt scrise cu dou culori albastru ³i alb, astfel încât s nu
existe dou c suµe al turate (pe cele patru direcµii Nord, Est, Sud, Vest) având numere scrise cu
aceea³i culoare. Întotdeauna, prima c suµ din primul rând al ³otronului are înscris un num r de
culoare albastr .
Se stabilesc apoi, urm toarele reguli ale jocului:
- la începutul jocului, piatra poate aruncat în oricare c suµ a ³otronului. Din poziµia
respectiv juc torul î³i conduce piatra pân la sfâr³itul traseului stabilit de el;
- dintr-o c suµ în care num rul este scris cu albastru, piatra poate deplasat doar în c suµa
vecin pe direcµia Nord;
- dintr-o c suµ în care num rul este scris cu alb, piatra poate deplasat doar în c suµa
vecin pe direcµia Est;
- juc torul poate alege orice c suµ (inclusiv cea în care a aruncat piatra) pentru a încheia
jocul, atâta timp cât piatra nu iese din ³otron.
CAPITOLUL 33. ONI 2007 695
Cerinµ
S se scrie un program care s determine cel mai mare punctaj care se poate obµine jucând
³otron dup regulile stabilite.
Date de intrare
Fi³ierul de intrare sotron.in are pe prima linie dimensiunea n a ³otronului, iar pe urm toarele
n linii câte n numere separate de câte un spaµiu, reprezentând numerele scrise în ³otron.
Date de ie³ire
Fi³ierul de ie³ire sotron.out va conµine pe prima linie un singur num r reprezentând punctajul
maxim care se poate obµine jucând ³otron.
Restricµii ³i preciz ri
1 & n & 240
Exemplu
secv.in secv.out Explicaµii
5 21
0 -6 -5 -17 2 Punctajul obµinut este
1 -4 7 10 5 3+(-2)+3+7+10=21
-3 -2 3 -8 -8
-20 3 5 3 -5
-10 -15 2 2 -4
Timp maxim de execuµie/test(Windows/Linux): 0.1 secunde
Pentru a calcula punctajul maxim obµinut de un juc tor, se calculeaz pentru ecare astfel
de traseu suma maxim a numerelor unei succesiuni de c suµe vecine. Numerele scrise într-un
traseu determinant la un moment dat se pot memora într-un vector, astfel, acest problem este
echivalent cu determinarea unei secvenµe de sum maxim dintr-un vector.
CAPITOLUL 33. ONI 2007 696
68 }// main(...)
69
70 static int secvsummax(int n)
71 {
72 int i,i1,i2,ic,sc,smax;
73 i1=i2=ic=1;
74 smax=sc=x[1];
75 for(i=2;i<=n;i++)
76 {
77 if(sc<=0) { ic=i; sc=x[i]; continue; } else sc=sc+x[i];
78 if(sc>=smax) { smax=sc; i1=ic; i2=i; }
79 }
80 //System.out.println("smax = "+smax+" x["+i1+"..."+i2+"]");
81 return smax;
82 }// secvsummax(...)
83 }// class
33.6 Triunghi
În comuna Triunghi din România sunt n µ rani codicaµi prin numerele 1, 2, ..., n. Dup
anul 1990 a început retrocedarea suprafeµelor de p mânt deµinute înainte de colectivizare. Fiecare
µ ran are un document prin care dovede³te c este proprietar pe o singur suprafaµ de teren de
form triunghiular . Din p cate, documentele dau b taie de cap primarului (care se ocup de
retrocedarea suprafeµelor de p mânt), pentru c sunt porµiuni din suprafeµele de p mânt care se
reg sesc pe mai multe documente.
În aceast comun exist o fântân cu ap , ind posibil ca ea s e revendicat de mai mulµi
µ rani. O suprafaµ de p mânt este dat prin coordonatele celor trei colµuri, iar fântâna este
considerat punctiform ³i dat prin coordonatele punctului.
Cerinµ
S se scrie un program care s determine:
a Codurile µ ranilor care au documente cu suprafeµe de p mânt ce conµin în interior sau pe
frontier fântâna.
b Codul µ ranului ce deµine un document cu suprafaµa de teren, care include toate celelalte
suprafeµe.
Date de intrare
Fi³ierul de intrare triunghi.in are pe prima linie num rul n de µ rani, pe urm toarele n linii
câte 6 valori numere întregi separate prin câte un spaµiu, în formatul: x1 y1 x2 y2 x3 y3, ce
reprezint coordonatele celor trei colµuri ale suprafeµei triunghiulare deµinute de un µ ran (x1, x2,
x3 abscise, iar y1, y2, y3 ordonate). Pe linia i 1 se a coordonatele colµurilor suprafeµei de
teren triunghiulare deµinute de µ ranul i, i 1, 2, ..., n. Ultima linie a ³ierului (linia n 2) va
conµine coordonatele fântânii în formatul x y , cu un spaµiu între ele (x abscis , iar y ordonat ).
Date de ie³ire
Fi³ierul de ie³ire triunghi.out va conµine pe prima linie r spunsul de la punctul a, adic :
num rul de µ rani care îndeplinesc condiµia din cerinµ ³i apoi codurile lor (în ordine cresc toare),
cu un spaµiu între ele. Dac nu exist µ rani cu condiµia din cerinµ , pe prima linie se va scrie cifra
0. Pe linia a doua se va scrie r spunsul de la punctul b, adic : codul µ ranului cu proprietatea
cerut , sau cifra 0, dac nu exist un astfel de µ ran.
Restricµii ³i preciz ri
a 2 & n & 65
a coordonatele colµurilor suprafeµelor de p mânt ³i ale fântânii sunt numere întregi din inter-
valul 3000, 3000
a cele trei colµuri ale ec rei suprafeµe de p mânt sunt distincte ³i necoliniare
a nu exist doi µ rani care s deµin aceea³i suprafaµ de p mânt
a nu se acord punctaje parµiale.
Exemplu
CAPITOLUL 33. ONI 2007 698
secv.in secv.out
3 212
10 0 0 10 10 10 2
0 100 100 0 -100 0
0 0 10 0 0 10
10 5
Explicaµie:
La punctul a, sunt doi µ rani care deµin suprafeµe de p mânt ce au în interior sau pe frontier
fântâna, cu codurile 1 ³i 2.
La punctul b, µ ranul cu codul 2 deµine o suprafaµ de teren care include, suprafeµele de
p mânt deµinute de ceilalµi µ rani (cu codurile 1 ³i 3).
Timp maxim de execuµie/test: 0.1 secunde
24 for(i=1;i<=n;i++)
25 {
26 st.nextToken(); x1[i]=(int)st.nval;
27 st.nextToken(); y1[i]=(int)st.nval;
28 st.nextToken(); x2[i]=(int)st.nval;
29 st.nextToken(); y2[i]=(int)st.nval;
30 st.nextToken(); x3[i]=(int)st.nval;
31 st.nextToken(); y3[i]=(int)st.nval;
32 }
33 st.nextToken(); x0=(int)st.nval;
34 st.nextToken(); y0=(int)st.nval;
35 for(i=1;i<=n;i++)
36 {
37 s=aria(x1[i],y1[i],x2[i],y2[i],x3[i],y3[i]);
38 if(s>smax) {smax=s; imax=i;}
39 s1=aria(x1[i],y1[i],x2[i],y2[i],x0,y0);
40 s2=aria(x2[i],y2[i],x3[i],y3[i],x0,y0);
41 s3=aria(x1[i],y1[i],x3[i],y3[i],x0,y0);
42 if(s==s1+s2+s3) {nr++; sol[nr]=i;}
43 //System.out.println("i = "+i+" --> "+s+" "+s1+" "+s2+" "+s3);
44 }
45 if(nr>0)
46 {
47 out.print(nr+" ");
48 for(i=1;i<=nr;i++)
49 if(i!=nr) out.print(sol[i]+" "); else out.println(sol[i]);
50 }
51 else out.println(0);
52
53 //System.out.println("imax = "+imax);
54 ok=true;
55 for(i=1;i<=n;i++)
56 {
57 if(i==imax) continue;
58
59 s1=aria(x1[imax],y1[imax],x2[imax],y2[imax],x1[i],y1[i]);
60 s2=aria(x2[imax],y2[imax],x3[imax],y3[imax],x1[i],y1[i]);
61 s3=aria(x1[imax],y1[imax],x3[imax],y3[imax],x1[i],y1[i]);
62 if(smax!=s1+s2+s3) { ok=false; break; }
63
64 s1=aria(x1[imax],y1[imax],x2[imax],y2[imax],x2[i],y2[i]);
65 s2=aria(x2[imax],y2[imax],x3[imax],y3[imax],x2[i],y2[i]);
66 s3=aria(x1[imax],y1[imax],x3[imax],y3[imax],x2[i],y2[i]);
67 if(smax!=s1+s2+s3) { ok=false; break; }
68
69 s1=aria(x1[imax],y1[imax],x2[imax],y2[imax],x3[i],y3[i]);
70 s2=aria(x2[imax],y2[imax],x3[imax],y3[imax],x3[i],y3[i]);
71 s3=aria(x1[imax],y1[imax],x3[imax],y3[imax],x3[i],y3[i]);
72 if(smax!=s1+s2+s3) { ok=false; break; }
73 }
74 if(ok) out.println(imax); else out.println(0);
75 out.close();
76 }// main(...)
77
78 static int aria(int x1, int y1, int x2, int y2, int x3, int y3) // dubla ...
79 {
80 int s=x1*y2+x2*y3+x3*y1-y1*x2-y2*x3-y3*x1;
81 if(s<0) s=-s;
82 return s;
83 }
84 }// class
Capitolul 34
ONI 2006
34.1 Factorial
autor Mânz Victor Liceul
teoretic "C. Brancoveanu" Bucuresti
Pentru un num r natural nenul, denim factorialul s u ca ind produsul tuturor numerelor
naturale nenule mai mici sau egale decât el ³i îl not m N ! (adic N ! 1 2 ... N ). Pentru
o baz de numeraµie B ³i un num r natural nenul N , se cere determinarea ultimei cifre nenule a
scrierii în baza B a lui N !.
Cerinµ
Se citesc 5 perechi de forma Ni , Bi , unde 1 & i & 5. Pentru ecare din cele 5 perechi citite,
aaµi ultima cifr nenul a scrierii în baza Bi a factorialului num rului Ni .
Date de intrare
Fi³ierul de intrare fact.in conµine 5 linii, pe ecare dintre ele ind scrise câte dou numere
naturale nenule Ni ³i Bi , scrise în baza 10, desp rµite printr-un spaµiu.
Date de ie³ire
Fi³ierul de ie³ire fact.out va conµine 5 linii. Pe linia i se va aa cifra corespunz toare unei
perechi Ni , Bi , citit de pe linia i din ³ierul de intrare.
Restricµii ³i preciz ri
1 & Ni & 1000000, pentru 1 & i & 5;
2 & Bi & 36, pentru 1 & i & 5;
în cazul în care Bi % 10, cifrele mai mari decât 9 vor reprezentate prin litere mari ale
¬ ¬ ¬ ¬ ¬ ¬
alfabetului englez (10 A , 11 B ,...,35 Z );
un test va punctat doar dac toate cele 5 rezultate cerute sunt corecte.
700
CAPITOLUL 34. ONI 2006 701
Exemplu
.in .out Explicaµie
5 10 2 5! 120, în baza 10, deci ultima cifr nenul este 2
7 10 4 7! 5040, în baza 10, deci ultima cifr nenul este 4
7 20 C 7! CC0, în baza 20, deci ultima cifr nenul este C
8 16 8 8! 9D80, în baza 16, deci ultima cifr nenul este 8
9 8 6 9! 1304600, în baza 8, deci ultima cifr nenul este 6
Timp maxim de execuµie/test: 1 secund (Windows), 0.3 secunde (Linux)
Soluµia comisiei
Se descompune mai întâi B în produs de factori primi. Retinem în di0 factorul prim
cu numarul de ordine i ³i în di1 puterea la care apare acesta în descompunerea lui B .
Apoi se parcurg numerele de la 1 la N ³i din ecare dintre acestea se elimin toµi factorii primi
ai lui B , reµinuµi în di0. Se p streaz totodat în di2 puterea la care ar aparut ace³tia
în descompunerea lui N !. Odat cu eliminarea factorilor primi ai lui B din N !, se calculeaz ³i
restul la împ rµirea cu B al produsului (notat p).
Se calculeaz apoi num rul de zerouri consecutive care se vor aa la sfâr³itul lui N !, reprezentat
în baza B : minimul rapoartelor dintre di2 ³i di1, notat min. Se face diferenta între di2
³i min di1, adic num rul de elemente di0 care mai trebuie înmulµite cu p ³i se fac aceste
înmulµiri moduloB . Acesta este rezultatul c utat.
40 {
41 long n,b,i,j;
42 long x[lmax];
43
44 fin=fopen("fact.in","r");
45 fout=fopen("fact.out","w");
46 for(i=1;i<=5;i++)
47 {
48 fscanf(fin,"%ld %ld",&n,&b);
49 x[0]=x[1]=1;
50 for(j=1;j<=n;j++)
51 multiply(x,j,b);
52 print(x);
53 for(j=0;j<lmax;j++) x[j]=0;
54 }
55 fclose(fin);
56 fclose(fout);
57 return 0;
58 }
54 if(d[i][2]/d[i][1]<min)
55 min=d[i][2]/d[i][1];
56 return min;
57 }
58
59 long calcul()
60 {
61 long i,j,p=cifra();
62 long min=minim();
63 for(i=0;i<nr;i++)
64 for(j=0;j<d[i][2]-d[i][1]*min;j++)
65 p=(p*d[i][0])%b;
66 return p;
67 }
68
69 void scrie()
70 {
71 long x=calcul();
72 if(x<10)
73 fprintf(fout,"%ld\n",x);
74 else
75 fprintf(fout,"%c\n",’A’+(x-10));
76 }
77
78 int main()
79 {
80 for(int i=0;i<T;i++)
81 {
82 fscanf(fin,"%ld%ld",&n,&b);
83 desc(b);
84 scrie();
85 }
86
87 fclose(fin);
88 fclose(fout);
89 return 0;
90 }
33 for(j=1;j<=m;j++) en[j]=0;
34 for(i=2;i<=n;i++) // n!
35 {
36 ii=i;
37 for(j=1;j<=m;j++) while(ii%fb[j]==0) { en[j]++; ii/=fb[j]; }
38 p=(p*(ii%b))%b;
39 }
40
41 min=en[1]/eb[1];
42 for(j=2;j<=m;j++) if(en[j]/eb[j]<min) min=en[j]/eb[j];
43 for(j=1;j<=m;j++) en[j]=en[j]-min*eb[j];
44 for(j=1;j<=m;j++) for(i=1;i<=en[j];i++) p=(p*(fb[j]%b))%b;
45 }// calcul()
46
47 public static void main(String[] args) throws IOException
48 {
49 int k;
50 StreamTokenizer st=new StreamTokenizer(
51 new BufferedReader(new FileReader("fact.in")));
52 PrintWriter out=new PrintWriter(
53 new BufferedWriter(new FileWriter("fact.out")));
54
55 for(k=1;k<=5;k++)
56 {
57 st.nextToken(); n=(int)st.nval;
58 st.nextToken(); b=(int)st.nval;
59 calcul();
60 if(p<=9) out.println(p); else out.println((char)(p-10+’A’));
61 }
62 out.close();
63 }// main(...)
64 }// class
34.2 Limbaj
autor Domsa Ovidiu
Universitatea 1 Decembrie 1918 Alba Iulia
Denim un limbaj de programare, cu instrucµiuni de atribuire ³i de decizie. Sintaxa instruc-
µiunilor este:
Instrucµiunea de atribuire
variabila=variabila
Instrucµiunea de decizie
if
semn variabila variabila
{da
instrucµiuni }
{ nu
instrucµiuni }
Variabilele limbajului sunt identicate printr-un singur caracter, liter mic , din alfabetul
englez. Valorile variabilelor sunt de tip întreg.
semn este unul din caracterele $ , % sau
¬ ¬ ¬ ¬ ¬ ¬
.
Liniile instrucµiunilor nu conµin spaµii.
Instrucµiunile din { } pot lipsi.
Cerinµ
Dac se dau valorile iniµiale ale tuturor variabilelor (de la a la z ), în ordine alfabetic începând
cu a, se cer valorile tuturor variabilelor de la a la z , dup execuµia secvenµei de program.
Date de intrare
Fi³ier de intrare: limbaj.in
Linia 1: Va Vb ... Vz - Valorile iniµiale ale variabilelor, de la a la z , separate prin câte un
spaµiu.
Linia 2: linie de program - Urm toarele linii, pân la sfâr³itul ³ierului conµin linii de program,
CAPITOLUL 34. ONI 2006 705
Exemplu
limbaj.in
13574000000000000000000000
if
=ab
nu
if
$ab
da
b=d
f=d
limbaj.out
17574070000000000000000000
Timp maxim de execuµie/test: 0.5 secunde (Windows), 0.1 secunde (Linux)
Soluµia comisiei
Soluµia problemei const în parcurgerea liniar a instrucµiunilor linie cu linie ³i p strarea
valorilor logice ale condiµiilor ³i respectiv a ramurilor da ³i nu într-un ³ir.
Semnicaµia poziµiei din ³ir este nivelul de imbricare la care ne a m. Practic parcurgem, f r
a evalua, acele instrucµiuni care nu aparµin nivelului ³i ramurii pe care ne a m.
În acest sens vom evalua instrucµiunile de atribuire doar cele care îndeplinesc condiµiile de a
se aa pe nivelul corespunz tor ³i pentru care valorile condiµiilor ³i respectiv a ramurilor sunt în
aceal³i timp adevarate.
16 {
17 freopen("limbaj.in","rt",stdin);
18 freopen("limbaj.out","wt",stdout);
19
20 int v[26];
21 int nivel[2500];
22
23 memset(nivel,0,2500*sizeof(int));
24
25 int niv=0;
26 for(int i=0;i<26;i++)
27 scanf("%d",&v[i]);
28
29 int flag=0;
30 char string[200];
31
32 while(scanf("%s",string)>0)
33 {
34 to_lower(string);
35
36 if(flag=1 && strlen(string)==3 && string[1]==’=’)
37 {
38 v[string[0]-97]=v[string[2]-97];
39 continue;
40 }
41
42 if(!strcmp(string,"if"))
43 {
44 scanf("%s",string);
45 if(string[0]==’=’)
46 if(v[string[1]-97]==v[string[2]-97])
47 nivel[niv]=1;
48
49 if(string[0]==’>’)
50 if(v[string[1]-97]>v[string[2]-97])
51 nivel[niv]=1;
52
53 if(string[0]==’<’)
54 if(v[string[1]-97]<v[string[2]-97])
55 nivel[niv]=1;
56
57 niv++;
58 continue;
59 }
60
61 if(!strcmp(string,"fi"))
62 {
63 nivel[niv-1]=0;
64 niv--;
65 }
66
67 //sar peste toate liniile din da, daca asta e fals
68 if((!strcmp(string,"da")) && (nivel[niv-1]==0))
69 {
70 flag=0;
71 char string1[10];
72 int niv1=0;
73 while(flag==0)
74 {
75 scanf("%s",string1);
76 if(!strcmp(string1,"if")) niv1++;
77 if(!strcmp(string1,"fi")&&(niv1>0)) niv1--;
78 if(!strcmp(string1,"fi")&&(niv1==0)) flag=1;
79 if(!strcmp(string1,"nu")&&(niv1==0)) flag=1;
80 }
81
82 continue;
83 }
84
85 //sar peste toate liniile din nu, daca asta e fals
86 if((!strcmp(string,"nu")) && (nivel[niv-1]==1))
87 {
88 flag=0;
89 char string1[10];
90 int niv1=0;
91 while(flag==0)
CAPITOLUL 34. ONI 2006 707
92 {
93 scanf("%s",string1);
94 if(!strcmp(string1,"if")) niv1++;
95 if(!strcmp(string1,"fi")&&(niv1>0)) niv1--;
96 if(!strcmp(string1,"fi")&&(niv1==0)) flag=1;
97 }
98 continue;
99 }
100 }
101
102 //afisarea
103 for(int j=0;j<26;j++)
104 printf("%d ",v[j]);
105 printf("\n");
106
107 return 0;
108 }
51 }// blocda(...)
52
53 static void blocnu(boolean ok) throws IOException
54 {
55 System.out.println(" --> blocNU: "+s+" ok="+ok); //br.readLine();
56 bloc(ok);
57 System.out.println(" <-- blocNU: "+s+" ok="+ok); //br.readLine();
58 }// blocnu(...)
59
60 static void blocif(boolean ok) throws IOException
61 {
62 System.out.println(" --> blocif: "+s+" ok="+ok); //br.readLine();
63 boolean oke=false;
64
65 // urmeaza expresia logica (conditia din IF)
66 s=brin.readLine(); a=s.toCharArray();
67 System.out.println("evaluare expresie: "+s+" --> oke = "+oke+" ok="+ok);
68 //br.readLine();
69 afisx();
70
71 if(a[0]==’=’ && x[a[1]-’a’] == x[a[2]-’a’]) oke=true; else
72 if(a[0]==’<’ && x[a[1]-’a’] < x[a[2]-’a’]) oke=true; else
73 if(a[0]==’>’ && x[a[1]-’a’] > x[a[2]-’a’]) oke=true;
74
75 // urmeaza "DA" sau "NU"
76 s=brin.readLine(); a=s.toCharArray();
77
78 System.out.println(" ? bloc DA ? s= "+s);
79 if(esteda())
80 {
81 s=brin.readLine(); a=s.toCharArray();
82 blocda(ok && oke);
83 }
84
85 System.out.println(" ? bloc NU ? s= "+s);
86 if(estenu())
87 {
88 s=brin.readLine(); a=s.toCharArray();
89 blocnu(ok && !oke);
90 }
91
92 s=brin.readLine(); if(s!=null) a=s.toCharArray();
93 System.out.println(" <-- blocif: "+s+" ok="+ok); //br.readLine();
94 }// blocif(...)
95
96 static void blocatr(boolean ok) throws IOException
97 {
98 System.out.println(" --> blocatr: "+s+" ok="+ok); //br.readLine();
99 if(ok) x[a[0]-’a’]=x[a[2]-’a’];
100
101 // mai sunt si alte atribuiri consecutive ...
102 s=brin.readLine(); if(s!=null) a=s.toCharArray();
103 while((s!=null)&&(a[1]==’=’))
104 {
105 System.out.println(" "+s+" ok="+ok); //br.readLine();
106 if(ok) x[a[0]-’a’]=x[a[2]-’a’];
107 s=brin.readLine(); if(s!=null) a=s.toCharArray();
108 }
109 System.out.println(" <-- blocatr: "+s); //br.readLine();
110 }// blocatr(...)
111
112 static void blocelem(boolean ok) throws IOException
113 {
114 if(estefi()||esteda()||estenu()) return;
115 System.out.println(" --> blocelem: "+s); //br.readLine();
116
117 if(a[1]==’=’) blocatr(ok);
118 if(esteif()) blocif(ok);
119
120 System.out.println(" <-- blocelem: "+s); //br.readLine();
121 }// blocelem(...)
122
123 static void bloc(boolean ok) throws IOException // blocElementar + blocElementar
+...
124 {
125 System.out.println("--> bloc: "+s); //br.readLine();
CAPITOLUL 34. ONI 2006 709
126 while(s!=null&&!estefi()&&!esteda()&&!estenu())
127 {
128 blocelem(ok);
129 }
130 System.out.println("<-- bloc: "+s); //br.readLine();
131 }// bloc(...)
132
133 public static void main(String[] args) throws IOException
134 {
135 int k;
136 brin=new BufferedReader(new FileReader("limbaj.in"));
137 stin=new StreamTokenizer(brin);
138 PrintWriter out=new PrintWriter(
139 new BufferedWriter(new FileWriter("limbaj.out")));
140
141 int i;
142 for(i=0;i<26;i++) { stin.nextToken(); x[i]=(int)stin.nval; }
143 brin.readLine();
144 afisx();
145
146 s=brin.readLine();
147 if(s!=null) a=s.toCharArray();
148
149 bloc(true);
150
151 for(i=0;i<26;i++) out.print(x[i]+" ");
152 out.println();
153 out.close();
154 }// main(...)
155 }// class
41
42 // urmeaza "DA" sau "NU"
43 s=brin.readLine(); a=s.toCharArray();
44
45 if(esteda())
46 {
47 s=brin.readLine(); a=s.toCharArray();
48 bloc(ok && oke);
49 }
50
51 if(estenu())
52 {
53 s=brin.readLine(); a=s.toCharArray();
54 bloc(ok && !oke);
55 }
56
57 s=brin.readLine(); if(s!=null) a=s.toCharArray();
58 }// blocif(...)
59
60 static void blocatr(boolean ok) throws IOException
61 {
62 if(ok) x[a[0]-’a’]=x[a[2]-’a’];
63
64 // mai sunt si alte atribuiri consecutive ...
65 s=brin.readLine(); if(s!=null) a=s.toCharArray();
66 while((s!=null)&&(a[1]==’=’))
67 {
68 if(ok) x[a[0]-’a’]=x[a[2]-’a’];
69 s=brin.readLine(); if(s!=null) a=s.toCharArray();
70 }
71 }// blocatr(...)
72
73 static void blocelem(boolean ok) throws IOException
74 {
75 if(estefi()||esteda()||estenu()) return;
76 if(a[1]==’=’) blocatr(ok);
77 if(esteif()) blocif(ok);
78 }// blocelem(...)
79
80 static void bloc(boolean ok) throws IOException// blocElementar + blocElementar +...
81 {
82 while(s!=null&&!estefi()&&!esteda()&&!estenu()) blocelem(ok);
83 }// bloc(...)
84
85 public static void main(String[] args) throws IOException
86 {
87 int k;
88 brin=new BufferedReader(new FileReader("limbaj.in"));
89 stin=new StreamTokenizer(brin);
90 PrintWriter out=new PrintWriter(
91 new BufferedWriter(new FileWriter("limbaj.out")));
92
93 int i;
94 for(i=0;i<26;i++) { stin.nextToken(); x[i]=(int)stin.nval; }
95 brin.readLine();
96
97 s=brin.readLine();
98 if(s!=null) a=s.toCharArray();
99
100 bloc(true);
101
102 for(i=0;i<26;i++) out.print(x[i]+" ");
103 out.println();
104 out.close();
105 }// main(...)
106 }// class
34.3 Panouri
autor G l µan Constantin, ISJ
Bistrita-Nasaud
Pe autostrada "Soarele Estului" sunt a³ezate de-a lungul ³oselei, la distanµe egale, panouri
publicitare ale unor rme. Aceea³i rm , poate s aib mai multe panouri publicitare ³i ecare
CAPITOLUL 34. ONI 2006 711
panou poate s apar în mai multe locuri. Panourile se identic prin numere naturale, num rul
total de panouri ind N .
Firma "X Corporation" are panouri de T tipuri diferite. Firma a primit aprobarea construirii
unui mare complex turistic în apropierea autostr zii; de aceea, pentru alegerea locului, este inte-
resat ³i de urm torul aspect: care este lungimea minim de ³osea, în care se pot întâlni, toate
cele T tipuri de panouri publicitare ale rmei, indiferent de ordinea acestora, ³i indiferent dac
între ele se mai interpun sau nu panouri ale altor rme.
Cerinµ
Cunoscând N - num rul total de panouri de la marginea autostr zii ³i ordinea amplas rii lor,
ca ³i cele T tipuri de panouri amplasate de rm , determinaµi num rul minim de intervale dintre
dou panouri între care rma "X Corporation" î³i reg se³te toate panourile sale.
Date de intrare
Fi³ierul de intrare panouri.in are pe prima linie numerele N ³i T .
Pe urm toarele N linii, sunt N numere naturale, nu neaparat diferite, câte unul pe linie,
reprezentând panourile, iar începând cu linia N 2, câte unul pe linie, cele T tipuri de panouri
diferite al rmei.
Date de ie³ire
Fi³ierul de ie³ire panouri.out va conµine pe prima linie un singur num r întreg pozitiv L,
reprezentând num rul cerut, sau 1 în caz c nu exist soluµie.
Restricµii ³i preciz ri
1&N & 15000
1&T & 1000
Toate numerele reprezentând panouri sunt numere naturale din intervalul 1..1000.
Exemple
panouri.in panouri.out Explicaµie
62 2 Sunt N 6 panouri : 1 2 3 5 3 1.
1 Firma are T 2 tipuri de panouri: 5 ³i 1.
2
3 Cel mai scurt interval care conµine elementele
5 5 ³i 1, este între panourile al 4 - lea
3 ³i al 6 -lea, ³i conµine 2 intervale.
1
5
1
83 4 Sunt N 8 panouri de tipurile: 5 1 3 3 5 4 2 1.
5 Firma are T 3 tipuri de panouri: 3, 1 ³i 4.
1
3 Cel mai scurt interval care conµine elementele
3 1, 3 ³i 4, este între al 2 lea ³i al 6-lea panou,
5 ³i conµine 4 intervale.
4
2
1
3
1
4
Soluµia comisiei
Reformul m problema: ind dat un ³ir a1..n ³i o multime B cu m elemente, s se gaseasc
dou poziµii start ³i f inal, astfel încât toate elementele mulµimii B s e conµinute în subsecvenµa
astart, ..., f inal, cu proprietatea c diferenµa f inal start are valoare minim .
CAPITOLUL 34. ONI 2006 712
Cu alte cuvinte, s se gaseasc subsecvenµa de lungime minim astart..f inal care conµine
toate elementele mulµimii B .
Având în vedere valorile mici pentru tipurile de panouri (1 & tip & 1000), pentru operaµia
de c utare în O 1 a unui element în multimea B , denim ³irul b, cu bi 1 dac i aparµine
mulµimii B .
Denim de asemenea ³rul frecvenµelor f r, cu proprietatea c f ri x daca i aparµine lui B
³i i apare de x ori în subsecvenµa astart, ..f inal.
Fix m start ³i f inal la valoarea 1 ³i increment m poziµia f inal pân când toate elementele
mulµimii B se a în intervalul astart, ..f inal. Apoi incrementam start pân la valoarea maxim
la care astart, ..f inal mai conµine înc toate elementele mulµimii B .
În continuare, pentru ecare incrementare a poziµiei f inal, m rim cât se poate de mult poziµia
start, cu respectarea restricµiilor. În acest fel ne asigur m c pentru ecare poziµie f inal, avem o
subsecvenµ de lungime minim care conµine multimea B .
Algoritmul are complexitatea O n.
52 s = 1; f = 1;
53 nr = 0;
54 if ( b[a[s]] == 1 )
55 fr[a[s]] = 1, nr = 1;
56
57 while (f < n && nr < m) // cautam cel mai mic al 2-lea indice f
58 // astfel ca in a[s..f]
59 { // sa fie continute toate numerele din b[]
60 f++;
61 if (b[a[f]] == 1) // face parte din b[]
62 {
63 if ( fr[a[f]] == 0 ) // o singura aparitie in secventa
64 nr++;
65 fr[a[f]]++;
66 }
67 }
68
69 if ( nr < m ) // nu exista solutie
70 {
71 // fout << nr << ’\n’;
72 fout << -1 << ’\n’;
73 fout.close();
74 return;
75 }
76
77 while (b[a[s]] == 0 || (b[a[s]] == 1 && fr[a[s]] > 1))
78 --fr[a[s++]]; // marim s cat se poate astfel ca in secventa a[s..f]
79 // sa apara toate numerele din b
80 best = DIM1;
81 if (best > f - s)
82 best = f - s, minx = s, maxx = f;
83
84 for (f = f + 1; f <= n; f++ )
85 {
86 if (b[a[f]] == 1)
87 fr[a[f]]++;
88
89 while (b[a[s]] == 0 || (b[a[s]] == 1) && (fr[a[s]] > 1))
90 --fr[a[s++]]; // la fiecare incrementare a indicelui f incercam
91 // sa marim pe cat posibil si indicele s
92
93 if (best > f - s)
94 best = f - s, minx = s, maxx = f;
95 }
96
97 fout << best << ’\n’;
98 // fout << min << " " << max << ’\n’;
99 fout.close();
100 }
17 imin=i;
18 if(pf[x[i]]==0) continue;
19
20 for(j=1;j<=1000;j++) pu[j]=0;
21
22 npu=1;
23 pu[x[i]]=1;
24 jmin=-1;
25 for(j=i+1;j<=n;j++)
26 {
27 if( (pf[x[j]]==1) && (pu[x[j]]==0) )
28 {
29 npu++;
30 pu[x[j]]=1;
31 if(npu==t) {jmin=j; break;}
32 }
33 }
34 if(npu==t)
35 if((jmin-imin)<min) min=jmin-imin;
36 }
37 }// calcul()
38
39 public static void main(String[] args) throws IOException
40 {
41 int i,tipp;
42 long t1,t2;
43 t1=System.currentTimeMillis();
44 StreamTokenizer st=new StreamTokenizer(
45 new BufferedReader(new FileReader("panouri.in")));
46 PrintWriter out=new PrintWriter(
47 new BufferedWriter(new FileWriter("panouri.out")));
48
49 st.nextToken(); n=(int)st.nval;
50 st.nextToken(); t=(int)st.nval;
51 for(i=1;i<=n;i++) { st.nextToken(); x[i]=(int)st.nval; px[x[i]]=1; }
52 for(i=1;i<=t;i++) { st.nextToken(); tipp=(int)st.nval; pf[tipp]=1; }
53
54 min=0;
55 for(i=1;i<=1000;i++)
56 if((px[i]==0)&&(pf[i]==1)) {min=-1; break;}
57
58 if(min==0)
59 if(t>1) calcul();
60
61 out.println(min);
62 out.close();
63 t2=System.currentTimeMillis();
64 System.out.println("Time = "+(t2-t1));
65 }// main(...)
66 }// class
21 {
22 while(pf[x[j]]==0) j++;
23 if(pu[x[j]]==0) npu++;
24 pu[x[j]]++; // panou utilizat (nr de ori)
25 if(npu<t) j++;
26 }
27 min=j-i; // intre i ... j sunt toate ...
28
29 while(j<=n)
30 {
31 while(npu==t)
32 {
33 while(pf[x[i]]==0) i++; // i -->
34 if(pu[x[i]]==1) break; else {pu[x[i]]--; i++;}
35 }
36 if(j-i<min) min=j-i;
37
38 // il scot pe i ...
39 pu[x[i]]=0;
40 npu=t-1;
41 i++;
42
43 j++; // j --> pana refac nr panouri = t
44 while((j<=n)&&(npu<t))
45 {
46 while(pf[x[j]]==0) j++; // ma plasez pe panou firma
47 if(pu[x[j]]==0) npu++;
48 pu[x[j]]++; // panou utilizat (nr de ori)
49 if(npu<t) j++;
50 }
51 }
52 }// calcul()
53
54 public static void main(String[] args) throws IOException
55 {
56 int i,tipp;
57 long t1,t2;
58 t1=System.currentTimeMillis();
59 StreamTokenizer st=new StreamTokenizer(
60 new BufferedReader(new FileReader("panouri.in")));
61 PrintWriter out=new PrintWriter(
62 new BufferedWriter(new FileWriter("panouri.out")));
63
64 st.nextToken(); n=(int)st.nval;
65 st.nextToken(); t=(int)st.nval;
66 for(i=1;i<=n;i++) { st.nextToken(); x[i]=(int)st.nval; px[x[i]]=1; }
67 for(i=1;i<=t;i++) { st.nextToken(); tipp=(int)st.nval; pf[tipp]=1; }
68
69 min=0;
70 for(i=1;i<=1000;i++)
71 if((px[i]==0)&&(pf[i]==1)) {min=-1; break;}
72
73 if(min==0)
74 if(t>1) calcul();
75
76 out.println(min);
77 out.close();
78 t2=System.currentTimeMillis();
79 System.out.println("Time = "+(t2-t1));
80 }// main(...)
81 }// class
34.4 Pereµi
autor Dom³a Ovidiu,
Universitatea 1 Decembrie 1918 Alba Iulia
Localitatea Târgovi³te este în plin modernizare. Prim ria decide s inventarieze toate cl dirile
din ora³ pentru a renova faµadele acestora. În acest sens analizeaz harta ora³ului ³i constat c
toµi pereµii sunt a³ezaµi doar pe direcµia Nord Sud sau Est Vest. Pereµii vizibili de c tre turi³ti
sunt doar aceia la care se poate ajunge din exteriorul ora³ului prin deplasarea pe cele dou direcµii
date, în oricare din cele 4 sensuri (N , E , S , V ). Harta ora³ului este întocmit pe un caroiaj format
din p trate cu latur 1.
CAPITOLUL 34. ONI 2006 716
Cerinµ
Cunoscându-se harta ora³ului, determinaµi lungimea pereµilor vizibili ce urmeaz a zugr viµi.
Date de intrare
Fi³ierul de intrare pereti.in are pe prima linie dimensiunile m (num rul de linii), n (num rul
de coloane) ale h rµii. Pe ecare dintre urm toarele m linii exist n numere naturale de la 0 la
15, separate prin câte un spaµiu, cu semnicaµia:
- reprezentarea binar a num rului pe 4 cifre semnic , începând de la stânga spre dreapta,
existenµa unui perete spre direcµiile N , E , S , V (1 - exist perete, 0 - nu exist perete;
explicaµii în gura de mai jos).
De exemplu valoarea 13 se reprezint în binar 1101, deci în mod corespunz tor, de la stânga
spre dreapta, vom avea pereµi spre N, E ³i V.
N
0 6 13 1
4 15 5 1
V 0 14 1 E
4 15 0
0 12 5 7
Date de ie³ire
Fi³ierul de ie³ire pereti.out va conµine pe prima linie num rul natural k reprezentând lungimea
pereµilor ce vor zugr viµi.
Restricµii ³i preciz ri
1 & m, n & 100
Pereµii aaµi la marginea h rµii sunt pereµi vizibili.
Datele de intrare sunt considerate corecte.
Exemplu
pereti.in pereti.out Explicaµie
5 4 22 Pentru poziµiile (5, 2) ³i (5, 3) peretele dintre ele
0 6 13 1 va zugr vit pe ambele feµe.
4 15 5 1
0 14 7 1 Peretele dinspre Nord al poziµiei (1,3) este perete
4 15 9 0 exterior, chiar dac se a pe marginea h rµii.
0 12 5 7
Timp maxim de execuµie/test: 1 secund (Windows), 0.5 secunde (Linux)
Soluµia comisiei
Se bordeaz matricea cu valorile corespunz toare, astfel încât toat harta se înconjor cu ziduri
exterioare. Se determin toate poziµiile (celulele) din matrice accesibile din pozitia 0, 0 care este
exterioar astfel:
Se construie³te un ³ir de perechi, i, j care vor marca pe rând poziµiile din matrice pe care
le-am parcurs deja.
Se porne³te din 0, 0, se determin toate poziµiile din matrice vecine cu acestea, în care se
poate ajunge, ³i se adaug la ³irul construit. Odat ad ugate, se trece la urm toarea poziµie din
CAPITOLUL 34. ONI 2006 717
³ir ³i se adaug din nou toµi vecinii accesibili din aceasta dar care nu gureaz în ³irul nostru.
Procedura continu pân când marc m toµi vecinii celulelor ad ugate în ³ir.
Pentru a marca elementele din matrice deja ad ugate în sir adun m 16 ec rei "celule". În
acela³i timp ad ug m num rul de pereµi vizibili din exterior, respectiv 1, 2 sau 3 în funcµie de
valoarea celulei.
Vericarea vecinilor se realizeaz f r a folosi descompunerea binar a valorilor. Se folose³te
operaµia AND între valorile numerice întregi (de exemplu, 8 and 11 = 8 deci exist perete spre
N).
59 a[0,0]:=a[0,0]+16;
60 while k<=l do
61 begin
62 for i:=1 to 4 do
63 if ((a[x[k].i,x[k].j] and d[i])<>d[i])and (a[x[k].i+dx[i],x[k].j+dy[i]]<16) then
64 begin
65 inc(l);
66 x[l].i:=x[k].i+dx[i];
67 x[l].j:=x[k].j+dy[i];
68 a[x[l].i,x[l].j]:=a[x[l].i,x[l].j]+16;
69 end;
70 case a[x[k].i,x[k].j] -16 of
71 1,2,4,8: nr:=nr+1;
72 3,5,6,9,10,12: nr:=nr+2;
73 7,11,13,14: nr:=nr+3;
74 end;
75 inc(k);
76 end;
77 numara:=nr;
78 end;
79
80 begin
81 citire(a,m,n);
82 bordare(a,m,n);
83 assign(f,’pereti.out’);
84 rewrite(f);
85 writeln(f,numara(a,m,n)-2*m-2*n-8);
86 close(f);
87 end.
44 Procedure fill(x,y:byte);
45 var i:byte;
46 begin
47 a[x,y]:=a[x,y]+16;
48 for i:=1 to 4 do
49 if (a[x,y] and d[i]<>d[i]) and (a[x+dx[i],y+dy[i]]<16) then
50 fill(x+dx[i],y+dy[i]);
51 end;
52
53 Function numara(var a:mat;m,n:byte):longint;
54 var nr:longint;
55 i,j:byte;
56 begin
57 nr:=0;
58 for i:=1 to m do
59 for j:=1 to n do
60 begin
61 if a[i,j]>16 then
62 case a[i,j]-16 of
63 1,2,4,8: nr:=nr+1;
64 3,5,6,9,10,12: nr:=nr+2;
65 7,11,13,14: nr:=nr+3;
66 end;
67 end;
68 for i:=1 to n do
69 begin
70 if a[0,i]<>24 then inc(nr);
71 if a[m+1,i]<>18 then inc(nr);
72 end;
73 for i:=1 to m do
74 begin
75 if a[i,0]<>17 then inc(nr);
76 if a[i,n+1]<>20 then inc (nr);
77 end;
78 numara:=nr;
79 end;
80
81 begin
82 citire(a,m,n);
83 bordare(a,m,n);
84 fill(0,0);
85 assign(f,’pereti.out’);
86 rewrite(f);
87 writeln(f,numara(a,m,n));
88 close(f);
89 end.
22 }// fill(...)
23
24 static void intra()
25 {
26 int i,j;
27 for(i=1;i<=m;i++) // de la vest
28 if((b[i][1]==0)&&((a[i][1]&vest)==0)) { nz++; fill(i,1); }
29 for(i=1;i<=m;i++) // de la est
30 if((b[i][n]==0)&&((a[i][n]&est)==0)) { nz++; fill(i,n); }
31 for(j=1;j<=n;j++) // de la nord
32 if((b[1][j]==0)&&((a[1][j]&nord)==0)) { nz++; fill(1,j); }
33 for(j=1;j<=n;j++) // de la sud
34 if((b[m][j]==0)&&((a[m][j]&sud)==0)) { nz++; fill(m,j); }
35 }// intra(...)
36
37 static void exterior()
38 {
39 int i,j;
40 for(i=1;i<=m;i++) if((a[i][1]&vest)!=0) np++; // vest
41 for(i=1;i<=m;i++) if((a[i][n]&est) !=0) np++; // est
42 for(j=1;j<=n;j++) if((a[1][j]&nord)!=0) np++; // nord
43 for(j=1;j<=n;j++) if((a[m][j]&sud) !=0) np++; // sud
44 }// exterior(...)
45
46 public static void main(String[] args) throws IOException
47 {
48 int i,j;
49 StreamTokenizer st=new StreamTokenizer(
50 new BufferedReader(new FileReader("pereti.in")));
51 PrintWriter out=new PrintWriter(
52 new BufferedWriter(new FileWriter("pereti.out")));
53 st.nextToken(); m=(int)st.nval;
54 st.nextToken(); n=(int)st.nval;
55 for(i=1;i<=m;i++)
56 for(j=1;j<=n;j++) { st.nextToken(); a[i][j]=(int)st.nval; }
57 np=0; // nr pereti
58 nz=0; // nr zone (fill!)
59 intra();
60 exterior();
61 out.println(np);
62 out.close();
63 }// main(...)
64 }// class
34.5 anµ
autor erban Marinel, Liceul de
Informatica "Gr. C. Moisil" Iasi
Cei n deµinuµi ai unei închisori, numerotaµi de la 1 la n, trebuie s sape un ³anµ dispus în linie
dreapt între dou puncte A ³i B , situate la distanµa de 250 km unul de cel lalt, pe care exist
251 borne kilometrice numerotate de la 0 la 250. Fiecare deµinut are îns o pretenµie, "e doar
democraµie, nu?": el dore³te s sape doar undeva în zona dintre borna x ³i borna y . Pe lâng
aceste pretenµii închisoarea se confrunt ³i cu o alt problem : nu are sucienµi paznici angajaµi.
Cerinµ
Cunoscându-se num rul n de deµinuµi ³i pretenµiile lor, s se determine locul (locurile) unde
vor pu³i deµinuµii s sape într-o zi de munc , respectându-se pretenµiile lor, astfel încât num rul
de paznici necesari pentru a p zi cei n deµinuµi s e minim. Intervalul în care poate p zi un
paznic nu poate conµine dou sau mai multe zone disjuncte dintre cele exprimate de deµinuµi în
preferinµele lor.
Date de intrare
Fi³ierul de intrare sant.in are pe prima linie num rul n de deµinuµi. Pe ecare dintre urm -
toarele n linii exist câte dou numere naturale, ai bi , separate printr-un spaµiu (ai & bi ), care
reprezint pretenµia deµinutului. Mai exact pe linia i 1 (1 & i & n) este descris pretenµia
deµinutului cu num rul de ordine i.
Date de ie³ire
Fi³ierul de ie³ire sant.out va conµine pe prima linie num rul natural k reprezentând num rul
minim de paznici necesari pentru paza celor n deµinuµi sco³i la lucru. Pe urm toarele 2k linii vor
CAPITOLUL 34. ONI 2006 721
descrise locurile unde vor pu³i s sape deµinuµii, astfel: ecare pereche de linii 2j, 2j 1
va conµine pe linia 2j trei numere naturale p xj yj , separate prin câte un spaµiu reprezentând
num rul de ordine al paznicului ³i bornele kilometrice xj c si yj unde va p zi paznicul p, iar pe
linia 2j 1 vor scrise numerele de ordine ale deµinuµilor care sap în aceast zon , separate prin
câte un spaµiu, ordonate cresc tor.
Restricµii ³i preciz ri
1 & n & 10000
Exemplu
.in .out Explicaµie
3 2 sunt necesari 2 paznici: paznicul 1 va p zi între
0 20 1 8 13 borna 8 ³i borna 13, iar deµinuµii p ziµi sunt 1 ³i 2;
8 13 1 2 paznicul 2 va p zi între borna 30 ³i borna 60, iar
30 60 2 30 60 deµinutul p zit este 3
3
4 3 sunt necesari 3 paznici: paznicul 1 va p zi între
10 203 1 10 20 borna 10 ³i borna 20, iar deµinutul p zit este 1;
2 53 1 paznicul 2 va p zi la borna 5, iar deµinuµii p ziµi
30 403 2 55 sunt 2 ³i 4; paznicul 3 va p zi între borna 30 ³i
5 7 33 2 4 borna 40, iar deµinutul p zit este 3
3 30 40
3
5 2 sunt necesari 2 paznici: paznicul 1 va p zi la
10 30 1 30 30 borna 30, iar deµinuµii p ziµi sunt 1, 2, 3 ³i 4;
30 32 1 234 paznicul 2 va p zi între borna 27 ³i borna 28,
0 30 2 27 28 iar deµinutul p zit este 5
27 30 5
27 28 !Soluµia nu este unic !
Soluµia comisiei
Problema cere, de fapt, determinarea num rului minim de intersecµii între segmentele deter-
minate de kilometrul minim ³i maxim între care sap un deµinut.
Pentru a le determina procedez astfel:
ordonez intervalele cresc tor dup kilometrul minim ³i descresc tor dup kilometrul maxim
pun primul deµinut (deci cel cu intervalul de s pare cel mai mare) în grija primului paznic
caut un paznic care mai p ze³te deµinuµi ³i care poate p zi ³i acest deµinut (adic
intersecµia segmentelor s e nevid )
dac g sesc
ajustez intervalul de s pare ca s poat s pa ³i acest deµinut
CAPITOLUL 34. ONI 2006 722
45 {
46 st.nextToken(); x1[k]=(int)st.nval;
47 st.nextToken(); x2[k]=(int)st.nval;
48 o[k]=k;
49 }
50
51 qsort(1,n);
52
53 np=1;
54 xp=x2[1];
55 for(k=2;k<=n;k++) if(x1[k]>xp) { np++; xp=x2[k]; }
56 out.println(np);
57
58 // inca o data pentru ...!
59 np=1;
60 xp=x2[1];
61 out.println(np+" "+xp+" "+xp);
62 out.print(o[1]+" ");
63 for(k=2;k<=n;k++)
64 {
65 if(x1[k]>xp)
66 {
67 out.println();
68 np++;
69 xp=x2[k];
70 out.println(np+" "+xp+" "+xp);
71 out.print(o[k]+" ");
72 }
73 else out.print(o[k]+" ");
74 }// for k
75 out.close();
76 }// main(...)
77 }// class
34.6 Zumzi
autor Popescu Carmen, Colegiul
National "Gh. Lazar" Sibiu
Albinuµa zumzi locuie³te într-un stup format din N celule de form hexagonal . Cele N celule
numerotate de la 1 la N sunt dispuse sub form de spiral (ca în gur ).
15
14 16
13 5 17
4 6
12 1 18
3 7
11 2 19
10 8
9 20
23 21
22
Adic , celula din centrul stupului este numerotat cu 1. Plecând de la aceast celul spre sud
³i apoi în spiral , în sensul acelor de ceasornic, sunt numerotate celelalte celule.
Iniµial zumzi se g se³te în celula din centru (cea numerotat cu 1), ³i dore³te s ajung ,
trecând din celul în celul , la celula cu num rul de ordine X , unde se g se³te prietenul ei. zumzi
se poate deplasa dintr-o celul în oricare dintre celulele vecine, f r a p r si îns stupul.
Dou celule sunt vecine dac au o latur comun .
Unele celule ale stupului sunt ocupate de alte albine ³i de aceea zumzi nu poate s treac prin
ele.
Cerinµ
Problema v cere s determinaµi câte variante are zumzi ca dup exact K pa³i s ajung la
prietenul ei.
CAPITOLUL 34. ONI 2006 728
Date de intrare
Fi³ierul de intrare zumzi.in conµine pe prima sa linie valorile naturale N , M , K ³i X separate
printr-un spaµiu, având urm toarea semnicaµie:
N - num rul total de celule din stup;
M - num rul de celule din stup ocupate de alte albine
K - num rul de pa³i pe care îi are la dispoziµie zumzi
X - num rul de ordine a celulei în care se g se³te prietenul lui zumzi.
Urm toarea linie a ³ierului de intrare conµine M numere naturale separate printr-un spaµiu
reprezentând numerele de ordine ale celulelor ocupate din stup.
Date de ie³ire
Fi³ierul text zumzi.out va conµine pe prima sa linie un singur num r natural reprezentând
num rul de variante pe care le are zumzi la dispoziµie de a ajunge la prietenul ei.
Restricµii ³i preciz ri
1&M $ N & 300
X j1
K & 100
zumzi nu are posibilitatea de a p r si stupul, iar în plus odat ajuns la prietenul ei nu îl
va mai p r si.
zumzi nu este o albin foarte inteligent de aceea ea poate trece de mai multe ori printr-o
celul , cu excepµia celulei nale, în care se a prietenul ei, celul în care va intra o singur
dat ³i nu o mai p r se³te.
Exemplu
zumzi.in zumzi.out Explicaµie
12 4 3 9 4 Variantele sunt:
11 4 6 8 1-2-10-9
1-3-2-9
1-3-10-9
1-7-2-9
12 4 4 2 9 Variantele avute la dispoziµie sunt:
11 4 6 8 1-3-10-9-2
1-7-1-3-2
1-5-1-7-2
etc.
Soluµia comisiei
Pentru memorarea "stupului" vom folosi o matrice p tratic T de ordinul 2 k 1, unde
valoarea lui k este data de relaµia:
3 k 1 k 1 $ n & 3 k k 1 1
CAPITOLUL 34. ONI 2006 729
adic k reprezint num rul de cercuri concentrice din stup (f r a num ra celula 1 ca un cerc).
32 while length(x)>length(y) do
33 y:=y+’0’;
34 while length(y)>length(x) do
35 x:=x+’0’;
36 z:=’’;
37 for i:=1 to length(x) do
38 z:=z+’0’;
39 t:=0;
40 for i:=1 to length(x) do
41 begin
42 c:=ord(x[i])+ord(y[i])-2*zero+t;
43 t:=c div 10;
44 c:=c mod 10;
45 z[i]:=chr(c+zero);
46 end;
47 if t>0 then
48 z:=z+chr(t+zero);
49 end;
50
51 procedure compl;
52 var c,i,j,s:integer;
53 begin
54 i:=k+1; j:=k+1; s:=1;
55 t[i,j]:=s; poz[s].x:=i; poz[s].y:=j;
56 s:=s+1;
57 for c:=1 to k do
58 begin
59 i:=i+1;
60 while i<=k+c+1 do
61 begin
62 t[i,j]:=s;
63 poz[s].x:=i; poz[s].y:=j;
64 s:=s+1;
65 if s>n then exit;
66 i:=i+1; j:=j-1;
67 end;
68 i:=i-1;
69 while j>=k-c+1 do
70 begin
71 t[i,j]:=s;
72 poz[s].x:=i; poz[s].y:=j;
73 s:=s+1;
74 if s>n then exit;
75 j:=j-1;
76 end;
77 j:=j+1; i:=i-1;
78 while i>=k+1 do
79 begin
80 t[i,j]:=s;
81 poz[s].x:=i; poz[s].y:=j;
82 s:=s+1;
83 if s>n then exit;
84 i:=i-1;
85 end;
86 j:=j+1;
87 while i>=k-c+1 do
88 begin
89 t[i,j]:=s;
90 poz[s].x:=i; poz[s].y:=j;
91 s:=s+1;
92 if s>n then exit;
93 i:=i-1; j:=j+1;
94 end;
95 i:=i+1;
96 while j<=k+c+1 do
97 begin
98 t[i,j]:=s;
99 poz[s].x:=i; poz[s].y:=j;
100 s:=s+1;
101 if s>n then exit;
102 j:=j+1;
103 end;
104 j:=j-1; i:=i+1;
105 while i<=k+1 do
106 begin
107 t[i,j]:=s;
CAPITOLUL 34. ONI 2006 731
i-1, j
N
i,j
SV SE
i+1-(j%2) , j-1 i+1-(j%2) , j+1
S
i+1, j
107 {
108 for(i=1;i<=n;i++) // celula i
109 {
110 nd[i][k%2]=0; // este suma vecinilor
111
112 if(a[i]==1) continue; // este ocupata
113 if((i==x)&&(k<np)) continue; // nu mai pleaca !
114
115 v=s[in(is[i],js[i])][jn(is[i],js[i])]; // vecin la nord
116 if(a[v]==0) nd[i][k%2]+=nd[v][(k+1)%2]; // celula libera
117
118 v=s[is(is[i],js[i])][js(is[i],js[i])]; // vecin la sud
119 if(a[v]==0) nd[i][k%2]+=nd[v][(k+1)%2]; // celula libera
120
121 v=s[ine(is[i],js[i])][jne(is[i],js[i])]; // vecin la nord_est
122 if(a[v]==0) nd[i][k%2]+=nd[v][(k+1)%2]; // celula libera
123
124 v=s[ise(is[i],js[i])][jse(is[i],js[i])]; // vecin la sud_est
125 if(a[v]==0) nd[i][k%2]+=nd[v][(k+1)%2]; // celula libera
126
127 v=s[inv(is[i],js[i])][jnv(is[i],js[i])]; // vecin la nord_vest
128 if(a[v]==0) nd[i][k%2]+=nd[v][(k+1)%2]; // celula libera
129
130 v=s[isv(is[i],js[i])][jsv(is[i],js[i])]; // vecin la sud_vest
131 if(a[v]==0) nd[i][k%2]+=nd[v][(k+1)%2]; // celula libera
132 }// for i
133 }// for k
134 }// calcul()
135
136 public static void main(String[] args) throws IOException
137 {
138 int i,j;
139 StreamTokenizer st=new StreamTokenizer(
140 new BufferedReader(new FileReader("zumzi.in")));
141 PrintWriter out=new PrintWriter(
142 new BufferedWriter(new FileWriter("zumzi.out")));
143 st.nextToken(); n=(int)st.nval;
144 st.nextToken(); m=(int)st.nval;
145 st.nextToken(); np=(int)st.nval;
146 st.nextToken(); x=(int)st.nval;
147
148 for(i=1;i<=m;i++) { st.nextToken(); j=(int)st.nval; a[j]=1; }
149
150 stupul(); // numerotare celule
151 calcul();
152
153 out.println(nd[x][np%2]);
154 out.close();
155 }// main(...)
156 }// class
ONI 2005
35.1 Bifo
Autor: Silviu G nceanu
Pentru a-³i vindeca rana provocat de Spânul cel Negru, prinµul Algorel are nevoie de
leacul miraculos aat în posesia vr jitoarei din p durea întunecat .
Aceasta i-a promis leacul dac îi rezolv urm toarea problem , la care ea s-a gândit zadarnic o
mie de ani: pornind de la dou cuvinte iniµiale A1 ³i A2 ³i aplicând "formula bifo" An An2 An1
pentru n ' 3, se obµin cuvintele A3 , A4 , A5 , ³.a.m.d.
Prin An2 An1 înµelegem concatenarea cuvintelor An2 ³i An1 în aceast ordine.
Toate aceste cuvinte (A1 , A2 , A3 , ³.a.m.d), sunt la rândul lor concatenate, în ordine, formând
un ³ir de caractere innit denumit ³ir magic.
Formula leacului miraculos are M caractere, pe care vr jitoarea nu le ³tie. Se ³tiu îns cele M
poziµii din ³irul magic în care apar, în ordine, caracterele din formul .
Cerinµ
Cu toat inteligenµa lui, Algorel nu poate rezolva aceast problem . Ajutaµi-l pe prinµ s ias
din încurc tur aând formula leacului magic.
Date de intrare
Primele dou linii ale ³ierului bifo.in conµin ecare câte un ³ir de cel mult 100 de caractere
reprezentând cuvintele A1 (pe prima linie) ³i respectiv A2 (pe a doua linie).
A treia linie conµine un num r întreg M , reprezentând num rul de caractere din formula
leacului miraculos.
Urmeaz M linii descriind, în ordine, poziµiile din ³irul magic unde se g sesc caracterele din
formul .
Date de ie³ire
738
CAPITOLUL 35. ONI 2005 739
Fi³ierul de ie³ire bifo.out va conµine pe prima linie un ³ir de M caractere reprezentând formula
leacului miraculos.
Restricµii ³i preciz ri
a 1 & M & 100;
a A1 ³i A2 conµin doar litere mici ale alfabetului englez;
a Numerotarea poziµiilor din ³irul innit începe cu 1;
a Cele M poziµii vor numere întregi (nu neap rat distincte) de maxim 100
de cifre;
a Pentru 60% din teste poziµiile vor numere întregi între 1 ³i 1.000.000.000;
a Fiecare linie din ³ierul de intrare ³i din ³ierul de ie³ire se termin cu
marcaj de sfâr³it de linie;
Exemplu
bifo.in bifo.out
ab xdb
cdx
3
10
4
15
Explicaµie: Primele 5 ³iruri obµinute folosind "formula bifo" sunt:
ab, cdx, abcdx, cdxabcdx, abcdxcdxabcdx
Concatenând aceste ³iruri se obµine ³irul magic:
abcdxabcdxcdxabcdxabcdxcdxabcdx...
Timp maxim de execuµie/test: 1 sec sub Windows ³i 1 sec sub Linux
66 for(i=1;i<=m;i++) out.print(f[i]);
67 out.println();
68 out.close();
69 }
70 }
67 k=k-2;
68 }
69 else // caracterul este in a[k-1] dreapta
70 {
71 x=x-lg[k-2];
72 k--;
73 }
74 }
75 if(k==1) f[i]=a1[x-1];
76 if(k==2) f[i]=a2[x-1];
77 }
78
79 static void afisare() throws IOException
80 {
81 int i;
82 out=new PrintWriter(new BufferedWriter(new FileWriter("bifo.out")));
83 for(i=1;i<=m;i++) out.print(f[i]);
84 out.println();
85 out.close();
86 }
87 }
51 {
52 char[] x,sk1,sk,pk;
53 int k;
54 lg[1]=nr2v(a1.length);
55 lg[2]=nr2v(a2.length);
56
57 x=suma(nr2v(0),p[i]); // improvizatie pentru x=p[i]; !!!
58 if(compar(x,lg[1])<=0){f[i]=a1[v2nr(x)-1];return;}
59 if(compar(x,suma(lg[1],lg[2]))<=0){f[i]=a2[v2nr(x)-v2nr(lg[1])-1];return;}
60
61 sk1=suma(nr2v(0),lg[1]);
62 sk=suma(sk1,lg[2]);
63 k=2; // k=cuvantul unde se gaseste caracterul de pe pozitia x
64 while(compar(sk,x)<0)
65 {
66 k++;
67 lg[k]=suma(lg[k-2],lg[k-1]);
68 sk1=suma(nr2v(0),sk);
69 sk=suma(sk1,lg[k]);
70 }
71 x=scade(x,sk1);
72 while(k>2) // a[k]=a[k-2]a[k-1]
73 {
74 if(compar(lg[k-2],x)>=0) // caracterul este in a[k-2] stanga
75 {
76 k=k-2;
77 }
78 else // caracterul este in a[k-1] dreapta
79 {
80 x=scade(x,lg[k-2]);
81 k--;
82 }
83 }
84 if(k==1) f[i]=a1[v2nr(x)-1];
85 if(k==2) f[i]=a2[v2nr(x)-1];
86 }
87
88 static void afisare() throws IOException
89 {
90 int i;
91 out=new PrintWriter(new BufferedWriter(new FileWriter("bifo.out")));
92 for(i=1;i<=m;i++) out.print(f[i]);
93 out.println();
94 out.close();
95 }
96
97 static int compar(char[] a, char[] b) //-1, 0, 1 ... a < = > b
98 {
99 int na=a.length;
100 int nb=b.length;
101 if(na>nb) return 1; else if(na<nb) return -1;
102
103 int i=na-1;
104 while((i>=0)&&(a[i]==b[i])) i--;
105 if(i==-1) return 0;
106 else if(a[i]>b[i]) return 1; else return -1;
107 }
108
109 static char[] scade(char[] x,char[] y) // z=x-y unde x>=y
110 {
111 int nx=x.length;
112 int ny=y.length;
113 int nz=nx;
114 int i,s;
115 char t;
116 char[] z=new char[nz];
117 char[] yy=new char[nz];
118 for(i=0;i<ny;i++) yy[i]=y[i];
119 t=0;
120 for(i=0;i<nz;i++)
121 {
122 s=x[i]-yy[i]-t; // poate fi negativ ==> nu merge tipul char !!!
123 if(s<0) {z[i]=(char)(s+10); t=1;} else {z[i]=(char)s; t=0;}
124 }
125 if(z[nz-1]!=0) return z;
126 else
CAPITOLUL 35. ONI 2005 744
127 {
128 int poz=nz-1; // de exemplu 123-121=002 ==>
129 while((int)z[poz]==0) poz--;// pot fi mai multe zero-uri la inceput
130 char[] zz=new char[poz+1];
131 for(i=0;i<=poz;i++) zz[i]=z[i];
132 return zz;
133 }
134 }
135
136 static char[] suma(char[] x,char[] y)
137 {
138 int nx=x.length;
139 int ny=y.length;
140 int nz;
141 if(nx>ny) nz=nx+1; else nz=ny+1;
142 int t,i;
143 char[] z=new char[nz];
144 char[] xx=new char[nz];
145 char[] yy=new char[nz];
146 for(i=0;i<nx;i++) xx[i]=x[i];
147 for(i=0;i<ny;i++) yy[i]=y[i];
148 t=0;
149 for(i=0;i<nz;i++)
150 {
151 z[i]=(char)(xx[i]+yy[i]+t);
152 t=z[i]/10;
153 z[i]=(char)(z[i]%10);
154 }
155 if(z[nz-1]!=0) return z;
156 else
157 {
158 char[] zz=new char[nz-1];
159 for(i=0;i<nz-1;i++) zz[i]=z[i];
160 return zz;
161 }
162 }
163
164 static char[] nr2v(int nr)
165 {
166 int nrr=nr,nc=0,i;
167 while(nr!=0) { nc++; nr=nr/10; }
168 char[] nrv=new char[nc];
169 nr=nrr;
170 for(i=0;i<nc;i++) { nrv[i]=(char)(nr%10); nr=nr/10; }
171 return nrv;
172 }
173
174 static int v2nr(char[] x)
175 {
176 int nr=0,i;
177 for(i=x.length-1;i>=0;i--) nr=nr*10+x[i];
178 return nr;
179 }
180 }
35.2 Romeo
Autor: prof. Dan Grigoriu
Ora³ul Julietei este de form p trat ³i are str zi doar pe direcµiile Nord-Sud ³i Est-Vest,
toate la distanµe egale ³i numite ca în desen: strada vertical 0, 1, 2, 3, ..., respectiv strada
orizontal 0, 1, 2, 3... . Julieta locuie³te la intersecµia str zilor: vertical x ³i orizontalu a y
(poziµia x, y ).
Romeo se a în colµul de Sud-Vest al ora³ului (poziµia (0,0)) ³i dore³te s ajung la Julieta,
nu ³tim exact de ce, dar este treaba lui. Peste toate necazurile cunoscute ale bietului b iat, mai
apar ³i altele:
ora³ul urc în pant spre Nord, ceea ce îngreuneaz mersul în acea direcµie;
nu poate merge decât spre Nord sau spre Est, pentru c dac "ea" l-ar vedea mergând spre
Vest sau spre Sud, atunci ar crede c el se îndep rteaz denitiv de ea.
Numim segment elementar distanµa dintre dou str zi paralele al turate.
CAPITOLUL 35. ONI 2005 745
Dac Romeo merge spre Est, atunci el consum 1J (J = joule = o unitate de energie) pentru
ecare segment elementar parcurs.
Din cauza pantei, dac merge spre Nord k segmente elementare consecutive, consum 1 2
3 ... k J .
Romeo vrea s ajung la Julieta (mergând în condiµiile de mai sus) cu un consum minim
de energie.
De exemplu, dac datele sunt:
x 4 ³i y 3,
atunci desenul al turat prezint un drum posibil (dar nu cu consum minim de energie).
În desen, avem
a un prim segment elementar orizontal (consum = 1J ), apoi
a spre Nord dou segmente elementare (consum: 1 2 3J )
a urmeaz 3 segmente spre Est (consum: 1 1 1 3J ) ³i
a ultima porµiune de un segment vertical (consum: 1J ).
Total consum energie: 1 3 3 1 8J .
Cerinµ
Scrieµi un program care cite³te x ³i y ³i care a³eaz num rul minim de J consumaµi pentru
tot drumul de la poziµia 0, 0 la poziµia x, y , mergând doar în direcµiile precizate.
Date de intrare
Fi³ierul de intrare romeo.in conµine numerele x ³i y pe prima linie, separate de un spaµiu.
Date de ie³ire
Fi³ierul de ie³ire romeo.out conµine o singur linie cu num rul de J consumaµi pentru distanµa
total parcurs din poziµia de plecare pân în cea nal .
Restricµii ³i preciz ri
a x ³i y sunt numere naturale;
a 0 & x, y & 40000
a Fiecare linie din ³ierul de intrare ³i din ³ierul de ie³ire se încheie cu marcaj de sfâr³it de
linie.
Exemplu
romeo.in romeo.out
32 5
Explicaµie
Datele de intrare indic un ora³ ca în desen.
CAPITOLUL 35. ONI 2005 746
35.3 Seceta
lect. Ovidiu Dom³a
Gr dinile roditoare ale B r ganului sufer anual pierderi imense din cauza secetei. C u-
t torii de ap au g sit n fântâni din care doresc s alimenteze n gr dini. Fie Gi , Fi , i 1, ..., n
puncte în plan reprezentând puncte de alimentare ale gr dinilor ³i respectiv punctele în care se
a fântânile. Pentru ecare punct se dau coordonatele întregi x, y în plan.
Pentru a economisi materiale, leg tura dintre o gr din ³i o fântân se realizeaz printr-o
conduct în linie dreapt . Fiecare fântân alimenteaz o singur gr din . Consiliul Judeµean
Galaµi pl te³te investiµia cu condiµia ca lungimea total a conductelor s e minim .
Fiecare unitate de conduct cost 100 lei noi (RON).
Cerinµ
S se determine m, costul minim total al conductelor ce leag ecare gr din cu exact o fântân .
Date de intrare
Fi³ierul de intrare seceta.in va conµine:
Pe prima linie se a num rul natural n, reprezentând num rul gr dinilor ³i al fântânilor.
a
a Pe urm toarele n linii se a perechi de numere întregi Gx Gy , separate printr-un spaµiu,
reprezentând coordonatele punctelor de alimentare ale gr dinilor.
a Pe urm toarele n linii se a perechi de numere întregi Fx Fy , separate printr-un spaµiu,
reprezentând coordonatele punctelor fântânilor.
Date de ie³ire
Fi³ierul de ie³ire seceta.out va conµine:
m un num r natural reprezentând partea întreag a costului minim total al conductelor.
Restricµii ³i preciz ri
a 1 $ n $ 13
a 0 & Gx, Gy, F x, F y & 200
a Nu exist trei puncte coliniare, indiferent dac sunt gr dini sau fântâni
a Orice linie din ³ierele de intrare ³i ie³ire se termin prin marcajul de sfâr³it de linie.
Exemplu
seceta.in seceta.out Explicaµie
3 624 Costul minim este [6.24264 * 100]=624
1 4 prin legarea perechilor:
3 3 Gradini Fantani
4 7 14 23
2 3 33 31
2 5 47 25
3 1
Timp maxim de execuµie/test: 1 sec sub Windows ³i 0.5 sec sub Linux.
39 st.nextToken(); xg[k]=(int)st.nval;
40 st.nextToken(); yg[k]=(int)st.nval;
41 }
42 for(k=1;k<=n;k++)
43 {
44 st.nextToken(); xf[k]=(int)st.nval;
45 st.nextToken(); yf[k]=(int)st.nval;
46 }
47 }
48
49 static void rezolvare() throws IOException
50 {
51 int i,j;
52 int s;
53 for(i=1;i<=n;i++) // gradina i
54 for(j=1;j<=n;j++) // fantana j
55 {
56 s=(xg[i]-xf[j])*(xg[i]-xf[j])+(yg[i]-yf[j])*(yg[i]-yf[j]);
57 d[i][j]=Math.sqrt(s);
58 }
59 f(1); // generez permutari
60 }
61
62 static void f(int k)
63 {
64 boolean ok;
65 int i,j;
66 for(i=1;i<=n;i++)
67 {
68 ok=true; // k=1 ==> nu am in stanga ... for nu se executa !
69 for(j=1;j<k;j++) if(i==a[j]) {ok=false; break;}
70 if(!ok) continue;
71 for(j=1;j<k;j++)
72 if(seIntersecteaza(xg[k],yg[k],xf[i], yf[i],
73 xg[j],yg[j],xf[a[j]],yf[a[j]]))
74 {
75 ok=false;
76 break;
77 }
78 if(!ok) continue;
79 a[k]=i;
80 if(k<n) f(k+1); else verificCostul();
81 }
82 }
83
84 static void verificCostul()
85 {
86 int i;
87 double s=0;
88 for(i=1;i<=n;i++) s=s+d[i][a[i]];
89 if(s<costMin) costMin=s;
90 }
91
92 // de ce parte a dreptei [(xa,ya);(xb,yb)] se afla (xp,yp)
93 static int s(int xp,int yp,int xa,int ya,int xb,int yb)
94 {
95 double s=(double)yp*(xb-xa)-xp*(yb-ya)+xa*yb-xb*ya;
96 if(s<-0.001) return -1; // in zona "negativa"
97 else if(s>0.001) return 1; // in zona "pozitiva"
98 else return 0; // pe dreapta suport
99 }
100
101 // testeaza daca segmentul[P1,P1] se intersecteaza cu [P3,P4]
102 static boolean seIntersecteaza(int x1, int y1, int x2, int y2,
103 int x3, int y3, int x4, int y4)
104 {
105 double x,y;
106 if((x1==x2)&&(x3==x4)) // ambele segmente verticale
107 if(x1!=x3) return false;
108 else if(intre(y1,y3,y4)||intre(y2,y3,y4)) return true;
109 else return false;
110
111 if((y1==y2)&&(y3==y4)) // ambele segmente orizontale
112 if(y1!=y3) return false;
113 else if(intre(x1,x3,x4)||intre(x2,x3,x4)) return true;
114 else return false;
CAPITOLUL 35. ONI 2005 751
115
116 if((y2-y1)*(x4-x3)==(y4-y3)*(x2-x1)) // au aceeasi panta (oblica)
117 if((x2-x1)*(y3-y1)==(y2-y1)*(x3-x1)) // au aceeasi dreapta suport
118 if(intre(x1,x3,x4)||intre(x2,x3,x4)) return true;
119 else return false;
120 else return false;// nu au aceeasi dreapta suport
121 else // nu au aceeasi panta (macar unul este oblic)
122 {
123 x=(double)((x4-x3)*(x2-x1)*(y3-y1)-
124 x3*(y4-y3)*(x2-x1)+
125 x1*(y2-y1)*(x4-x3))/
126 ((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
127 if(x2!=x1) y=y1+(y2-y1)*(x-x1)/(x2-x1); else y=y3+(y4-y3)*(x-x3)/(x4-x3);
128 if(intre(x,x1,x2)&&intre(y,y1,y2)&&intre(x,x3,x4)&&intre(y,y3,y4))
129 return true; else return false;
130 }
131 }
132
133 static boolean intre(int c, int a, int b) // c este in [a,b] ?
134 {
135 int aux;
136 if(a>b) {aux=a; a=b; b=aux;}
137 if((a<=c)&&(c<=b)) return true; else return false;
138 }
139
140 static boolean intre(double c, int a, int b) // c este in [a,b] ?
141 {
142 int aux;
143 if(a>b) {aux=a; a=b; b=aux;}
144 if((a<=c)&&(c<=b)) return true; else return false;
145 }
146
147 static void afisare() throws IOException
148 {
149 int k;
150 out=new PrintWriter(new BufferedWriter(new FileWriter("seceta.out")));
151 out.println((int)(costMin*100));
152 out.close();
153 }
154 }
32 yf=new int[n+1];
33 a=new int[n+1];
34 d=new double[n+1][n+1];
35
36 for(k=1;k<=n;k++)
37 {
38 st.nextToken(); xg[k]=(int)st.nval;
39 st.nextToken(); yg[k]=(int)st.nval;
40 }
41 for(k=1;k<=n;k++)
42 {
43 st.nextToken(); xf[k]=(int)st.nval;
44 st.nextToken(); yf[k]=(int)st.nval;
45 }
46 }
47
48 static void rezolvare() throws IOException
49 {
50 int i,j;
51 int s;
52 for(i=1;i<=n;i++) // gradina i
53 for(j=1;j<=n;j++) // fantana j
54 {
55 s=(xg[i]-xf[j])*(xg[i]-xf[j])+(yg[i]-yf[j])*(yg[i]-yf[j]);
56 d[i][j]=Math.sqrt(s);
57 }
58 f(1); // generez permutari
59 }
60
61 static void f(int k)
62 {
63 boolean ok;
64 int i,j;
65 for(i=1;i<=n;i++)
66 {
67 ok=true; // k=1 ==> nu am in stanga ... for nu se executa !
68 for(j=1;j<k;j++) if(i==a[j]) {ok=false; break;}
69 if(!ok) continue;
70
71 for(j=1;j<k;j++)
72 if((s(xg[k],yg[k],xg[j],yg[j],xf[a[j]],yf[a[j]])*
73 s(xf[i],yf[i],xg[j],yg[j],xf[a[j]],yf[a[j]])<0)&&
74 (s(xg[j], yg[j], xg[k],yg[k],xf[i],yf[i])*
75 s(xf[a[j]],yf[a[j]],xg[k],yg[k],xf[i],yf[i])<0))
76 {
77 afisv(k-1);// pe pozitia k(gradina) vreau sa pun i(fantana)
78 System.out.print(i+" ");// pe pozitia j(gradina) e pus a[j](fantana)
79 System.out.print(k+""+i+" "+j+""+a[j]);
80 System.out.print(" ("+xg[k]+","+yg[k]+") "+" ("+xf[i]+","+yf[i]+") ");
81 System.out.println(" ("+xg[j]+","+yg[j]+") "+" ("+xf[a[j]]+","+yf[a[j]]+") "
);
82
83 ok=false;
84 break;
85 }
86 if(!ok) continue;
87
88 a[k]=i;
89 if(k<n) f(k+1); else verificCostul();
90 }
91 }
92
93 static void verificCostul()
94 {
95 int i;
96 double s=0;
97 for(i=1;i<=n;i++) s=s+d[i][a[i]];
98 if(s<costMin) costMin=s;
99 afisv(n); System.out.println(" "+s+" "+costMin+" "+(++nv));
100 }
101
102 static void afisv(int nn)
103 {
104 int i;
105 for(i=1;i<=nn;i++) System.out.print(a[i]);
106 }
CAPITOLUL 35. ONI 2005 753
107
108 // de ce parte a dreptei [(xa,ya);(xb,yb)] se afla (xp,yp)
109 static int s(int xp,int yp,int xa,int ya,int xb,int yb)
110 {
111 double s=(double)yp*(xb-xa)-xp*(yb-ya)+xa*yb-xb*ya;
112 if(s<-0.001) return -1; // in zona "negativa"
113 else if(s>0.001) return 1; // in zona "pozitiva"
114 else return 0; // pe dreapta suport
115 }
116
117 static void afisare() throws IOException
118 {
119 int k;
120 out=new PrintWriter(new BufferedWriter(new FileWriter("seceta.out")));
121 out.println((int)(costMin*100));
122 out.close();
123 }
124 }
54 {
55 s=(xg[i]-xf[j])*(xg[i]-xf[j])+(yg[i]-yf[j])*(yg[i]-yf[j]);
56 d[i][j]=Math.sqrt(s);
57 }
58 f(1); // generez permutari
59 }
60
61 static void f(int k)
62 {
63 boolean ok;
64 int i,j;
65 for(i=1;i<=n;i++)
66 {
67 ok=true; // k=1 ==> nu am in stanga ... for nu se executa !
68 for(j=1;j<k;j++) if(i==a[j]) {ok=false; break;}
69 if(!ok) continue;
70 for(j=1;j<k;j++)
71 if((s(xg[k], yg[k], xg[j],yg[j],xf[a[j]],yf[a[j]])*
72 s(xf[i], yf[i], xg[j],yg[j],xf[a[j]],yf[a[j]])<0)&&
73 (s(xg[j], yg[j], xg[k],yg[k],xf[i], yf[i])*
74 s(xf[a[j]],yf[a[j]],xg[k],yg[k],xf[i], yf[i])<0))
75 {
76 ok=false;
77 break;
78 }
79 if(!ok) continue;
80 a[k]=i;
81 if(k<n) f(k+1); else verificCostul();
82 }
83 }
84
85 static void verificCostul()
86 {
87 int i;
88 double s=0;
89 for(i=1;i<=n;i++) s=s+d[i][a[i]];
90 if(s<costMin) costMin=s;
91 }
92
93 //de ce parte a dreptei [(xa,ya);(xb,yb)] se afla (xp,yp)
94 static int s(int xp,int yp,int xa,int ya,int xb,int yb)
95 {
96 double s=(double)yp*(xb-xa)-xp*(yb-ya)+xa*yb-xb*ya;
97 if(s<-0.001) return -1; // in zona "negativa"
98 else if(s>0.001) return 1; // in zona "pozitiva"
99 else return 0; // pe dreapta suport
100 }
101
102 static void afisare() throws IOException
103 {
104 int k;
105 out=new PrintWriter(new BufferedWriter(new FileWriter("seceta.out")));
106 out.println((int)(costMin*100));
107 out.close();
108 }
109 }
Varianta 4:
16 long t1,t2;
17 t1=System.currentTimeMillis();
18
19 citire();
20 rezolvare();
21 afisare();
22
23 t2=System.currentTimeMillis();
24 System.out.println("Timp = "+(t2-t1)+" ms");
25 }// main(...)
26
27 static void citire() throws IOException
28 {
29 int k;
30 st=new StreamTokenizer(new BufferedReader(new FileReader("seceta.in")));
31 st.nextToken(); n=(int)st.nval;
32 xg=new int[n+1];
33 yg=new int[n+1];
34 xf=new int[n+1];
35 yf=new int[n+1];
36 a=new int[n+1];
37
38 d=new double[n+1][n+1];
39
40 for(k=1;k<=n;k++)
41 {
42 st.nextToken(); xg[k]=(int)st.nval;
43 st.nextToken(); yg[k]=(int)st.nval;
44 }
45 for(k=1;k<=n;k++)
46 {
47 st.nextToken(); xf[k]=(int)st.nval;
48 st.nextToken(); yf[k]=(int)st.nval;
49 }
50 }// citire(...)
51
52 static void rezolvare() throws IOException
53 {
54 int i,j;
55 int s;
56 for(i=1;i<=n;i++) // gradina i
57 for(j=1;j<=n;j++) // fantana j
58 {
59 s=(xg[i]-xf[j])*(xg[i]-xf[j])+(yg[i]-yf[j])*(yg[i]-yf[j]);
60 d[i][j]=Math.sqrt(s);
61 }
62 f(1); // generez permutari
63 }// rezolvare(...)
64
65 static void f(int k)
66 {
67 int i,j;
68 boolean seIntersecteaza;
69 for(i=1;i<=n;i++)
70 {
71 if(epus[i]) continue;
72 seIntersecteaza=false;
73 for(j=1;j<=k-1;j++)
74 if(d[k][i]+d[j][a[j]]>d[j][i]+d[k][a[j]])
75 {
76 seIntersecteaza=true;
77 break;
78 }
79
80 if(seIntersecteaza) continue;
81
82 a[k]=i;
83
84 epus[i]=true;
85 if(k<n) f(k+1); else verificCostul();
86 epus[i]=false;
87 }// for i
88 }// f(...)
89
90 static void verificCostul()
91 {
CAPITOLUL 35. ONI 2005 756
92 int i;
93 double s=0;
94 for(i=1;i<=n;i++) s=s+d[i][a[i]];
95 if(s<costMin) costMin=s;
96 }// verificCostul(...)
97
98 static void afisare() throws IOException
99 {
100 int k;
101 out=new PrintWriter(new BufferedWriter(new FileWriter("seceta.out")));
102 out.println((int)(costMin*100));
103 out.close();
104 }// afisare(...)
105 }// class
35.4 Biblos
Maria ³i Adrian Niµ
Din dorinµa de a realiza un fond de carte cât mai voluminos, ocialit µile ora³ului Ga-
laµi, au modernizat pentru început, o sal pentru depozitarea c rµilor ³i l-au numit pe Biblos
coordonatorul acestei biblioteci.
Achiziµionarea de carte s-a realizat în mai multe etape.
De ecare dat c rµile achiziµionate au fost depozitate pe câte un stativ construit special de
Biblos.
Pentru a avea spaµiu de depozitare Biblos a construit mai multe stative decât i-ar fost
necesare, unele putând r mâne f r c rµi.
Dup mai multe etape de achiziµionare, Biblos a constatat c spaµiul alocat bibliotecii este
prea mic.
Primind un alt spaµiu mai înc p tor, mut primul stativ cu toate c rµile conµinute de acesta
³i se opre³te deoarece î³i dore³te s mute acele stative care nu sunt a³ezate unul lâng cel lalt ³i
care fac ca fondul de carte din noua sal s e cât mai mare posibil.
Cerinµ
Scrieµi un program care, cunoscând num rul stativelor, precum ³i num rul de volume de carte
de pe ecare stativ, determin care este num rul maxim de volume care pot mutate în noua
sal , ³tiind c primul stativ a fost deja mutat iar celelalte se aleg astfel încât s nu e a³ezate unul
lâng cel lalt. Dac exist stative care nu au c rµi acestea nu vor mutate în a doua sal .
Date de intrare
Fi³ierul de intrare biblos.in conµine
a pe prima linie o valoare n, num r natural cu semnicaµia num rul de stative,
a pe a doua linie n numere naturale, x1 , x2 , ..., xn separate prin câte un spaµiu cu semnicaµia
xi = num rul de volume de carte existente pe ecare stativ.
Date de ie³ire
Fi³ierul de ie³ire biblos.out va conµine o singur linie unde se a un num r natural cu
semnicaµia: num rul maxim de volume ce au fost transferate.
Restricµii ³i preciz ri
a 1 & n & 30000
a 0 & xi & 32767, unde i 1, ..., n iar xi reprezint num rul de c rµi de pe stativul i.
a Pentru 70% dintre teste n & 1000
a Fiecare linie din ³ierul de intrare ³i din ³ierul de ie³ire se termin cu marcaj de sfâr³it de
linie.
Exemple
biblos.in biblos.out
7 16
1362584
Explicaµie: Suma maxim se obµine din mutarea stativelor 1 (obligatoriu), 3, 5, 7 (nu pot
stative al turate)
CAPITOLUL 35. ONI 2005 757
biblos.in biblos.out
15 836
3 1 84 9 89 55 135 49 176 238 69 112 28 175 142
Explicaµie: Suma maxim obµinut din mutarea stativelor 1, 3, 5, 7, 10, 12, 14
biblos.in biblos.out
8 32
7 1 4 12 9 9 12 4
Explicaµie: Suma maxim obµinut din mutarea stativelor 1, 3, 5, 7, sau din mutarea stativelor
1, 4, 6, 8.
Timp maxim de execuµie/test: 0.5 sec sub Windows ³i 0.1 sec sub Linux
Pentru toate celelalte valori cmax i, se observ c se poate folosi formula:
Prin alegerea maximului dintre valorile lui cmax, se obµine rezultatul cerut.
Pentru optimizare, se poate face observaµia c dintre valorile lui cmax, intereseaz doar cele
de pe poziµiile i 3 ³i i 2, deci:
dac cmax i 2 % cmax i 3
atunci cmax i cmax i 2 carti i
altfel cmax i cmax i 3 carti i/
Variant cu vectori.
36 }//class
35.5 Joc
Cristina Luca
Pe o tabl p trat de dimensiune n n se deseneaz o secvenµ de triunghiuri dreptunghic
isoscele.
Fiecare triunghi are vârfurile numerotate cu 1, 2 ³i 3 (2 corespunde unghiului drept iar ordinea
1, 2, 3 a vârfurilor este în sens invers acelor de ceasornic - vezi gura). Triunghiurile au catetele
paralele cu marginile tablei.
Primul triunghi, având lungimea catetei Lg , are vârful 1 pe linia L ³i coloana C ³i este orientat
ca în gur .
3
a
a a
a a a
1 a a a a 2
Jocul const în alipirea câte unui nou triunghi la unul din vârfurile 2 sau 3 ale triunghiului
curent. Dac se al tur colµului 2, noul triunghi se a³eaz cu vârful 1 în prelungirea laturii 1, 2 a
triunghiului curent, iar dac se al tur colµului 3 se a³eaz cu vârful 1 în prelungirea laturii 2, 3.
Iniµial noul triunghi este orientat ca ³i cel anterior. El se poate plasa pe tabl dac nu sunt
dep ³ite marginile acesteia sau nu se suprapune peste un alt triunghi. În caz contrar, se face o
o
singur rotaµie cu 90 spre stânga, obµinându-se o nou orientare a triunghiului. Dac nici în acest
caz noul triunghi nu poate plasat, jocul se opre³te.
Zona ocupat de primul triunghi se completez cu litera 'a'; zona celui de-al doilea se comple-
tez cu litera 'b', ³.a.m.d. Când literele mici ale alfabetului englez sunt epuizate, se reîncepe de la
'a'.
CAPITOLUL 35. ONI 2005 760
Cerinµ
Cunoscându-se dimensiunea tablei, poziµia primului triunghi (linie, coloan ) ³i lungimea catetei
precum ³i o secvenµ de triunghiuri care se doresc a alipite se cere s se genereze matricea
rezultat în nalul jocului.
Jocul se termin dac un triunghi nu mai poate alipit sau au fost plasate toate triunghiurile
descrise în secvenµ .
Date de intrare
În ³ierul de intrare joc.in, pe prima linie se a n (dimensiunea tablei). Pe a doua linie
separate prin câte un spaµiu se a : L (linia), C (coloana) ³i Lg (lungimea catetei) corespunz toare
primului triunghi. Urm toarele linii, pân la sfâr³itul ³ierului, conµin câte dou numere naturale
separate prin câte un singur spaµiu reprezentând colµul triunghiului curent la care va alipit
triunghiul urm tor ³i dimensiunea catetei triunghiului urm or.
Date de ie³ire
În ³ierul de ie³ire joc.out va a³at matricea rezultat . Celulele tablei care nu sunt com-
pletate cu litere ale alfabetului vor completate cu '.'.
Restricµii ³i preciz ri
a 1 & n & 100; 1 & C , L & n; 2 & Lg & n
a Fiecare linie din ³ierul de intrare ³i din c serul de iec sre se termin cu marcaj de sfâr³it
de linie.
Exemplu
joc.in joc.out
20 . . . . . . . . . . . . . . . . . . . .
16 8 4 . . . . . . . . . . . . . . . . . . . .
35 . . . . . . . . . . f f f f f e e e . .
23 . . . . . . . . . . f f f f . . e e . .
34 . . . . . . . . . . f f f . . . . e . .
23 . . . . . . . . . . f f . . d d d d . .
35 . . . . . . . . . . f . . . . d d d . .
33 . . . . . . h h g g g . . . b . d d . .
22 . . . . . . h . g g . . . b b . . d . .
34 j j j i i i i . g . . . b b b . . c . .
23 j j . i i i . . . . . b b b b . c c . .
33 j . . i i . . . . . b b b b b c c c . .
32 k . . i . . . . . . a . . . . . . . . .
33 k k . . . . . . . a a . . . . . . . . .
33 k k k l . . . . a a a . . . . . . . . .
24 . . . l l m . a a a a . . . . . . . . .
. . . . . m m . . . . . . . . . . . . .
. . . . . m m m n . . . . . . . . . . .
. . . . . . . . n n . . . . . . . . . .
. . . . . . . . n n n . . . . . . . . .
Explicaµii
Triunghiul 'a' este plasat în linia 16 coloana 8 ³i are latura 4.
Triunghiul 'b' se alipe³te în colµul 3 ³i are lungimea 5.
Triunghiul 'c' se alipe³te în colµul 2 ³i are lungimea 3.
Tringhiurile 'a', 'b' ³i 'c' p streaz aceea³i aranjare.
Triunghiul 'd' nu se poate alipi în aceea³i aranjare colµului 3 deoarece are cateta de lungimea
o
4 ³i dep ³e³te tabla. Rotim triunghiul cu 90 spre stânga ³i obµinem o nou aranjare.
Triunghiul 'e' se alipe³te în colµul 2 ³i are cateta de lungime 3 în aranjarea curent .
Triunghiul 'f' nu se poate alipi în aceea³i aranjare cu 'e' în colµul 3 deoarece are cateta de
o
lungimea 5 ³i dep ³e³te tabla. Rotim triunghiul cu 90 spre stânga ³i obµinem o nou aranjare.
Triunghiul 'f' se alipe³te în colµul 3, are lungimea 5 ³i o nou aranjare.
Algoritmul continu pân la al 14-lea triunghi, 'n'.
Al 15-lea triunghi nu se mai poate plasa.
Timp maxim de execuµie/test: 0.2 sec în Windows ³i 0.2 sec sub Linux
CAPITOLUL 35. ONI 2005 761
11 long t1,t2;
12 t1=System.currentTimeMillis();
13 int v,d,i,j;
14 int l1, c1, d1;
15 boolean ok=true;
16 StreamTokenizer st=new StreamTokenizer(
17 new BufferedReader(new FileReader("joc.in")));
18 PrintWriter out=new PrintWriter(
19 new BufferedWriter(new FileWriter("joc.out")));
20 st.nextToken(); n=(int)st.nval;
21
22 a=new int[n+1][n+1];
23 for(i=1;i<=n;i++) for(j=1;j<=n;j++) a[i][j]=-1;
24
25 st.nextToken(); l1=(int)st.nval; // linia varful 1
26 st.nextToken(); c1=(int)st.nval; // coloana varful 1
27 st.nextToken(); d1=(int)st.nval; // latura
28
29 val=0;
30 dir=0;
31 if(esteGol0(l1,c1,d1)) umple0(l1,c1,d1);
32 else if(esteGol1(l1,c1,d1)) {dir=(dir+1)%4; umple1(l1,c1,d1);}
33
34 while(ok&&(st.nextToken()!=StreamTokenizer.TT_EOF))
35 {
36 v=(int)st.nval;
37 st.nextToken(); d=(int)st.nval;
38 val=(val+1)%26;
39
40 if(v==2)
41 switch(dir)
42 {
43 case 0: if(esteGol0(l1,c1+d1,d)) // direct
44 {
45 c1=c1+d1; d1=d; umple0(l1,c1,d1);
46 }
47 else if(esteGol1(l1,c1+d1,d)) // rotit
48 {
49 c1=c1+d1; d1=d;
50 dir=(dir+1)%4;
51 umple1(l1,c1,d1);
52 }
53 else ok=false;
54 break;
55 case 1: if(esteGol1(l1-d1,c1,d)) // direct
56 {
57 l1=l1-d1; d1=d; umple1(l1,c1,d1);
58 }
59 else if(esteGol2(l1-d1,c1,d)) // rotit
60 {
61 l1=l1-d1; d1=d;
62 dir=(dir+1)%4;
63 umple2(l1,c1,d1);
64 }
65 else ok=false;
66 break;
67 case 2: if(esteGol2(l1,c1-d1,d)) // direct
68 {
69 c1=c1-d1; d1=d; umple2(l1,c1,d1);
70 }
71 else if(esteGol3(l1,c1-d1,d)) // rotit
72 {
73 c1=c1-d1;d1=d;
74 dir=(dir+1)%4;
75 umple3(l1,c1,d1);
76 }
77 else ok=false;
78 break;
79 case 3: if(esteGol3(l1+d1,c1,d)) // direct
80 {
81 l1=l1+d1;d1=d; umple3(l1,c1,d1);
82 }
83 else if(esteGol0(l1+d1,c1,d)) // rotit
84 {
85 l1=l1+d1; d1=d;
86 dir=(dir+1)%4;
CAPITOLUL 35. ONI 2005 763
87 umple0(l1,c1,d1);
88 }
89 else ok=false;
90 break;
91 default: System.out.println("Ciudat!!!");
92 }
93
94 if(v==3)
95 switch(dir)
96 {
97 case 0: if(esteGol0(l1-d1,c1+d1-1,d)) // direct
98 {
99 c1=c1+d1-1; l1=l1-d1; d1=d; umple0(l1,c1,d1);
100 }
101 else if(esteGol1(l1-d1,c1+d1-1,d)) // rotit
102 {
103 l1=l1-d1; c1=c1+d1-1; d1=d;
104 dir=(dir+1)%4;
105 umple1(l1,c1,d1);
106 }
107 else ok=false;
108 break;
109 case 1: if(esteGol1(l1-d1+1,c1-d1,d)) // direct
110 {
111 l1=l1-d1+1; c1=c1-d1; d1=d; umple1(l1,c1,d1);
112 }
113 else if(esteGol2(l1-d1+1,c1-d1,d)) // rotit
114 {
115 l1=l1-d1+1; c1=c1-d1; d1=d;
116 dir=(dir+1)%4;
117 umple2(l1,c1,d1);
118 }
119 else ok=false;
120 break;
121 case 2: if(esteGol2(l1+d1,c1-d1+1,d)) // direct
122 {
123 c1=c1-d1+1; l1=l1+d1; d1=d; umple2(l1,c1,d1);
124 }
125 else if(esteGol3(l1+d1,c1-d1+1,d)) // rotit
126 {
127 c1=c1-d1+1; l1=l1+d1; d1=d;
128 dir=(dir+1)%4;
129 umple3(l1,c1,d1);
130 }
131 else ok=false;
132 break;
133 case 3: if(esteGol3(l1+d1-1,c1+d1,d)) // direct
134 {
135 l1=l1+d1-1;c1=c1+d1; d1=d; umple3(l1,c1,d1);
136 }
137 else if(esteGol0(l1+d1-1,c1+d1,d)) // rotit
138 {
139 l1=l1+d1-1;c1=c1+d1; d1=d;
140 dir=(dir+1)%4;
141 umple0(l1,c1,d1);
142 }
143 else ok=false;
144 break;
145 default: System.out.println("Ciudat!!!");
146 }
147 }
148
149 for(i=1;i<=n;i++)
150 {
151 for(j=1;j<=n;j++)
152 if(a[i][j]==-1) out.print("."); else out.print((char)(a[i][j]+’a’));
153 out.println();
154 }
155 out.println();
156 out.close();
157
158 t2=System.currentTimeMillis();
159 System.out.println("Timp = "+(t2-t1)+" ms");
160 }
161
162 static void umple0(int lin, int col, int d) // 12=sd==>dir=0
CAPITOLUL 35. ONI 2005 764
163 {
164 int i,j,k;
165 for(k=0;k<d;k++)
166 {
167 i=lin-k;
168 for(j=col+k;j<col+d;j++) a[i][j]=val;
169 }
170 }
171
172 static boolean esteGol0(int lin, int col, int d)
173 {
174 int i,j,k;
175 if((lin-0>n)||(lin-d+1<1)||(col<1)||(col+d-1>n)) return false;
176 boolean gol=true;
177 for(k=0;k<d;k++)
178 {
179 i=lin-k;
180 for(j=col+k;j<col+d;j++) if(a[i][j]!=-1){ gol=false;break;}
181 }
182 return gol;
183 }
184
185 static void umple1(int lin, int col, int d) // 12=js==>dir=1
186 {
187 int i,j,k;
188 for(k=0;k<d;k++)
189 {
190 i=lin-k;
191 for(j=col-k;j<=col;j++) a[i][j]=val;
192 }
193 }
194
195 static boolean esteGol1(int lin, int col, int d)
196 {
197 int i,j,k;
198 if((lin-0>n)||(lin-d+1<1)||(col-d+1<1)||(col>n)) return false;
199 boolean gol=true;
200 for(k=0;k<d;k++)
201 {
202 i=lin-k;
203 for(j=col-k;j<=col;j++) if(a[i][j]!=-1) {gol=false; break;}
204 }
205 return gol;
206 }
207
208 static void umple2(int lin, int col, int d) // 12=ds==>dir=2
209 {
210 int i,j,k;
211 for(k=0;k<d;k++)
212 {
213 i=lin+k;
214 for(j=col-d+1;j<=col-k;j++) a[i][j]=val;
215 }
216 }
217
218 static boolean esteGol2(int lin, int col, int d)
219 {
220 int i,j,k;
221 if((lin<1)||(lin+d-1>n)||(col-d+1<1)||(col>n)) return false;
222 boolean gol=true;
223 for(k=0;k<d;k++)
224 {
225 i=lin+k;
226 for(j=col-d+1;j<=col-k;j++) if(a[i][j]!=-1){ gol=false;break;}
227 }
228 return gol;
229 }
230
231 static void umple3(int lin, int col, int d) // 12=sj==>dir=3
232 {
233 int i,j,k;
234 for(k=0;k<d;k++)
235 {
236 i=lin+k;
237 for(j=col;j<=col+k;j++) a[i][j]=val;
238 }
CAPITOLUL 35. ONI 2005 765
239 }
240
241 static boolean esteGol3(int lin, int col, int d)
242 {
243 int i,j,k;
244 if((lin<1)||(lin+d-1>n)||(col<1)||(col+d-1>n)) return false;
245 boolean gol=true;
246 for(k=0;k<d;k++)
247 {
248 i=lin+k;
249 for(j=col;j<=col+k;j++) if(a[i][j]!=-1) {gol=false; break;}
250 }
251 return gol;
252 }
253 }
35.6 Pal
Autor: Silviu G nceanu
Prinµul Algorel este în încurc tur din nou: a fost prins de Spânul cel Negru în încercarea
sa de a o salva pe prinµes ³i acum este închis în Turnul cel Mare.
Algorel poate evada dac g se³te combinaµia magic cu care poate deschide poarta turnului.
Prinµul ³tie cum se formeaz aceast combinaµie magic : trebuie s utilizeze toate cifrele scrise
pe u³a turnului pentru a obµine dou numere palindroame, astfel încât suma lor s e minim , iar
aceast sum este combinaµia magic ce va deschide u³a.
Primul num r palindrom trebuie s aib cel puµin L cifre, iar cel de-al doilea poate avea orice
lungime diferit de 0. Numerele palindroame formate nu pot începe cu cifra 0. Acum interveniµi
dumneavoastr în poveste, ind prietenul s u cel mai priceput în algoritmi.
Prin noul super-telefon al s u, prinµul transmite num rul de apariµii a ec rei cifre de pe u³a
turnului precum ³i lungimea minim L a primului num r, iar dumneavoastr trebuie s -i trimiteµi
cât mai repede numerele cu care poate obµine combinaµia magic .
Cerinµ
Având datele necesare, aaµi dou numere palindroame cu care se poate obµine combinaµia
magic .
Date de intrare
Prima linie a ³ierului pal.in conµine un num r întreg L reprezentând lungimea minim a
primului num r. Urmeaz 10 linii: pe linia i 2 se va aa un num r întreg reprezentând num rul
de apariµii ale cifrei i, pentru i cu valori de la 0 la 9.
Date de ie³ire
Prima linie a ³ierului de ie³ire pal.out conµine primul num r palidrom, iar cea de-a doua
linie conµine cel de-al doilea num r palindrom. Dac exist mai multe soluµii se va scrie doar una
dintre ele.
Restricµii ³i preciz ri
În total vor cel mult 100 de cifre
a
1 & L $ 100 ³i L va mai mic decât num rul total de cifre
a
a Pentru datele de test va exista întotdeauna soluµie: se vor putea forma din cifrele scrise pe
u³a turnului dou numere care încep cu o cifr diferit de 0, iar primul num r s aib cel puµin L
cifre
a Un num r este palindrom dac el coincide cu r sturnatul s u. De exemplu 12321 ³i 7007
sunt numere palindroame, în timp ce 109 ³i 35672 nu sunt.
a Pentru 30% dintre teste, num rul total de cifre va cel mult 7; pentru alte 40% din teste
num rul total de cifre va cel mult 18, iar pentru restul de 30% din teste num rul total de cifre
va mai mare sau egal cu 30.
a Fiecare linie din ³ierul de intrare ³i din ³ierul de ie³ire se termin cu marcaj de sfâr³it de
linie.
Exemplu
CAPITOLUL 35. ONI 2005 766
100
101 for(i=0;i<=9;i++)
102 if(fc[i]%2==1) { p1[imp1]=i; fc[i]--; break;}
103 for(i=0;i<=9;i++)
104 if(fc[i]%2==1) { p2[imp2]=i; fc[i]--; break;}
105
106 k1=0;
107 k2=0;
108 while(k1<nc1-nc2) {incarcPozitia(k1,p1); k1++;}// incarc numai p1
109 while((k1<imp1)||(k2<imp2))
110 {
111 if(k1<imp1) { incarcPozitia(k1,p1); k1++; }
112 if(k2<imp2) { incarcPozitia(k2,p2); k2++; }
113 }
114 }
115
116 static void corectez(int[] x)
117 {
118 int pozdif0,val, n=x.length;
119 pozdif0=0;
120 while(x[pozdif0]==0) pozdif0++;
121 if(pozdif0>0)
122 {
123 val=x[pozdif0];
124 x[0]=x[n-1]=val;
125 x[pozdif0]=x[n-pozdif0-1]=0;
126 }
127 }
128
129 static void incarcPozitia(int k, int[] x)
130 {
131 int i;
132 int n=x.length;
133 for(i=0;i<=9;i++)
134 if(fc[i]>0)
135 {
136 x[k]=i; fc[i]--;
137 x[n-k-1]=i; fc[i]--;
138 break;
139 }
140 }
141
142 static int[] suma(int[] x, int[] y)
143 {
144 int[] z=new int[(x.length>y.length) ? (x.length+1) : (y.length+1)];
145 int k,t=0;
146 for(k=0;k<=z.length-2;k++)
147 {
148 z[k]=t;
149 if(k<x.length) z[k]+=x[k];
150 if(k<y.length) z[k]+=y[k];
151 t=z[k]/10;
152 z[k]=z[k]%10;
153 }
154 z[z.length-1]=t;
155 if(z[z.length-1]!=0) return z;
156 else
157 {
158 int[] zz=new int[z.length-1];
159 for(k=0;k<zz.length;k++) zz[k]=z[k];
160 return zz;
161 }
162 }
163 }//class
Capitolul 36
ONI 2004
36.1 Coduri
Un detectiv particular are de rezolvat un caz special.
Este vorba de o deturnare de fonduri. Pentru a putea rezolva cazul trebuie s g seasc un ³ir
cu n coduri distincte. Fiecare cod este un num r natural scris în baza 10.
Din p cate lucrurile nu sunt simple, pentru c din cercet rile efectuate a obµinut dou infor-
maµii. Prima informaµie este legat de faptul c suma p tratelor codurilor este un cub perfect,
iar a doua spune c suma cuburilor codurilor este un p trat perfect.
Cerinµ
Ajutaµi detectivul s g sesc un ³ir de coduri x1 , x2 , ..., xn , care veric condiµiile din enunµ ³i
xi & n14 , pentru orice i cu 1 & i & n.
Date de intrare
Fi³ierul de intrare coduri.in conµine pe prima linie num rul natural n.
Date de ie³ire
Fi³ierul de ie³ire coduri.out va conµine n linii, câte una pentru ecare cod din ³ir, în ordine
cresc toare.
Restricµii
a 1 & n & 20
Exemplu
coduri.in coduri.out
2 625
1250
Timp maxim de execuµie: 1 sec/test
k s ,1&k & n.
4
Fie s n n 1 2n 1©6. Se pot considera codurile xk
769
CAPITOLUL 36. ONI 2004 770
71 suma(x,dx,t,dt,u,du);
72 dt:=du;
73 for k:=1 to du do t[k]:=u[k];
74 end;
75 for j:=1 to i-1 do
76 begin
77 inc(dt);
78 t[dt]:=0;
79 end;
80 suma(z,dz,t,dt,u,du);
81 dz:=du;
82 for j:=1 to du do z[j]:=u[j];
83 end;
84 end;{produs}
85
86 begin
87 assign(f,’coduri.in’);
88 reset(f);
89 readln(f,n);
90 close(f);
91 m:=n*(n+1)*(2*n+1) div 6;
92 str(m,sm);
93 ds:=length(sm);
94 for i:=1 to ds do
95 val(sm[i],s[i],er);
96 produs(s,ds,s,ds,x,dx);
97 s:=x;ds:=dx;
98 produs(s,ds,s,ds,x,dx);
99 s:=x;ds:=dx;
100
101 assign(f,’coduri.out’);
102 rewrite(f);
103 for i:=1 to n do
104 begin
105 str(i,si);
106 di:=length(si);
107 for j:=1 to di do
108 val(si[j],ii[j],er);
109 produs(ii,di,s,ds,x,dx);
110 for j:=1 to dx do
111 write(f,x[j]);
112 writeln(f);
113 end;
114 close(f);
115 end.
2 2 2 n n 1 2n 1 3 3 3 n n 1 2
1 2 ... n ³i 1 2 ... n
6 2
3 3 3 3 n n 1 2
x1 x2 ... xn α
2
2
³i pentru a obµine un p trat perfect vom considera α β , deci codurile vor considerate sub
2
forma xk β k .
Acum suma cuburilor
3 3 3 6 n n 1 2
x1 x2 ... xn β
2
este un p trat perfect.
Suma p tratelor codurilor este
2 2 2 4n n 1 2n 1 3 n n 1 2n 1
x1 x2 ... xn β β β
6 6
³i pentru a obµine un cub perfect putem considera
n n 1 2n 1 2
β .
6
n n 1 2n 1 4
xk k .
6
36.2 Logic
Demonstrarea automat a teoremelor ³i vericarea satisabilit µii unei formule constituie dou
capitole importante în cadrul logicii matematice.
Formulele propoziµionale sunt alc tuite din variabile propoziµionale (variabile care pot lua doar
dou valori: sau adev rat sau fals) ³i din operatorii logici ³i, sau, negaµie, echivalent, implic .
CAPITOLUL 36. ONI 2004 773
Informaµia "în formul nu apar mai mult de 10 litere mici ale alfabetului latin" ne conduce
10
la ideea de a genera toate conguraµiile (sunt cel mult 2 1024) ³i a calcula valoarea de
adev r a formulei pentru ecare conguraµie. Se folose³te recursivitatea µinând cont de priorit µile
operatorilor.
58 }
59 return value;
60 }
61
62 int implicatie(void)
63 {
64 int value = sau(), v;
65
66 while (e[pos] == ’=’)
67 {
68 pos += 2;
69 v = implicatie();
70 value = (!value) || v;
71 }
72 return value;
73 }
74
75 int echivalenta(void)
76 {
77 int value = implicatie(), v;
78
79 while (e[pos] == ’<’)
80 {
81 pos += 3;
82 v = echivalenta();
83 value = value == v;
84 }
85 return value;
86 }
87
88 int main(void)
89 {
90 FILE *fi, *fo;
91 int len, result;
92 int i, j;
93 int a[256];
94
95 memset(e, 0, sizeof(e));
96 fi = fopen("logic.in", "r");
97 fscanf(fi, "%s", e);
98 len = strlen(e);
99 fclose(fi);
100
101 memset(a, 0, sizeof(a));
102 for (i = 0; i < len; i++) a[(int)e[i]]++;
103 nv = 0;
104 for (i = ’a’; i <= ’z’; i++)
105 if (a[i]) c[nv++] = i;
106
107 result = 0;
108 for (i = 0; i < (1 << nv); i++)
109 {
110 for (j = 0; j < nv; j++)
111 t[(int)c[j]] = i & (1 << j) ? 1 : 0;
112 pos = 0;
113 result += echivalenta();
114 }
115
116 fo = fopen("logic.out", "w");
117 fprintf(fo, "%d\n", result);
118 fclose(fo);
119
120 return 0;
121 }
3 {
4 static char[] e; // expresia
5
6 public static void main(String[]args) throws IOException
7 {
8 int i,n;
9 PrintWriter out = new PrintWriter(
10 new BufferedWriter(new FileWriter("logic.out")));
11 BufferedReader br=new BufferedReader(new FileReader("logic.in"));
12
13 e=br.readLine().toCharArray();
14 n=e.length;
15 for(i=0;i<n;i++) System.out.print(e[i]);
16 System.out.println();
17
18 System.out.println("~ "+(int)’~’);
19 System.out.println("& "+(int)’&’);
20 System.out.println("| "+(int)’|’);
21 System.out.println("< "+(int)’<’);
22 System.out.println("= "+(int)’=’);
23 System.out.println("> "+(int)’>’);
24 System.out.println("a "+(int)’a’);
25 System.out.println("z "+(int)’z’);
26 out.close();
27 }//main
28 }//class
69 boolean a, b, val;
70 a=not();
71 val=a;
72 if((poz<n)&&(e[poz]==’&’)) {poz++; b=si(); val=(a&&b);}
73 return val;
74 }
75
76 static boolean not()
77 {
78 boolean val;
79 if(e[poz]==’~’) {poz++; val=!not();}
80 else val=paranteza();
81 return val;
82 }
83
84 static boolean paranteza()
85 {
86 boolean val;
87 if(e[poz]==’(’) {poz++;val=formula(); poz++;}
88 else if(e[poz] == ’)’) val=false;
89 else val=variabila();
90 return val;
91 }
92
93 static boolean variabila()
94 {
95 boolean val;
96 if((poz<n)&&(e[poz]>=’a’)&&(e[poz]<=’z’)) val=v[(int)e[poz++]];
97 else val=formula();
98 return val;
99 }
100 }//class
36.3 Poligon
Se d un caroiaj de M N în care sunt plasate K puncte. Fiecare punct poate legat de
vecinul s u direct pe maxim opt direcµii (N , N E , E , SE , S , SV , V , N V ).
Cerinµ
Determinaµi patrulaterele având vârfurile în punctele date iar laturile formate din leg turi între
dou sau mai multe puncte coliniare.
Date de intrare
Fi³ierul de intrare poligon.in conµine
a pe prima linie trei numere naturale nenule, separate prin câte un spaµiu,
M N K
reprezentând dimensiunile M , N ale caroiajului ³i K num rul de puncte, iar
a pe urm toarele K linii câte trei numere naturale separate printr-un spaµiu,
Ii Ji Vi
reprezentând coordonatele punctului i, 1 & i & K respectiv direcµiile
spre care este legat de vecini direcµi.
Codicarea direcµiilor se face printr-un num r cuprins între 0 ³i 255.
Reprezentarea binar a acestuia pe 8 cifre reprezint , începând de la stânga
spre dreapta, leg tur pe direcµiile (1 - legatur , 0 - nu ):
N N E E SE S SV V N V .
De exemplu: 1 0 0 0 0 1 1 0 = 134 deci leg turi spre N , SV , V
Date de ie³ire
Fi³ierul de ie³ire poligon.out conµine numai num rul natural
npol
reprezentând num rul patrulaterelor.
Restricµii
1 $ M, N & 100
4 & K & 50
CAPITOLUL 36. ONI 2004 780
Exemplu
POLIGON.IN POLIGON.OUT
449 6
1 1 24
2 1 184
2 2 43
2 3 22
3 1 136
3 2 213
345
4 1 192
4 3 65
Se genereaz toate combin rile de câte 4 puncte ³i se veric dac acestea pot porma un
patrulater (tinând cont de direcµii).
28 a[i,j]:=v;
29 e[k]:=(i-1)*m+j;
30 end;
31 close(f);
32 end;
33
34 Function traseu(vi,vf,i1,c1,i2:byte;c2:integer;c:byte):boolean;
35 var aux,i:byte;
36 begin
37 if vi>vf then begin aux:=vi;vi:=vf;vf:=aux end;
38 traseu:=true;
39 for i:=vi to vf-1 do
40 if a[i1+c1*i,i2+c2*i] and d[c] <> d[c] then
41 traseu:=false
42 end;
43
44 Function verif(var x:sir; p:integer):boolean;
45 var i,j,l1,c1,l2,c2,t,nc,nl,ndp,nds:byte;
46 begin
47 if p=1 then verif:=true
48 else
49 begin
50
51 verif:=true;
52 nc:=0;nl:=0;ndp:=0;nds:=0;
53 l1:=(e[x[p]]-1) div n +1;
54 c1:=(e[x[p]]-1) mod n +1;
55 for i:=1 to p-1 do
56 begin
57 l2:=(e[x[i]]-1) div n +1;
58 c2:=(e[x[i]]-1) mod n +1;
59 if (c1=c2) then inc(nc);
60 if (l1=l2) then inc(nl);
61 if l1-l2=c1-c2 then inc(ndp);
62 if l1-l2=c2-c1 then inc(nds);
63 end;
64 if (nc>1) or (nl>1) or (ndp>1) or (nds>1) then verif:=false;
65 end;
66 end;
67
68 Function este(y:vecini):boolean;
69 var i,l1,c1,l2,c2,min,max:byte;
70 cod:boolean;
71 begin
72 este:=true;
73 for i:=1 to k do
74 begin
75 cod:=false;
76 l1:=(e[x[y[i+1]]]-1) div n +1;
77 c1:=(e[x[y[i+1]]]-1) mod n +1;
78 l2:=(e[x[y[i]]]-1) div n +1;
79 c2:=(e[x[y[i]]]-1) mod n +1;
80 min:=trunc(((l1+l2)-abs(l1-l2))/2);
81 if (c1=c2) and traseu(l1,l2,0,1,c1,0,5) then cod:=true;
82 if (l1=l2) and traseu(c1,c2,l1,0,0,1,3) then cod:=true;
83 if (l1-l2=c1-c2) and
84 traseu(0,abs(c1-c2),min,1,trunc(((c1+c2)-abs(c1-c2))/2),1,4)
85 then cod:=true;
86 if (l1-l2=c2-c1)
87 and traseu(0,abs(c1-c2),min,1,trunc(((c1+c2)+abs(c1-c2))/2),-1,6)
88 then cod:=true;
89 if not cod then este:=false;
90 end;
91 end;
92
93 Procedure Poligon(x:sir;n:integer);
94 var i:byte;
95 begin
96 if este(x1) or este(x2) or este(x3) then
97 begin
98 inc(nr);
99 {for i:=1 to n do
100 write(f,e[x[i]],’,’);
101 writeln(f);}
102 end;
103 end;
CAPITOLUL 36. ONI 2004 782
104
105 procedure comb (p:integer);
106 var i:integer;
107 begin
108 for i:=x[p-1]+1 to l do
109 begin
110 x[p]:=i;
111 if verif(x,p) then
112 if p=k then
113 Poligon(x,k)
114 else
115 comb(p+1);
116 end;
117 end;
118
119 begin
120 {writeln(’Incepem’);
121 timeinit:=time;
122 writeln(time);}
123 nr:=0;
124 assign(f,’poligon.out’);
125 rewrite(f);
126 k:=4;
127 citire(a,m,n,l);
128 comb(1);
129 writeln(f,nr);
130 close(f);
131 {writeln(time,’/’,(timeinit-time)/18:4:2); }
132 end.
39 generezCombinariPePozitia(1);
40
41 out.println(nsol);
42 out.close();
43 t2=System.nanoTime();
44 System.out.println("Timp = "+((double)(t2-t1))/1000000000);
45 }
46
47 static void generezCombinariPePozitia(int j)
48 {
49 int i;
50 for(i=a[j-1]+1;i<=k-4+j;i++)
51 {
52 a[j]=i;
53 if(j<4) generezCombinariPePozitia(j+1);
54 else if(ePoligonOK()) nsol++;
55 }
56 }
57
58 static boolean ePoligonOK()
59 {
60 if(coliniare3Puncte()) return false;
61 if(ePoligon(a[1],a[2],a[3],a[4])) return true;
62 if(ePoligon(a[1],a[2],a[4],a[3])) return true;
63 if(ePoligon(a[1],a[3],a[2],a[4])) return true;
64 if(ePoligon(a[1],a[3],a[4],a[2])) return true;
65 if(ePoligon(a[1],a[4],a[2],a[3])) return true;
66 if(ePoligon(a[1],a[4],a[3],a[2])) return true;
67 return false;
68 }
69
70 static boolean coliniare3Puncte()
71 {
72 if(coliniare(a[1],a[2],a[3])) return true;
73 if(coliniare(a[1],a[2],a[4])) return true;
74 if(coliniare(a[1],a[3],a[4])) return true;
75 if(coliniare(a[2],a[3],a[4])) return true;
76 return false;
77 }
78
79 static boolean coliniare(int p1, int p2, int p3)
80 {
81 int s;
82 s=x[p1]*y[p2]+x[p2]*y[p3]+x[p3]*y[p1];
83 s=s-y[p1]*x[p2]-y[p2]*x[p3]-y[p3]*x[p1];
84 if(s==0) return true; else return false;
85 }
86
87 static boolean ePoligon(int p1, int p2, int p3, int p4)
88 {
89 if(!eLinie(p1,p2)) return false;
90 if(!eLinie(p2,p3)) return false;
91 if(!eLinie(p3,p4)) return false;
92 if(!eLinie(p4,p1)) return false;
93 if(eNedegenerat(p1,p2,p3,p4)) return true; else return false;
94 }
95
96 static boolean eLinie(int p1, int p2) // trece prin coordonate intregi!
97 {
98 if(Math.abs(x[p1]-x[p2])==Math.abs(y[p1]-y[p2])) return eLinieOkOblica(p1,p2);
99 else if(x[p1]==x[p2]) return eLinieOkVerticala(p1,p2);
100 else if(y[p1]==y[p2]) return eLinieOkOrizontala(p1,p2);
101 else return false;
102 }
103
104 static boolean eLinieOkOrizontala(int p1, int p2)
105 {
106 int i;
107 if(x[p1]>x[p2]) {i=p1;p1=p2;p2=i;} // p1 ... p2
108
109 for(i=x[p1]+1; i<=x[p2]; i++)
110 {
111 if(ePunctIn[y[p1]][i]==0) return false;
112 else if((d[ePunctIn[y[p1]][i]]&(1<<1))==0) // linie spre V
113 return false;
114 }
CAPITOLUL 36. ONI 2004 784
36.4 ablon
Gigel ³i Vasilic imagineaz un mod de a transmite mesaje pe care nimeni s nu le poat
descifra. Mesajul este ascuns într-un text care are N linii ³i pe ecare linie sunt exact N caractere
- litere mari ale alfabetului englez, cifre, semne de punctuaµie ³i caracterul spaµiu.
Decodicarea se face cu ajutorul unui ³ablon, de acelea³i dimensiuni ca ³i textul, care are
câteva g uri.
Suprapunând ³ablonul peste text r mân vizibile câteva caractere.
Acestea se citesc în ordinea liniilor, de sus în jos, iar pe aceea³i linie de la stânga la dreapta.
CAPITOLUL 36. ONI 2004 785
o
Apoi hârtia cu textul se rote³te spre stânga, în sens trigonometric, cu 90 , ³ablonul r mânând
x. Alte caractere devin vizibile ³i acestea se citesc în acela³i mod.
o o
Operaµia se repet de înc dou ori (rotire cu 180 , respectiv cu 270 ), pân când textul
o
ajunge, printr-o nou rotaµie cu 90 , din nou în poziµia iniµial .
Din p cate, ³ablonul pentru codicare/decodicare s-a pierdut. În schimb a r mas la Gigel
mesajul iniµial iar la Vasilic a ajuns textul care conµine mesajul.
Cerinµ
S se reconstituie ³ablonul care a fost folosit la codicare.
Date de intrare
Fi³ierul de intrare sablon.in conµine
a pe prima linie, mesajul iniµial
a pe linia a doua a ³ierului de intrare se g se³te valoarea N
a urm toarele N linii conµin textul care ascunde mesajul.
Date de ie³ire
Fi³ierul de ie³ire sablon.out conµine N linii a câte N caractere. Caracterele sunt 'O' (pentru
reprezentarea unei g uri) ³i 'X'.
Restricµii ³i
a prin rotirea textului nici una din g uri nu se va suprapune peste nici una
din poziµiile ocupate de o gaur în poziµiile precedente ale textului
a 1 & N & 50
a mesajul are maxim 1000 caractere ³i se încheie cu un caracter diferit de
spaµiu
a în cazul în care exist mai multe soluµii, a³aµi una dintre ele
Exemplu
sablon.in sablon.out
CODIFICARE CU SABLON XXXXOXXXXX
10 XXOXXXXXXX
ABCDCEFAGH OXXXXXXXXX
IJOKLEMNOP XXXOXXXXXX
DQRSTUVWCX XOXXXXXXXX
YZAIBCRDEF XXXXXXXXXX
GFHIJKLMNI XXXXXXXXXX
AJKLMNOPSQ XXXXXXXXXX
RSTOUV WXY XXXXXXXXXX
ZBABCDEFGU XXXXXXXXXX
HIJKNLMCNO
PQLRS TUVW
Timp de execuµie: 1 sec/test
Soluµia ocial
Problema se rezolv relativ simplu µinând cont de urm toarele observaµii:
1. Deoarece întregul mesaj a fost codicat prin 4 rotiri ale textului, este clar c la o poziµionare a
textului sub ³ablon pot citite Lung M esaj ©4 caractere, deci întregul mesaj are 4N umarGauri
caractere
2. Ca urmare a observaµiei de la punctul 1, mesajul poate împartit exact în 4 ³iruri de
lungimi egale M esaj1, ..., M esaj4
3. Dac o gaur se a în poziµia T i, j din ³ablon, ei îi corespund poziµiile
4. Dac lungimea unui ³ir este L4 (vezi în surs ), este sucient s parcurgem numai primul
din cele 4 ³iruri cu un Index. Atunci, parcurgând textul care ascunde mesajul, în poziµia i, j
exist o gaur în ³ablon dac ³i numai dac toate cele 4 caractere
60 i, j: Integer;
61 Lung: Integer;
62 M : Array[1..1000] Of Char;
63 Begin
64 Assign(f, ’sablon.in’); reset (f);
65 Lung := 0;
66 FillChar(M, SizeOf(M), #0);
67 While Not Eoln(f) Do {citesc mesajul in sirul de caractere}
68 Begin {determinandu-i lungimea}
69 Inc(Lung);
70 Read(f, M[Lung]);
71 End;
72 ReadLn(f, N); {citesc N}
73 For i := 1 To N Do {citesc textul in T}
74 Begin
75 For j := 1 To N Do
76 Read(f, T[i,j]);
77 Readln(f);
78 End;
79 Close(f);
80 If Lung Mod 4<>0 Then
81 WriteLn(’Mesajul nu are lungimea corecta’)
82 Else
83 Begin
84 L4 := Lung Div 4; {determin numarul de caractere la o rotire}
85 For i := 1 To L4 Do {si impart mesajul in 4 parti egale}
86 Begin
87 Mesaj[1][i] := M[i];
88 Mesaj[2][i] := M[L4+i];
89 Mesaj[3][i] := M[2*L4+i];
90 Mesaj[4][i] := M[3*L4+i]
91 End
92 End
93 End;
94
95 Begin
96 Citire;
97 Prelucrare;
98 Afisare;
99 End.
28 }
72 }
36.5 ir
Gigel se distreaz construind ³iruri cresc toare de numere din mulµimea r1, 2, ..., nx. La un
moment dat observ c unele ³iruri, de cel puµin k termeni (k ' 3), au o proprietate mai aparte:
diferenµa dintre doi termeni consecutivi este constant . Iat câteva exemple de astfel de ³iruri
pentru n ' 21:
2,3,4
1,5,9,13
7,10,13,16,19,21
Cerinµ
Dându-se num rul natural n ajutaµi-l pe Gigel s numere câte astfel de ³iruri poate s con-
struiasc .
Date de intrare
În ³ierul de intrare sir.in se g se³te, pe prima linie, num rul n.
Date de ie³ire
În ³ierul de ie³ire sir.out se va a³a, pe prima linie, num rul cerut urmat de caracterul sfâr³it
de linie.
Restricµii:
a 3 & n & 20000
a 3&k&n
Exemple:
sir.in sir.out
3 1
4 3
5 7
Timp execuµie: 1 sec/test
Soluµia ocial
Notând cu r diferenta dintre doi tereni consecutivi constat m c pentru r 1 se pot construi
urmatoarele submulµimi, ³iruri cu proprietea cerut , de lungime 3:
Cele de lungime superioar se construiesc ad ugând elemente pe cele deja obµinute. Num rul
<
n2
lor va i 1 i.
Similar pentru r 2 obµinem urm toarele submulµimi, ³iruri de lungime 3:
Cele de lungime superioar se construiesc ad ugând elemente pe acestea. Numarul lor este o
sum te tipul precedent.
Se continu astfel pân la r n©2, valoarea maxim a lui r.
5 begin
6 assign(f,’sir.in’);
7 assign(g,’sir.out’);
8 reset(f);rewrite(g);
9 s:=0;
10 readln(f,n);
11 for r:= 1 to n div 2 do
12 begin
13 i:= n-2*r;
14 while i>0 do
15 begin
16 s:=s+i;
17 i:= i-r;
18 end;
19 end;
20 writeln(g,s);
21 Close(g)
22 end.
36.6 Snipers
Se spune c în timpul r zboiului cu gnomii, trolii au trimis n tr g ori de elit s lichideze cele
n c petenii inamice.
Din fericire c peteniile inamice erau plasate în câmp deschis, iar tr g torii au reu³it s se
plaseze în zon f r s e observaµi.
Când s e dat comanda de tragere s-a constatat c nu se transmisese ec rui tr g tor ce
c petenie s împu³te, iar dac doi tr g tori ar tras în aceea³i c petenie sau traiectoriile razelor
uciga³e s-ar intersectat, atunci ar sc pat cel puµin o c petenie care ar putut duce r zboiul
pân la cap t, iar trolii ar fost învin³i.
Deoarece c peteniile aveau capacitatea de a deveni invizibile oricând doreau (pe o perioad
nelimitat ), trebuiau lichidate simultan, altfel ...
Istoria ne spune c trolii au învins deoarece comandantul lor a reu³i ca în mai puµin de o
secund s transmit ec rui tr g tor în ce c petenie s trag .
Voi puteµi face asta?
Cerinµ
Scrieµi un program care, citind poziµiile tr g torilor ³i a c peteniilor, determin c petenia în
care trebuie s trag ecare tr g tor.
Date de intrare
CAPITOLUL 36. ONI 2004 791
Date de ie³ire
Fi³ierul de ie³ire snipers.out conµine n linii.
Pe linia i a ³ierului se a num rul c peteniei µintite de tr g torul i
(i 1...n).
Restricµii ³i preciz ri
a 0 $ n $ 200
a Coordonatele sunt numere întregi din intervalul [0, 50000]
a Raza uciga³ a oric rei arme se opre³te în µinta sa.
a În datele de intrare nu vor exista trei persoane aate în puncte coliniare.
Exemple
snipers.in snipers.out snipers.in snipers.out
2 1 5 2
1 3 2 6 6 5
1 1 4 12 1
3 4 2 8 3
3 1 9 4 4
5 2
6 11
9 7
3 9
1 4
7 3
Timp de execuµie: 1 sec/test
Soluµia ocial
La început ec rui tragator i îi asociem capetenia i, dup care vom lua în considerare toate
perechile tr g tor-c petenie ³i vom elimina încruci³ rile razelor, la câte dou perechi prin in-
terschimbarea µintelor tr g torilor.
Se vor face interschimb ri între câte dou perechi tr g tor-µint pâna când nu vor mai exista
intersecµii.
Se observ c la eliminarea unei intersecµii suma distanµelor dintre tr g tori ³i µinte scade, ceea
ce asigur nitudinea algoritmului.
54 {
55 j=j+1;
56 seIntersecteaza_ij=seIntersecteaza(xt[i],yt[i],xc[t[i]],yc[t[i]],
57 xt[j],yt[j],xc[t[j]],yc[t[j]]);
58 if(seIntersecteaza_ij)
59 {
60 aux=t[i];t[i]=t[j];t[j]=aux; // interschimbam tintele
61 ok=false; // nu avem combinatie buna
62 }
63 } while ((j!=n) && !seIntersecteaza_ij);
64 if(!seIntersecteaza_ij) i++; // trecem la urmatorul sniper
65 } while(i!=n); // pana terminam lista de tragatori
66 } while(!ok);
67 }
68
69 //de ce parte a dreptei [(xa,ya);(xb,yb)] se afla (xp,yp)
70 static int s(int xp,int yp,int xa,int ya,int xb,int yb)
71 {
72 double s=(double)yp*(xb-xa)-xp*(yb-ya)+xa*yb-xb*ya;
73 if(s<-0.001) return -1;
74 else if(s>0.001) return 1;
75 else return 0;
76 }
77
78 // testeaza daca segmentul[a1,b1] se intersecteaza cu [a2,b2]
79 static boolean seIntersecteaza(int xa1,int ya1,int xb1,int yb1,
80 int xa2,int ya2,int xb2,int yb2)
81 {
82 // a2 si b2 se afla de o parte si de alta a lui [a1,b1] si
83 // a1 si b1 se afla de o parte si de alta a lui [a2,b2]
84 return (s(xa2,ya2,xa1,ya1,xb1,yb1)*s(xb2,yb2,xa1,ya1,xb1,yb1)<0) &&
85 (s(xa1,ya1,xa2,ya2,xb2,yb2)*s(xb1,yb1,xa2,ya2,xb2,yb2)<0);
86 }
87
88 static void afisare() throws IOException
89 {
90 int k;
91 out=new PrintWriter(new BufferedWriter(new FileWriter("snipers.out")));
92 for(k=1;k<=n;k++) out.println(t[k]);
93 out.close();
94 }
95 }
Capitolul 37
ONI 2003
37.1 Seti
Cercet torii ce lucreaz la programul SETI au recepµionat dou transmisii de date foarte
ciudate, date care ar putea veni din partea unor civilizaµii extraterestre. Primul set de date
este format din 10 caractere distincte, date în ordinea lor lexicograc , ce formeaz alfabetul
extraterestru. A doua transmisie conµine cuvinte din exact 4 caractere.
Cerinµ
Cercet torii trebuie s ordoneze lexicograc cuvintele primite în a doua transmisie (conform
alfabetului extraterestru).
Date de intrare
Fi³ierul de intrare seti.in conµine pe prima linie cele 10 caractere ale alfabetului, iar pe ecare
din urm toarele linii câte un cuvânt.
Date de ie³ire
Fi³ierul de ie³ire seti.out va conµine cuvintele ordonate, câte unul pe linie.
Restricµii ³i preciz ri
a În ³ier nu sunt mai mult de 200.000 de cuvinte, iar caracterele sunt literele mici ale alfabe-
tului englez.
a Datele de intrare se presupun ca ind corecte.
Exemplu
seti.in seti.out
abcdefghij aaaa
aaaa aabc
fgaa fgaa
aabc iihf
iihf
Timp de execuµie: 1 sec/test
795
CAPITOLUL 37. ONI 2003 796
2 class Seti1
3 {
4 static int[] codd=new int[10];
5 static int[] codi=new int[26];
6 static char[] caractercd=new char[10];
7 static int[] f=new int[10000];
8
9 public static void main(String[]args) throws IOException
10 {
11 String alfabet,cuvant;
12 int i,nr;
13 long t1,t2;
14 t1=System.currentTimeMillis();
15 PrintWriter out = new PrintWriter(
16 new BufferedWriter(new FileWriter("seti.out")));
17 StreamTokenizer st=new StreamTokenizer(
18 new BufferedReader(new FileReader("seti.in")));
19
20 st.nextToken(); alfabet=st.sval.toString();
21 System.out.println(alfabet);
22
23 for(i=0;i<10;i++)
24 {
25 codd[i]=alfabet.charAt(i)-’a’;
26 caractercd[i]=alfabet.charAt(i);
27 }
28 for(i=0;i<10;i++)
29 System.out.println(i+" : "+codd[i]+" "+caractercd[i]);
30 System.out.println();
31
32 for(i=’a’;i<=’z’;i++) codi[i-’a’]=-1;
33 for(i=0;i<10;i++) codi[codd[i]]=i;
34
35 for(i=0;i<=’z’-’a’;i++)
36 System.out.println(i+" : "+codi[i]+" "+(char)(i+’a’));
37 System.out.println();
38
39 while(st.nextToken()!=st.TT_EOF) // preluarea cuvantului
40 {
41 cuvant=st.sval.toString(); // conversia in String
42 nr=0;
43 for(i=0;i<4;i++) nr=nr*10+codi[cuvant.charAt(i)-’a’];
44 System.out.println(cuvant+" "+nr);
45 f[nr]++;
46 }
47
48 for(i=0;i<10000;i++)
49 if(f[i]>0)
50 {
51 cuvant=cuvantul(i);
52 for(nr=1;nr<=f[i];nr++) out.println(cuvant);
53 }
54 out.close();
55 t2=System.currentTimeMillis();
56 System.out.println("Timp = "+(t2-t1));
57 }//main
58
59 static String cuvantul(int nr)
60 {
61 int r,i;
62 char[] c=new char[4];
63 for(i=0;i<4;i++) c[i]=caractercd[0];
64
65 i=3;
66 while(nr!=0)
67 {
68 r=nr%10;
69 c[i]=caractercd[r];
70 nr=nr/10;
71 i--;
72 }
73 String s=new String(c);
74 return s;
75 }
76 }//class
CAPITOLUL 37. ONI 2003 798
Versiune nala!
Listing 37.1.3: seti1.java
1 import java.io.*;
2 class Seti2
3 {
4 static int[] codd=new int[10];
5 static int[] codi=new int[26];
6 static char[] caractercd=new char[10];
7 static int[] f=new int[10000];
8
9 public static void main(String[]args) throws IOException
10 {
11 String alfabet,cuvant;
12 int i,nr;
13 long t1,t2;
14 t1=System.currentTimeMillis();
15 PrintWriter out = new PrintWriter(
16 new BufferedWriter(new FileWriter("seti.out")));
17 StreamTokenizer st=new StreamTokenizer(
18 new BufferedReader(new FileReader("seti.in")));
19
20 st.nextToken(); alfabet=st.sval.toString();
21
22 for(i=0;i<10;i++)
23 {
24 codd[i]=alfabet.charAt(i)-’a’;
25 caractercd[i]=alfabet.charAt(i);
26 }
27
28 for(i=’a’;i<=’z’;i++) codi[i-’a’]=-1;
29 for(i=0;i<10;i++) codi[codd[i]]=i;
30
31 while(st.nextToken()!=st.TT_EOF) // preluarea cuvantului
32 {
33 cuvant=st.sval.toString(); // conversia in String
34 nr=0;
35 for(i=0;i<4;i++) nr=nr*10+codi[cuvant.charAt(i)-’a’];
36 f[nr]++;
37 }
38
39 for(i=0;i<10000;i++)
40 if(f[i]>0)
41 {
42 cuvant=cuvantul(i);
43 for(nr=1;nr<=f[i];nr++) out.println(cuvant);
44 }
45 out.close();
46 t2=System.currentTimeMillis();
47 System.out.println("Timp = "+(t2-t1));
48 }//main
49
50 static String cuvantul(int nr)
51 {
52 int i;
53 char[] c=new char[4];
54 for(i=0;i<4;i++) c[i]=caractercd[0];
55
56 i=3;
57 while(nr!=0)
58 {
59 c[i]=caractercd[nr%10];
60 nr=nr/10;
61 i--;
62 }
63 String s=new String(c);
64 return s;
65 }
66 }//class
37.2 Scaune
Se consider ns scaune numerotate de la 1 la ns, aranjate în cerc.
CAPITOLUL 37. ONI 2003 799
Exemplu
scaune.in scaune.out
20 5 6 16
6 19 3
19 17 0
17 13 20
13 11
1
1
3
20
16
Timp maxim de execuµie: 1 secund /test
Deoarece limita pentru num rul de scaune este destul de mic , avansarea copiilor se poate
realiza pas cu pas; astfel, în momentul în care un scaun se elibereaz , ecare copil avanseaz câte
o poziµie pân când unul dintre ei ajunge în dreptul scaunului ³i îl ocup .
O metod mai rapid const în calcularea, pentru ecare copil, a num rului de mut ri pân
la ajungerea la scaunul liber.
Fie un copil situat în poziµia C , iar scaunul liber în poziµia S ; atunci copilul va avansa S C
poziµii, dac C S , respectiv N S S C poziµii, dac C % S .
Astfel, la ecare ridicare a unui copil se poate aa cel mai apropiat copil, se calculeaz câte
poziµii se va deplasa acesta (s spunem P ), apoi toµi copiii vor avansa P poziµii. Un copil care
avanseaz P poziµii din poziµia C va ajunge în poziµia C P (dac C P N S ), respectiv
C P N S (dac C P % N S ).
Analiza complexit µii
Deoarece sunt N C copii în a³teptare, vor analizate cel mult N C ridic ri de pe scaun, indi-
ferent dac mai urmeaz ceva în ³ierul de intrare.
Dac sunt mai puµin de N C copii care se ridic , atunci o parte dintre cei care a³teapt vor
r mâne în picioare.
La ecare moment în care se ridic un copil, avansarea pas cu pas a copiilor aaµi în a³teptare
pân la a³zarea pe scaun a unuia dintre ei nu poate necesita mai mult de N S pa³i; ecare pas
necesit avansarea tuturor copiilor, deci a cel mult N C copii.
Complexitatea ocup rii unui scaun prin avansare pas cu pas este deci O N S N C .
În cazul metodei mai rapide, calcularea distanµei pentru toµi copiii pân la scaunul liber are
complexitatea O N C . Aceea³i complexitate au ³i operaµiile de alegere a minimului P dintre
aceste distanµe, respectiv de avansare a tuturor copiilor cu P poziµii.
Ordinul de complexitate al algoritmului de rezolvare a acestei probleme este O N C N S N C
pentru prima variant , respectiv O N C N C pentru cea de-a doua.
12 long t1,t2;
13 t1=System.currentTimeMillis();
14 PrintWriter out = new PrintWriter(
15 new BufferedWriter(new FileWriter("scaune.out")));
16 StreamTokenizer st=new StreamTokenizer(
17 new BufferedReader(new FileReader("scaune.in")));
18 st.nextToken(); ns=(int)st.nval;
19 st.nextToken(); nc=(int)st.nval;
20 asezat=new boolean[nc+1];
21 pozInitiala=new int[nc+1];
22 pozFinala=new int[nc+1];
23
24 for(k=1;k<=nc;k++)
25 {
26 st.nextToken();
27 pozInitiala[k]=pozFinala[k]=(int)st.nval;
28 }
29 while(st.nextToken()!=st.TT_EOF)
30 {
31 k=(int)st.nval; // scaunul k este liber
32 i=esteLaPozitia(k);
33 while((nca<nc)&&(i==0)) { misca(); i=esteLaPozitia(k); }
34 pozFinala[i]=k;
35 asezat[i]=true;
36 nca++;
37 }
38
39 for(j=1;j<=nc;j++)
40 if(asezat[j]) out.println(pozInitiala[j]+" "+pozFinala[j]);
41 else out.println(pozInitiala[j]+" "+0);
42 out.close();
43 t2=System.currentTimeMillis();
44 System.out.println("Timp = "+(t2-t1));
45 }//main
46
47 static void misca()
48 {
49 int i;
50 for(i=1;i<=nc;i++)
51 if(!asezat[i])
52 {
53 pozFinala[i]++;
54 if(pozFinala[i]==ns+1) pozFinala[i]=1;
55 }
56 }
57
58 static int esteLaPozitia(int k)
59 {
60 int i,copil=0;
61 for(i=1;i<=nc;i++)
62 if(!asezat[i]&&(pozFinala[i]==k)) { copil=i; break; }
63 return copil;
64 }
65 }//class
Pentru a doua varianta se calculeaz distanµele pân la scaunul liber pentru ecare copil r mas
nea³ezat.
37.3 Circular
Unele numere naturale sunt formate doar din cifre distincte nenule.
Dintre acestea, unele, numite numere circulare, au urm toarea proprietate: pornind de la
prima cifr ³i num rând spre dreapta, dup cifr , atâtea cifre cât indic aceasta, se determin o
nou cifr . Procedând la fel ³i pentru aceasta ³i pentru toate cele care urmeaz se va ajunge din
nou la prima cifr .
Dac toate cifrele au fost vizitate exact o dat , num rul se nume³te circular.
De exemplu num rul
1894256
este num r circular deoarece:
a are numai cifre distincte
a nu conµine cifra 0
a pornind de la 1 obµinem, pe rând: 8, 9, 2, 6, 5, 4, 1
Cerinµ
CAPITOLUL 37. ONI 2003 804
Scrieµi un program care, pentru un N dat, determin câte numere circulare sunt mai mici sau
egale cu N, precum ³i cel mai mare num r circular mai mic sau egal cu N.
Date de intrare
Pe prima linie a ³ierului de intrare circular.in se a num rul natural N.
Date de ie³ire
Fi³ierul de ie³ire circular.out conµine o singur linie, pe care se a num rul de numere
circulare mai mici ca N precum ³i num rul circular maxim cerut, separate printr-un spaµiu.
Dac nu exist nici un num r circular mai mic ca N, în ³ierul de ie³ire se vor a³a dou valori
0 separate printr-un spaµiu.
Restricµii
10 & N $ 10.000.000
Exemplu
circular.in circular.out Semnicaµie
1894250 347 1849625 Exist 347 numere circulare mai mici dacât
1894250 cel mai mare dintre acestea ind
num rul 1849625
Timp de execuµie: 1 sec/test
71 }
72 // N++;
73 }
74 }
75 fclose(g);
76 return 0;
77 }
66 if (k==n+1)
67 prelucreaza();
68 else
69 for (i=1; i<=9; i++)
70 if (!uz[i])
71 {
72 uz[i]=1;
73 x[k]=i;
74 back(k+1);
75 uz[i]=0;
76 }
77 }
78
79 int main(void)
80 {
81 f=fopen("circular.in", "rt");
82 g=fopen("circular.out", "wt");
83 fscanf(f, "%U", &N); fclose(f);
84 nn=N;
85 nc=0;
86 while (nn) //determin numarul de cifre
87 {
88 nc++;
89 nn/=10;
90 }
91
92 nn=N;
93 for (i=nc; i>=1; i--) //pun cifrele in vector corect
94 { //Obs. daca un numar este circular
95 c[i]=nn%10; // nu rezulta ca inversul este
96 nn/=10; // si el circular
97 }
98 nc1=nc;
99 c1=c[1]; gata=0;
100 contor=0;
101 for (n=2; n<nc1; n++) back(1);
102 gata=1;
103 for (cifra=1; cifra<=c1; cifra++)
104 {
105 x[1]=cifra;
106 uz[cifra]=1;
107 back(2);
108 uz[cifra]=0;
109 }
110
111 fprintf(g, "%ld %ld\n", contor, NCircM);
112 fclose(g);
113
114 return 0;
115 }
23 {
24 k=1;
25 while (k<=c[i])
26 {
27 j++;
28 k++;
29 }
30 if (j%nc==0) //sunt chiar pe ultima cifra
31 k=nc;
32 else
33 k=j%nc; //sunt pe o cifra distincta de ultima
34 vc[k]++; //marchez in vectorul caracteristic
35 if (vc[k]>1) CORECT=0; //am ajuns aici a doua oara
36 i=k; //noua cifra
37 }
38 for (i=2; i<=nc; i++) //am "trecut" prin toate cifrele? sau
39 if ((!vc[i])||(vc[i]>1))//ciclul s-a incheiat la alta cifra decat prima?
40 return 0;
41 return 1; //este OK!!!
42 }
43
44 int main()
45 {
46 f=fopen("circular.in", "rt");
47 fscanf(f, "%U", &N); fclose(f);
48 CircM=0;
49 while (N>10)
50 {
51 nn=N;
52 nc=0;
53 while (nn) //determin numarul de cifre
54 {
55 nc++;
56 nn/=10;
57 }
58 nn=N;
59 for (i=nc; i>=1; i--) //pun cifrele in vector corect
60 { //Obs. daca un numar este circular
61 c[i]=nn%10; // nu rezulta ca inversul este
62 nn/=10; // si el circular
63 }
64 if (CIRC())
65 {
66 contor++;
67 if (N>CircM) CircM=N;
68 }
69 N--;
70 }
71 g=fopen("circular.out", "wt");
72 fprintf(g, "%ld %ld\n", contor, CircM);
73 fclose(g);
74 return 0;
75 }
14 t1=System.currentTimeMillis();
15 PrintWriter out = new PrintWriter(
16 new BufferedWriter(new FileWriter("circular.out")));
17 StreamTokenizer st=new StreamTokenizer(
18 new BufferedReader(new FileReader("circular.in")));
19 st.nextToken(); n=(int)st.nval;
20
21 for(k=12;k<=n;k++)
22 if(esteCircular(k)) { nnc++; ncmax=k; }
23
24 out.println(nnc+" "+ncmax);
25 out.close();
26 t2=System.currentTimeMillis();
27 System.out.println("Timp = "+(t2-t1));
28 }//main
29
30 static boolean esteCircular(int k)
31 {
32 int i,j;
33 int c; // cifra
34 nc=0;
35 for(i=0;i<=9;i++) fc[i]=0;
36 while(k!=0) {c=k%10; a[nc]=c; fc[c]++; k=k/10; nc++;}
37 if(fc[0]>0) return false;
38 for(i=1;i<=9;i++) if(fc[i]>1) return false;
39 for(i=0;i<nc/2;i++) {c=a[i]; a[i]=a[nc-1-i]; a[nc-1-i]=c;}
40 for(i=0;i<nc;i++) aa[i]=a[i];
41
42 j=0;
43 for(i=1;i<=nc;i++)
44 if(aa[j]==0) return false; else { aa[j]=0; j=(j+a[j])%nc; }
45 if(j==0) return true; else return false;
46 }
47 }//class
39 if(k>0)
40 for(j=0;j<k;j++) if(i==x[j]) {ok=false; break;}
41
42 if(!ok) continue;
43 x[k]=i;
44 if(k<nc-1) f(k+1); else afisv();
45 }
46 }
47
48 static void afisv()
49 {
50 if(!esteCircular(x)) return;
51 if(numar(x)>n) return;
52 nnc++;
53 ncmax=numar(x);
54 //System.out.print(nnc+" : ");
55 //for(int i=0; i<=nc-1; i++) System.out.print(x[i]);
56 //System.out.println();
57 }
58
59 static int numar(int[] x)
60 {
61 int nx=x[0];
62 for(int i=1;i<=nc-1;i++) nx=nx*10+x[i];
63 return nx;
64 }
65
66 static boolean esteCircular(int[] x)
67 {
68 int i,j;
69 for(i=0;i<nc;i++) a[i]=aa[i]=x[i];
70
71 j=0;
72 for(i=1;i<=nc;i++)
73 if(aa[j]==0) return false; else { aa[j]=0; j=(j+a[j])%nc; }
74 if(j==0) return true; else return false;
75 }
76 }
37.4 Criptare
Mircea ³i Vasilic vor s -³i trimit mesaje pe care alµii s nu le înµeleag . Au citit ei despre
spioni ³i modalit µi de a scrie mesaje ³i, în nal, au imaginat un mod de criptare a unui mesaj
care folose³te "cuvânt cheie" (le-a pl cut lor denumirea asta :-) ).
Alegându-³i un cuvânt cheie format numai din litere distincte, ei num r literele acestuia ³i
împart mesajul în grupe de lungime egal cu num rul de litere ale cuvântului cheie, ³i le a³eaz
una sub alta. Desigur, se poate întâmpla ca ultima grup s e incomplet , a³a c o completeaz
cu spaµii.
Apoi numeroteaz literele cuvântului cheie în ordinea apariµiei lor în alfabetul englez.
În nal, rescriu mesajul astfel: coloana de sub litera numerotat cu 1, urmat de coloana de
sub litera numerotat cu 2, etc. înlocuind totodat ³i spaµiile cu caracterul '*' (asterisc).
Exemplu:
cuvântul cheie: criptam
mesaj de criptat: Incercam sa lucram cu coduri si criptari.
cuvântul cheie criptam are 7 litere
numerotare: 2635714
deoarece, avem, în ordine
a b c defgh i jkl m no p q r s t uvwxzy
1 2 3 4 5 6 7
împ rµire în grupe: Incerca¶m sa lu¶cram cu¶ coduri¶ si cri¶ptari.
codicare:
CAPITOLUL 37. ONI 2003 811
2 6 3 5 7 1 4
I n c e r c a
m * s a * l u
c r a m * c u
* c o d u r i
* s i * c r i
p t a r i . *
mesaj criptat: clcrr.Imc**pcsaoiaauuii*eamd*rn*rcstr**uci
clcrr. Imc**p csaoia auuii* eamd*r n*rcst r**uci
col1 col2 col3 col4 col5 col6 col7
Cerinµ
Fiind date un cuvânt cheie ³i un mesaj criptat, decodicaµi mesajul trimis de Mircea pentru
Vasilic .
Date de intrare
Fi³ierul de intrare criptare.in conµine pe prima linie mesajul criptat iar pe linia a doua
cuvântul cheie.
Date de ie³ire
Fi³ierul de intrare criptare.out conµine pe prima linie mesajul decriptat.
Restricµii
a lungimea mesajului este de minim 20 ³i maxim 1000 caractere
a cuvântul cheie are minim 5 ³i maxim 20 de caractere
a cuvântul cheie conµine numai litere mici ale alfabetului
Exemplu
criptare.in
clcrr.Imc**pcsaoiaauuii*eamd*rn*rcstr**uci
criptam
criptare.out
Incercam sa lucram cu coduri si criptari.
Timp maxim de execuµie: 1 secund /test
10 String cheia=br.readLine();
11 br.close();
12
13 System.out.println("mesajul este: "+mesaj+" "+mesaj.length());
14 System.out.println("cheia este: "+cheia+" "+cheia.length());
15
16 int m=mesaj.length()/cheia.length(); // nr linii matrice
17 int n=cheia.length(); // nr coloane matrice
18
19 int[] p=new int[n];
20 // sortare prin numarare
21 for(j=1; j<=n-1; j++)
22 for(i=0;i<=j-1;i++)
23 if(cheia.charAt(i)<cheia.charAt(j)) ++p[j]; else ++p[i];
24 afisv(p);
25 int[] pp=new int[n]; // permutarea inversa
26 for(i=0;i<n;i++) pp[p[i]]=i;
27 afisv(pp);
28
29 char a[][]=new char[m][n];
30
31 k=0;
32 for(j=0;j<n;j++)
33 for(i=0;i<m;i++)
34 {
35 a[i][pp[j]]=mesaj.charAt(k);
36 k++;
37 }
38
39 System.out.println("Matricea a[][] este:");
40 for(i=0;i<m;i++)
41 {
42 for(j=0;j<n;j++) System.out.print(a[i][j]+" ");
43 System.out.println();
44 }
45
46 for(i=0;i<m;i++)
47 for(j=0;j<n;j++)
48 if(a[i][j]!=’*’) System.out.print(a[i][j]);
49 else System.out.print(" ");
50 System.out.println();
51 }//main
52
53 static void afisv(int[] x)
54 {
55 int n=x.length, i;
56 for(i=0;i<n;i++) System.out.print(x[i]+" ");
57 System.out.println();
58 }
59 }//class:
37.5 Ma³ina
O µar are 3 & N & 30000 ora³e, numerotate de la 1 la N , dispuse pe un cerc.
PAM tocmai ³i-a luat carnet de conducere ³i vrea s viziteze toate ora³ele µ rii. Lui PAM îi
este fric s conduc prin locuri aglomerate a³a c ea ³i-a propus s mearg numai pe ³oselele
unde tracul este mai redus.
Exist ³osele de leg tur între oricare dou ora³e al turate: între ora³ul 1 ³i ora³ul 2, ... , între
ora³ul i ³i ora³ul i 1, iar ora³ul N este legat de ora³ulul 1.
Ca s nu se r t ceasc , PAM ³i-a propus s -³i aleag un ora³ de început ³i s mearg pe ³oselele
respective în sens trigonometric pân ajunge înapoi în ora³ul de unde a plecat. Dac PAM pleac
din ora³ul K , atunci traseul ei va : K, K 1, ..., N, 1, 2, ..., K .
Ma³ina lui PAM are un rezervor foarte mare (în care poate pune oricât de mult benzin ). În
ecare ora³, PAM ia toat cantitatea de benzin existent în ora³, iar parcurgerea ec rei ³osele
necesit o anumit cantitate de benzin .
Cerinµ
tiind c PAM are, la începutul c l toriei, doar benzina existent în ora³ul de plecare, ³i c ,
atunci când ajunge într-un ora³, ea va lua toat cantitatea de benzin disponibil în acel ora³, s
se g seasc un ora³ din care PAM î³i poate începe excursia astfel încât s nu r mân f r benzin .
Se consider c PAM a r mas f r benzin dac în momentul plec rii dintr-un ora³, nu are
sucient benzin pentru a parcurge ³oseaua care duce la ora³ul urm tor. Dac benzina îi ajunge
la x (adic la plecare are tot atâta benzin cât îi trebuie) se consider c PAM poate ajunge
pân în ora³ul urm tor.
Date de intrare
Fi³ierul de intrare masina.in conµine
a pe prima linie num rul N ,
a pe cea de-a doua linie se g sesc N numere naturale a1, a2, ..., aN , separate prin câte
un spaµiu, unde ai reprezint cantitatea de benzin disponibil în ora³ul i.
a linia a treia conµine un ³ir de N numere naturale b1, b2, ..., bN , separate prin câte un
spaµiu, unde bi reprezint cantitatea de benzin necesar str baterii ³oselei dintre ora³ele i ³i
i 1 (sau N ³i 1, dac i N ).
Date de ie³ire
Fi³ierul de ie³ire masina.out va conµine un singur num r s care reprezint un ora³ din care,
dac PAM î³i începe c l toria, poate completa turul µ rii f r a face pana prostului.
Restricµii ³i preciz ri
a Dac exist mai multe soluµii, se cere una singur .
a 0 & ai & 30000
a 1 & bi & 30000
Exemplu
CAPITOLUL 37. ONI 2003 815
masina.in masina.out
6 4
0 3 2 5 10 5
783214
Timp maxim de execuµie: 0.3 sec/test
37.6 Operaµii
k
Not m cu c ³i r câtul ³i respectiv restul împ rµirii unui numar nr la 2 , unde k este un num r
natural nenul.
Asupra num rului putem efectua succesiv urm toarele operaµii:
k
a O1 nr, k reprezint transformarea num rului nr în num rul 2 2c 1 r pentru orice rest
r, sau
c r doar dac r $ 2k 1.
k1
a O2 nr, k reprezint transformarea num rului nr în num rul 2
Cerinµ
Se dau m ³i n dou numere naturale nenule.
Efectuaµi asupra numerelor m ³i n operaµii succesive, O1 sau O2, pentru valori alese ale lui k ,
astfel încât dup un num r nit de operaµii cele dou numere s devin egale, iar valoarea astfel
obµinut s e minim .
Date de intrare
Fi³ierul de intrare operatii.out conµine pe o linie m n dou numere naturale nenule, separate
printr-un spaµiu, reprezentând cele dou numere date.
Date de ie³ire
Fi³ierul de ie³ire operatii.out conµine pe cele i j 3 linii urm toarele:
a nmin num rul natural nenul nmin, reprezentând valoarea minim obµinut din m ³i n
prin aplicarea unor succesiuni de operaµii O1 sau O2,
a i num rul operaµiilor efectuate asupra primului num r m, pe a doua linie
a op1 k1 pe urm toarele i linii: perechi de numere
a ... reprezentând operaµia (1 sau 2) ³i respectiv valoarea lui k
a opi ki pentru operaµia respectiv , separate printr-un spaµiu.
a j num rul operaµiilor efectuate asupra celui de al doilea num r n, pe linia i+2
a op1 k1 pe urm toarele j linii: perechi de numere
a ... reprezentând operaµia (1 sau 2) ³i respectiv valoarea lui k
a opj kj pentru operaµia respectiv , separate printr-un spaµiu
Restricµii
1 $ m, n & 2.000.000.000
Exemplu
OPERATII.IN OPERATII.OUT
11 45 15
2
23
12
2
22
24
CAPITOLUL 37. ONI 2003 817
34
35 if(nc1a<nc1b) nc1sol=nc1b; else nc1sol=nc1a;
36 nminsol=1;
37 for(k=1;k<=nc1sol;k++) nminsol=nminsol*2;
38 nminsol=nminsol-1;
39 out.println(nminsol);
40
41 out.println(nc1sol-nc1a+nc0a);
42 j=0;
43 for(k=1;k<=nc0a;k++)
44 {
45 while(a[j]!=0) j++;
46 out.println(2+" "+(j-k+2)); // sterg 0 de pe pozitia j
47 j++;
48 }
49 for(k=nc1a;k<nc1sol;k++) out.println("1 1");
50
51 out.println(nc1sol-nc1b+nc0b);
52 j=0;
53 for(k=1;k<=nc0b;k++)
54 {
55 while(b[j]!=0) j++;
56 out.println(2+" "+(j-k+2)); // sterg 0 de pe pozitia j
57 j++;
58 }
59 for(k=nc1b;k<nc1sol;k++) out.println("1 1");
60
61 out.close();
62 }//main
63 }//class
Capitolul 38
ONI 2002
38.1 Pentagon
lect. univ. Ovidiu Dom³a, Alba Iulia
În urma bombardamentelor din 11 septembrie 2001, cl direa Pentagonului a suferit daune
la unul din pereµii cl dirii. Imaginea codicat a peretelui avariat se reprezint sub forma unei
matrice cu m linii ³i n coloane, ca în gura de mai jos:
1110000111 unde 1 reprezint zid intact
1100001111 0 zid avariat
1000000011
1111101111
1110000111
Sumele alocate de Bin Laden pentru refacerea Pentagonului vor donate celor care vor ajuta
americanii s refac aceast cl dire prin plasarea, pe vertical , a unor blocuri de în lµimi k ,
k 1, ..., m, ³i l µime 1, în locurile avariate.
Cerinµ :
Pentru o structur dat a unui perete din cl direa Pentagonului, determinaµi num rul minim
al blocurilor, de în lµimi k 1, k 2, ..., k m, necesare refacerii cl dirii.
Date de intrare:
Fi³ierul de intrare PENTAGON.IN conµine pe prima linie dimensiunile m ³i n ale peretelui
cl dirii, iar pe urm toarele m linii câte o secvenµ de caractere 1 sau 0 de lungime n.
Date de ie³ire:
Fi³ierul PENTAGON.OUT va conµine pe câte o linie, ordonate cresc tor dup k , secvenµe:
k nr
unde k este înalµimea blocului,
iar nr este num rul de blocuri de în lµime k , separate prin câte un spaµiu.
Restricµii ³i preciz ri
a 1 & m, n & 200
a nu se vor a³a blocurile de în lµime k , a c ror num r este zero (0).
819
CAPITOLUL 38. ONI 2002 820
Exemplu
PENTAGON.IN PENTAGON.OUT
5 10 17
1110000111 21
1100001111 32
1000000011 51
1111101111
1110000111
Timp maxim de execuµie: 1 secund /test
8 var i,j:byte;
9 cod:boolean;
10 nr:byte;
11 begin
12 for j:=1 to n do
13 begin
14 nr:=0;
15 cod:=c[1,j]=’1’;
16 for i:=1 to m do
17 if c[i,j]=’1’ then
18 begin
19 if not cod then
20 begin
21 cod:=true;
22 inc(s[nr]);
23 nr:=0;
24 end
25 end
26 else
27 begin
28 if cod then
29 begin
30 nr:=1;
31 cod:=false;
32 end
33 else
34 inc(nr);
35 end;
36 if not cod then
37 begin
38 cod:=true;
39 inc(s[nr]);
40 end
41 end;
42 end;
43
44 begin
45 assign(f,’pentagon.in’);
46 reset(f);
47 readln(f,m,n);
48 for i:=1 to m do
49 readln(f,c[i]);
50 close(f);
51 numara;
52 assign(f,’pentagon.out’);
53 rewrite(f);
54 for i:=1 to m do
55 if s[i]<>0 then
56 writeln(f,i,’ ’,s[i]);
57 close(f);
58 end.
19
20 br.readLine(); // altfel nu merge !!!
21
22 for(i=0;i<m;i++) a[i]=br.readLine();
23
24 for(j=0;j<n;j++)
25 {
26 i=0;
27 while(i<m)
28 {
29 while((i<m)&&(a[i].charAt(j)==’1’)) i++;
30 k=0;
31 while((i<m)&&(a[i].charAt(j)==’0’)) {k++; i++;}
32 f[k]++;
33 }
34 }
35
36 PrintWriter out=new PrintWriter(
37 new BufferedWriter(new FileWriter("pentagon.out")));
38 for(k=1;k<=n;k++) if(f[k]>0) out.println(k+" "+f[k]);
39 out.close();
40 }
41 }
38.2 Pod
prof. Marinel erban, Ia³i
Între dou maluri ale unei v i adânci s-a construit un pod suspendat format din N buc µi
de scândur , legate cu liane.
Vom considera c scândurile sunt numerotate de la 1 la N , începând de pe malul pe care ne
a m.
În timp unele buc µi de scândur s-au deteriorat, iar altele chiar au disp rut.
Pentru traversarea podului se ³tie c :
se pot face pa³i doar de lungime 1, 2 sau 3;
scândurile deteriorate sunt nesigure, deci pe ele ³i de pe ele se pot face doar pa³i de lungime
1.
evident, nu se poate p ³i pe o scândur care lipse³te.
Cerinµ :
Scrieµi un program care s determine num rul de modalit µi de traversare a podului (mai exact,
de a ajunge pe cel lalt mal), precum ³i o soluµie de traversare, dac o astfel de soluµie exist .
Date de intrare:
Fi³ierul de intrare POD.IN are structura:
POD.IN Semnicaµie
N Num rul total de scânduri
k s1 s2 ... sk Num rul de scânduri lips ³i numerele lor de ordine
h d1 d2 ... dh Num rul de scânduri deteriorate ³i numerele lor de ordine
Date de ie³ire:
Fi³ierul de ie³ire POD.OUT va conµine pe prima linie valoarea -1 dac nu este posibil s
travers m podul, respectiv num rul de posibilit µi de a traversa podul, dac aceasta este posibil.
În cazul în care exist soluµii, pe cea de a doua linie va a³at o astfel de soluµie, prin
indicarea, în ordine, a scândurilor pe care se p ³e³te, sub forma:
POD.OUT Semnicaµie
Nr Num rul total de posibilit µi
p1 p2 ... pm Soluµia determinat , prin indicarea în ordine a scândurilor
pe care se p ³e³te
Restricµii ³i preciz ri:
a 3 & N & 300
a 0 & k, h & N
a rs1 , s2 , ..., sk x N r2, ...N x,
a rd1 , d2 , ..., dh x N r1, 2, ...N x;
a rs1 , s2 , ..., sk x = rd1 , d2 , ..., dh x o
CAPITOLUL 38. ONI 2002 823
8
9 int n, uz[NMax], s[NMax], poz[NMax];
10 long Nr[NMax];
11
12 void Afisare();
13 void Rezolva();
14 void Citire();
15
16 int main()
17 {
18 Citire();
19 Rezolva();
20 Afisare();
21 return 0;
22 }
23
24 void Afisare()
25 {
26 long Total=0;
27 int d[NMax], final, lg;
28 if (!s[n]) {Total+=Nr[n]; final=n;}
29 if (Nr[n-1]!=-1 && !uz[n-1]) {Total+=Nr[n-1]; final=n-1;}
30 if (Nr[n-2]!=-1 && !uz[n-2]) {Total+=Nr[n-2]; final=n-2;}
31 if (!Total) Total=-1;
32 ofstream fout(nfout);
33 fout<<Total<<endl;
34 if (Total!=-1)
35 {d[0]=final; lg=1;
36 while (poz[final]!=0) {d[lg++]=poz[final]; final=poz[final];}
37 for (final=lg-1; final>=0; final--)
38 fout<<d[final]<<’ ’;
39 fout<<endl;
40 }
41 fout.close();
42 }
43
44 void Citire()
45 {
46 ifstream f(nfin);
47 int x, k, h, i;
48 f>>n>>k;
49 for(int i=0;i<k;i++) {f>>x; s[x]=1;}
50 //s[x]=1 daca scandura x lipseste si 0 altfel
51 f>>h;
52 for(i=0;i<h;i++) {f>>x; uz[x]=1;}
53 //uz[x]=1 daca scandura x este deteriorata si 0 altfel
54 f.close();
55 }
56
57 void Rezolva()
58 {
59 Nr[1]=1; poz[1]=0;
60 if (s[2]) Nr[2]=-1;
61 else {Nr[2]=2; poz[2]=0;}
62 if (s[3]) Nr[3]=-1;
63 else
64 if (s[2]) {Nr[3]=2; poz[3]=0;}
65 else {Nr[3]=4; poz[3]=0;}
66 for (int i=4; i<=n; i++)
67 if (s[i]) Nr[i]=-1;
68 else
69 if (uz[i]) { Nr[i]=Nr[i-1]; poz[i]=i-1;}
70 else
71 {Nr[i]=0;
72 if (Nr[i-1]!=-1) {Nr[i]=Nr[i-1];poz[i]=i-1;}
73 if (Nr[i-2]!=-1 && !uz[i-2]) {Nr[i]+=Nr[i-2];poz[i]=i-2;}
74 if (Nr[i-3]!=-1 && !uz[i-3]) {Nr[i]+=Nr[i-3];poz[i]=i-3;}
75 if (!Nr[i]) Nr[i]=-1;}
76 }
1 import java.io.*;
2 class Pod1
3 {
4 static final int buna=0, deteriorata=1, lipsa=2;
5 static int ns, nsl,nsd;
6 static int nsol;
7 static int[] x;
8 static int[] y;
9 static int[] p;
10
11 public static void main(String[] args) throws IOException
12 {
13 int i,j;
14 StreamTokenizer st=new StreamTokenizer(new BufferedReader(
15 new FileReader("pod.in")));
16 PrintWriter out=new PrintWriter(new BufferedWriter(
17 new FileWriter("pod.out")));
18
19 st.nextToken(); ns=(int)st.nval;
20 x=new int[ns+2];
21 y=new int[ns+2]; // nsol[i] ajunge in i
22 p=new int[ns+2]; // predecesor
23
24 st.nextToken();nsl=(int)st.nval; // lipsa
25 for(i=1;i<=nsl;i++)
26 {
27 st.nextToken(); j=(int)st.nval;
28 x[j]=lipsa;
29 }
30
31 st.nextToken();nsd=(int)st.nval; // deteriorate
32 for(i=1;i<=nsd;i++)
33 {
34 st.nextToken(); j=(int)st.nval;
35 x[j]=deteriorata;
36 }
37 afisv(x); System.out.println();
38
39 y[1]=0;
40 if(x[1]!=lipsa) y[1]+=1; // 1 pas de pe mal
41 afisv(y);
42
43 y[2]=0;
44 if(x[2]==deteriorata) y[2]+=y[1]; // 1 pas din 1
45 else if(x[2]==buna) y[2]+=y[1]+1; // 1 pas din 1 si 2 pasi de pe mal
46 if(y[2]>0) if(y[1]>0) p[2]=1;
47 else p[2]=0;
48 afisv(y);
49
50 y[3]=0;
51 if(x[3]==deteriorata)
52 {
53 if(x[2]!=lipsa) y[3]=y[2]+1; // 1 pas din 2
54 if(x[1]==buna) y[3]=y[3]+1; // 2 pasi din 1
55 }
56 else if(x[3]==buna)
57 {
58 y[3]+=1; // 3 pasi de pe mal;
59 if(x[1]==buna) y[3]+=y[1]; // 2 pasi din 1
60 if(x[2]!=lipsa) y[3]+=y[2]; // 1 pas din 2
61 }
62 afisv(y); System.out.println();
63
64 for(i=4;i<=ns+1;i++)
65 {
66 switch(x[i])
67 {
68 case lipsa:
69 y[i]=0; break;
70 case deteriorata:
71 if(x[i-1]!=lipsa) y[i]=y[i-1]; // 1 pas din i-1
72 break;
73 case buna:
74 y[i]=0; // pentru suma
75 if(x[i-3]==buna) y[i]+=y[i-3]; // 3 pasi din i-3
CAPITOLUL 38. ONI 2002 829
26 for(i=1;i<=nsl;i++)
27 {
28 st.nextToken(); j=(int)st.nval;
29 x[j]=lipsa;
30 }
31
32 st.nextToken();nsd=(int)st.nval; // deteriorate
33 for(i=1;i<=nsd;i++)
34 {
35 st.nextToken(); j=(int)st.nval;
36 x[j]=deteriorata;
37 }
38
39 if(x[1]!=lipsa) y[1]=nrv(1); // 1 pas de pe mal
40
41 y[2]=nrv(0);
42 if(x[2]==deteriorata) y[2]=suma(y[2],y[1]); // 1 pas din 1
43 else if(x[2]==buna)
44 y[2]=suma(y[2],suma(y[1],nrv(1)));
45 if(ok(y[1])) p[2]=1;
46
47 y[3]=nrv(0);
48 if(x[3]==deteriorata)
49 {
50 if(x[2]!=lipsa) y[3]=suma(y[2],nrv(1)); // 1 pas din 2
51 if(x[1]==buna) y[3]=suma(y[3],nrv(1)); // 2 pasi din 1
52 }
53 else if(x[3]==buna)
54 {
55 y[3]=suma(y[3],nrv(1)); // 3 pasi de pe mal;
56 if(x[1]==buna) y[3]=suma(y[3],y[1]); // 2 pasi din 1
57 if(x[2]!=lipsa) y[3]=suma(y[3],y[2]); // 1 pas din 2
58 }
59
60 if(ok(y[1])) p[3]=1;
61 else if(ok(y[2])) p[3]=2;
62
63 for(i=4;i<=ns+1;i++)
64 {
65 switch(x[i])
66 {
67 case lipsa:
68 y[i]=nrv(0); break;
69 case deteriorata:
70 if(x[i-1]!=lipsa) y[i]=suma(nrv(0),y[i-1]);// 1 pas din i-1
71 if(ok(y[i-1])) p[i]=i-1;
72 break;
73 case buna:
74 y[i]=nrv(0); // pentru
suma
75 if(x[i-3]==buna) y[i]=suma(y[i],y[i-3]); // 3 pasi din i-3
76 if(x[i-2]==buna) y[i]=suma(y[i],y[i-2]); // 2 pasi din i-2
77 if(x[i-1]!=lipsa) y[i]=suma(y[i],y[i-1]); // 1 pas din i-1
78 if(ok(y[i-3])) p[i]=i-3;
79 else if(ok(y[i-2])) p[i]=i-2;
80 else if(ok(y[i-1])) p[i]=i-1;
81 }
82 }
83 afisv(y[ns+1]);
84 drum(ns+1);
85 out.println();
86 out.close();
87 }// main
88
89 static boolean ok(int[] z)
90 {
91 int i;
92 for(i=0;i<z.length;i++) if(z[i]!=0) return true;
93 return false;
94 }
95
96 static void drum(int j)
97 {
98 if(p[j]!=0) drum(p[j]);
99 out.print(j+" ");
100 }
CAPITOLUL 38. ONI 2002 832
101
102 static void afisv(int[] x)
103 {
104 int nx=x.length;
105 int i;
106 for(i=nx-1;i>=0;i--) out.print(x[i]);
107 out.println();
108 }
109
110 static int[] nrv(int nr)
111 {
112 int nc;
113 int nrrez=nr;
114 nc=0;
115 while(nr!=0) {nc++; nr=nr/10;}
116 int[] x=new int[nc];
117 nr=nrrez;
118 nc=0;
119 while(nr!=0) { x[nc]=nr%10; nc++; nr=nr/10; }
120 return x;
121 }
122
123 static int[] suma(int[] x,int[] y)
124 {
125 int k,s,t;
126 int nx=x.length;
127 int ny=y.length;
128 int nz;
129 if(nx>ny)nz=nx+1; else nz=ny+1;
130 int[] z=new int[nz];
131 t=0;
132 for(k=0;k<nz;k++)
133 {
134 s=t;
135 if(k<nx) s=s+x[k];
136 if(k<ny) s=s+y[k];
137 z[k]=s%10;
138 t=s/10;
139 }
140 if(z[nz-1]!=0)return z;
141 else
142 {
143 int[] zz=new int[nz-1];
144 for(k=0;k<nz-1;k++) zz[k]=z[k];
145 return zz;
146 }
147 }
148 }// class
38.3 Suma
Florin Gheµu, Bucure³ti
Fie ³irul tuturor numerelor naturale de la 1 la un num r oarecare N .
Considerând asociate câte un semn (+ sau -) ec rui num r ³i adunând toate aceste numere
cu semn se obµine o sum S .
Problema const în a determina pentru o sum dat S , num rul minim N pentru care, printr-o
asociere de semne tuturor numerelor de la 1 la N , se poate obµine S .
Cerinµ :
Pentru un S dat, g siµi valoarea minim N ³i asocierea de semne numerelor de la 1 la N pentru
a obµine S în condiµiile problemei.
Restricµii:
a 0$S & 100.000.
Date de intrare
În ³ierul SUMA.IN se va aa pe prima linie un întreg pozitiv S reprezentând suma ce trebuie
obµinut .
Date de ie³ire
CAPITOLUL 38. ONI 2002 833
În ³ierul SUMA.OUT se va scrie, pe prima linie num rul minim N pentru care se poate obµine
suma S iar pe urm toarele linii, pân la sfâr³itul ³ierului, numerele care au semn negativ, câte
unul pe linie.
Ordinea de a³are a numerelor nu are importanµ .
Celelalte numere care nu apar în ³ier se consider pozitive.
Dac exist mai multe soluµii se cere doar una.
Exemplu:
SUMA.IN SUMA.OUT
12 7
1
7
Deci suma 12 se poate obµine din minimum 7 termeni astfel:
12 1 2 3 4 5 6 7.
Nu este singura posibilitate de asociere de semne termenilor de la 1 la 7.
Timpul de execuµie: 1 secund /test
Analiza complexit µii
Valoarea N poate obµinut folosind o simpl formul matematic , deci ordinul de complexi-
tate al acestei operaµii este O 1.
Valorile SN , SN 1 , SN 2 , DN , DN 1 , DN 2 sunt calculate tot cu ajutorul unor formule ma-
tematice simple, a³adar ordinul de complexitate al operaµiei de determinare a acestora este tot
O 1.
¬
Identicarea valorii N se face pe baza veric rii parit µii a cel mult trei numere, deci ³i aceast
operaµie are ordinul de complexitate O 1.
Determinarea valorii x ³i a celor cel mult dou numere c rora li se va modica semnul este
realizat tot pe baza unor calcule simple al c ror ordin de complexitate este O 1.
În concluzie, ordinul de complexitate al unui algoritm ecient de rezolvare a acestei probleme
este O 1 O 1 O 1 O 1 O 1.
CAPITOLUL 38. ONI 2002 834
28
29 %-----------------------------------------------
30
31
32 \section{Becuri}
33 \hspace{6cm} \hfill {\it prof. Cristina B\u arbieru, Timi\c soara}
34
35 \hspace{0.66cm}
36 Un panou publicitar, de form\u a dreptunghiular\u a con\c tine becuri, unul l\^ang\u a
altul, aliniate pe linii \c si coloane.
37
38 Fiecare linie \c si fiecare coloan\u a are un comutator care schimb\u a starea tuturor
becurilor de pe acea linie sau coloan\u a, din starea \^in care se afl\u a \^in
starea opus\u a (stins/aprins, aprins/stins). Asupra unui bec nu se poate ac\c tiona
individual. Ini\c tial panoul are toate becurile stinse.
39
40 \vspace{0.2cm}
41 {\bf Cerin\c t\u a:}
42
43 S\u a se realizeze un program care ac\c t ion\^and asupra unui num\u ar minim de linii \
c si coloane aduce panoul din starea ini\c tial\u a, la o configura\c tie dat\u a,
dac\u a acest lucru este posibil.
44
45 \vspace{0.2cm}
46 {\bf Datele de intrare}
47
48 se vor citi din fi\c sierul BECURI.IN, care are urm\u atoarea configura\c tie:
49
50 $\bullet$ pe prima linie dou\u a numere naturale, $m$ \c si $n$, separate prin spa\c tiu
, repre\-zen\-t\^and num\u arul de linii \c si de coloane ale panoului;
51
52 $\bullet$ pe urm\u atoarele $m$ linii c\^ate $n$ coloane, formate din elementele $0$ sau
$1$, se\-pa\-rate prin spa\c tiu, reprezent\^and configura\c tia final\u a a
panoului. $1$ este codificarea unui bec aprins iar $0$ a unui bec stins.
53
54 \vspace{0.2cm}
55 {\bf Datele de ie\c sire}
56
57 se va afi\c sa o solu\c tie \^in fi\c sierul BECURI.OUT astfel:
58
59 $\bullet$ pe prima linie a fi\c sierului indicii coloanelor asupra c\u arora s-a ac\c
tionat, separa\c ti prin spa\c tiu.
60
61 $\bullet$ pe a doua linie a fi\c sierului indicii linilor asupra c\u arora s-a ac\c
tionat, separa\c ti prin spa\c tiu.
62
63 Dac\u a nu se ac\c tioneaz\u a asupra liniilor sau coloanelor se va afi\c sa $0$ pe
linia corespunz\u atoare.
64
65 Numerotarea liniilor, respectiv coloanelor \^incepe de la 1.
66
67 Dac\u a problema nu are solu\c tie, pe prima linie a fi\c sierului se va afi\c sa $-1$.
68
69 \vspace{0.2cm}
70 {\bf Restrictii}
71
72 $\bullet$ $m \le 100, n \le 100$
73
74 \vspace{0.2cm}
75 {\bf Exemplu:}
76
77 \begin{tabular}{|l|l|}
78 \hline
79 BECURI.IN & BECURI.OUT \\
80 \hline
81 5 6 & 2 5 \\
82 1 0 1 1 0 1 & 1 2 3 \\
83 1 0 1 1 0 1 & \\
84 1 0 1 1 0 1 & \\
85 0 1 0 0 1 0 & \\
86 0 1 0 0 1 0 & \\
87 \hline
88 \end{tabular}
89
90 \vspace{0.2cm}
91 {\bf Timp maxim de execu\c tie:} 1 secund\u a/test
CAPITOLUL 38. ONI 2002 836
92
93
94 \subsection{Indica\c tii de rezolvare}
95 \hspace{0.66cm}
96
97 {\it Solu\c tie prezentat\u a \^in GInfo 12/6}
98
99 Este evident c\u a pentru a ob\c tine prima linie a matricei nu putem dec\^at fie s\u a
comut\u am toate coloanele pe care trebuie s\u a se afle becuri aprinse \c si s\u a
nu comut\u am prima linie, fie s\u a comut\u am prima linie \c si s\u a comut\u am
toate coloanele pe care trebuie s\u a se afle becuri stinse.
100
101 Analog, pentru prima coloan\u a putem fie s\u a comut\u am toate liniile pe care trebuie
s\u a se afle becuri aprinse \c si s\u a nu comut\u am prima coloan\u a, fie s\u a
comut\u am prima coloan\u a \c si s\u a comut\u am toate liniile pe care trebuie s\u
a se afle becuri stinse.
102
103 Astfel avem patru posibilit\u a\c ti de a ob\c tine configura\c tia cerut\u a:
104
105 $\bullet$ comut\u am liniile c\u arora le corespund becuri aprinse pe prima coloan\u a \
c si coloanele c\u arora le corespund becuri aprinse pe prima linie;
106
107 $\bullet$ comut\u am liniile c\u arora le corespund becuri aprinse pe prima coloan\u a \
c si coloanele c\u arora le corespund becuri stinse prima linie;
108
109 $\bullet$ comut\u am liniile c\u arora le corespund becuri stinse pe prima coloan\u a \c
si coloanele c\u arora le corespund becuri aprinse pe prima linie;
110
111 $\bullet$ comut\u am liniile c\u arora le corespund becuri stinse pe prima coloan\u a \c
si coloanele c\u arora le corespund becuri stinse pe prima linie.
112
113 Vom verifica fiecare dintre aceste patru variante \c si apoi o vom alege pe cea care
114 implic\u a cele mai pu\c tine comut\u ari de linii \c si coloane.
115
116 Dac\u a nici una dintre cele patru variante nu duce la ob\c tinerea configura\c tiei
cerute, putem trage concluzia c\u a aceasta nu poate fi ob\c tinut\u a prin
comutarea unor linii \c si a unor coloane.
117
118 {\bf Analiza complexit\u a\c tii}
119
120 Citirea datelor de intrare implic\u a parcurgerea unei matrice p\u atratice, deci
ordinul de complexitate al acestei opera\c tii este $O(N^2)$.
121
122 Verificarea fiec\u areia dintre cele patru posibilit\u a\c ti de a ob\c tine solu\c tia
implic\u a parcurgerea primei linii \c si a primei coloane; ordinul de complexitate
al unei astfel de parcurgere este $O(N) + O(N) = O(N)$.
123
124 Pentru fiecare element este posibil ca linia/coloana corespunz\u atoare s\u a fie
comutat\u a. Opera\c tia de comutare implic\u a traversarea liniei sau coloanei, a\c
sadar are ordinul de complexitate $O(N)$. Ca urmare, ordinul de complexitate al
fiec\u areia dintre cele patru
125 posibilit\u a\c ti este $O(N) \cdot O(N) = O(N^2)$. \^Intreaga opera\c tie de
determinare a solu\c tiei are ordinul de complexitate $4 \cdot O(N^2) = O(N^2)$.
126
127 Scrierea datelor de ie\c sire implic\u a traversarea \c sirurilor care indic\u a dac\u a
o linie sau coloan\u a a fost comutat\u a; ordinul de complexitate al opera\c tiei
este $O(N)$.
128
129 \^In concluzie, algoritmul de rezolvare al acestei probleme are ordinul de complexitate
$O(N^2) + O(N^2) + O(N) = O(N^2)$.
130
131
132
133 %-----------------------------------------------
134
135 \subsection{Cod surs\u a}
136 \hspace{0.66cm}
137
138 \begin{lstlisting}[language=C++,commentstyle=\color{purple}, caption={\hspace{5mm}
becbun.cpp}]
139 #include <iostream>
140 #include <conio.h>
141 #include <stdio.h>
142
143 using namespace std;
144
CAPITOLUL 38. ONI 2002 837
A doua faz : pun 1 pe prima linie ³i veric. Constat m c se poate folosi aceea³i metot dar
cu un parametru pentru a transmite valoarea 0 sau 1.
32 facLinia1((byte)0);
33 facLinia1((byte)1);
34 facColoana1((byte)0);
35 facColoana1((byte)1);
36
37 PrintWriter out=new PrintWriter(
38 new BufferedWriter(new FileWriter("becuri.out")));
39
40 if(nlincsol+ncolcsol>n+m) out.println(-1);
41 else
42 {
43 if(ncolcsol==0) out.print(0);
44 else for(j=1;j<=n;j++) if(colcsol[j]==1) out.print(j+" ");
45 out.println();
46 if(nlincsol==0) out.print(0);
47 else for(i=1;i<=m;i++) if(lincsol[i]==1) out.print(i+" ");
48 out.println();
49 }
50 out.close();
51 }
52
53 static void facLinia1(byte val)
54 {
55 int i,j;
56 int nlc=0, ncc=0; // nr linii/coloane comutate
57 boolean ok=true;
58
59 for(j=1;j<=n;j++) colc[j]=0; // coloane necomutate inca
60 for(i=1;i<=m;i++) linc[i]=0; // linii necomutate inca
61 for(i=1;i<=m;i++) for(j=1;j<=n;j++) b[i][j]=a[i][j]; // copie
62
63 for(j=1;j<=n;j++)
64 if(b[1][j]!=val)
65 {
66 comutaColoana(j);
67 colc[j]=1; // coloana j este comutata;
68 ncc++;
69 }
70 for(i=1;i<=m;i++)
71 if(!okLinia(i)) {ok=false; break;}
72 else if(b[i][1]==1) { linc[i]=1; nlc++; }
73 if(ok&&(nlc+ncc<nlincsol+ncolcsol))
74 {
75 nlincsol=nlc;
76 ncolcsol=ncc;
77 for(i=1;i<=m;i++) lincsol[i]=linc[i];
78 for(j=1;j<=n;j++) colcsol[j]=colc[j];
79 }
80 }
81
82 static void facColoana1(byte val)
83 {
84 int i,j;
85 int nlc=0, ncc=0; // nr linii/coloane comutate
86 boolean ok=true;
87
88 for(j=1;j<=n;j++) colc[j]=0; // coloane necomutate inca
89 for(i=1;i<=m;i++) linc[i]=0; // linii necomutate inca
90 for(i=1;i<=m;i++) for(j=1;j<=n;j++) b[i][j]=a[i][j]; // copie
91
92 for(i=1;i<=m;i++)
93 if(b[i][1]!=val)
94 {
95 comutaLinia(i);
96 linc[i]=1; // linia i este comutata;
97 nlc++;
98 }
99 for(j=1;j<=n;j++)
100 if(!okColoana(j)) { ok=false; break;}
101 else if(b[1][j]==1) { colc[j]=1; ncc++; }
102 if(ok&&(nlc+ncc<nlincsol+ncolcsol))
103 {
104 nlincsol=nlc;
105 ncolcsol=ncc;
106 for(i=1;i<=m;i++) lincsol[i]=linc[i];
107 for(j=1;j<=n;j++) colcsol[j]=colc[j];
CAPITOLUL 38. ONI 2002 843
108 }
109 }
110
111 static boolean okLinia(int i)
112 {
113 int j;
114 for(j=2;j<=n;j++) if(b[i][j]!=b[i][1]) return false;
115 return true;
116 }
117
118 static boolean okColoana(int j)
119 {
120 int i;
121 for(i=2;i<=m;i++) if(b[i][j]!=b[1][j]) return false;
122 return true;
123 }
124
125 static void comutaColoana(int j)
126 {
127 int i;
128 for(i=1;i<=m;i++) b[i][j]=(byte)((1+b[i][j])%2); // 0<-->1
129 }
130
131 static void comutaLinia(int i)
132 {
133 int j;
134 for(j=1;j<=n;j++) b[i][j]=(byte)((1+b[i][j])%2); // 0<-->1
135 }
136 }
38.4 Discuri
Florin Gheµu, Bucure³ti
Se dau N numere reale considerate ca ind razele a N discuri.
Consider m c a³ez m un disc în sistemul xOy dac îl plas m la o coordonat x pozitiv
sucient de mare, tangent cu axa Ox ³i deasupra ei, apoi îl împingem spre Oy pân când devine
tangent cu Oy sau cu primul disc întâlnit, a³ezat anterior.
Dup a³ezarea tuturor discurilor în ordinea dat unele dintre ele pot considerate dispensabile,
pentru c prin eliminarea lor nu se modic l µimea total a gurii rezultate, adic nici un disc
nu se mai poate deplasa spre stânga.
Cerinµ :
Identicaµi toate discurile dispensabile dintr-o conguraµie dat .
Date de intrare:
Din ³ierul de intrare DISCURI.IN veµi citi de pe prima linie num rul N de discuri, iar de
pe urm toarele N linii, N numere reale reprezentând razele discurilor în ordinea de a³ezare, câte
unul pe linie.
Date de iesire:
În ³ierul DISCURI.OUT veµi scrie pe prima linie num rul K de discuri dispensabile, iar pe
urm toarele K linii, K întregi reprezentând numerele de ordine ale discurilor considerate dispen-
sabile, câte unul pe linie.
Restricµii:
a N & 1000.
CAPITOLUL 38. ONI 2002 844
Analiza complexit µii
Pentru ecare disc i care este introdus, se determin posibila coordonat xi datorat atingerii
cu toate cele i 1 discuri inserate anterior. Pentru cele N discuri se vor determina, în total,
0 1 2 ... N 1 N N 1©2 coordonate, deci ordinul de complexitate al acestei operaµii
2
este O N .
La ecare pas, pot marcate ca dispensabile cel mult toate discurile inserate anterior, a³adar
2
ordinul de complexitate al acestei operaµii este tot O N .
CAPITOLUL 38. ONI 2002 845
10
11 public static void main(String args[]) throws IOException
12 {
13 citeste();
14 calcul();
15 scrie();
16 }
17
18 static void citeste() throws IOException
19 {
20 BufferedReader br=new BufferedReader(new FileReader("discuri.in"));
21 StreamTokenizer st=new StreamTokenizer(br);
22 st.nextToken(); n=(int)st.nval;
23 r=new double[n+1];
24 x=new double[n+1];
25 dispensabil=new boolean[n+1]; // implicit este false
26 for(int i=1; i<=n; i++){st.nextToken();r[i]=st.nval;}
27 br.close();
28 }
29
30 static void calcul()
31 {
32 int i;
33 for(i=1; i<=n; i++) plaseazaCerc(i);
34 for(i=ultimulDisc+1; i<=n; i++) dispensabil[i]=true;
35 }
36
37 static void plaseazaCerc(int i)
38 {
39 int j, discContact=0;
40 double contactOx;
41 x[i]=r[i]; // initializare contact cu axa Oy
42 for(j=1; j<i; j++)
43 {
44 contactOx=coord(x[j],r[j],r[i]);
45 if(contactOx>x[i]) {x[i]=contactOx; discContact=j;}
46 }
47 for(j=discContact+1; j<i; j++) dispensabil[j]=true;
48 if(latime<x[i]+r[i]) {latime=x[i]+r[i]; ultimulDisc=i;}
49 }
50
51 static double coord(double xj,double rj, double ri)
52 {
53 return(xj+Math.sqrt((ri+rj)*(ri+rj)-(ri-rj)*(ri-rj)));
54 }
55
56 static void scrie() throws IOException
57 {
58 int i;
59 k=0;
60 for(i=1; i<=n; i++) if(dispensabil[i]) k++;
61 PrintWriter out=new PrintWriter(
62 new BufferedWriter(new FileWriter("discuri.out")));
63 out.println(k);
64 for(i=1; i<=n; i++) if(dispensabil[i]) out.println(i);
65 out.close();
66 }
67 }
38.5 Cod
lect. univ. Ovidiu Dom³a, Alba Iulia
Transmiterea ³i memorarea informaµiilor necesit diverse sisteme de codicare în vederea
utiliz rii optime a spaµiilor disponibile. Un sistem foarte des întâlnit este acela prin care unei
secvenµe de caractere i se asociaz un num r.
Se consider cuvintele formate numai cu literele mici ale alfabetului englez a, b, c, ..., z (26 de
caractere). Din toate aceste cuvinte le consider m doar pe cele ale c ror caractere sunt în ordine
strict lexicograc (caracterul de pe orice poziµie este strict mai mic decât orice caracter urm tor).
Sistemul de codicare se obµine astfel:
a Se ordoneaz cuvintele în ordinea cresc toare a lungimilor lor.
CAPITOLUL 38. ONI 2002 847
În continuare, pentru prima liter a cuvântului, va trebui s g sim num rul cuvintelor care
încep cu o liter mai mic (din punct de vedere lexicograc).
k1 k1
În cazul în care cuvântul are k litere, vor exista C25 cuvinte valide care k încep cu 'a', C25
cuvinte valide care încep cu 'b' etc.
k1
În general, vor exista C26i cuvinte valide care încep cu a i-a liter a alfabetului.
<
Dac prima liter a cuvântului este cea de-a n-a liter a alfabetului, vom avea i 1 C26i
n k1
Adunând toate valorile obµinute pe parcurs vom obµine num rul cuvintelor care se a înaintea
cuvântului dat. Adunând 1 la aceast valoare, vom obµine num rul de ordine al cuvântului.
Analiza complexit µii
Pentru a analiza complexitatea acestui algoritm va trebui s preciz m faptul c num rul lite-
relor din alfabet este constant, deci nu poate interveni în exprimarea ordinului de complexitate.
Acesta va stabilit doar în funcµie de lungimea k a cuvântului.
< k i
Iniµial se calculeaz suma i 1 C26 , operaµie realizabil în timp liniar, avân în vedere observaµia
anterioar . A³adar, primul pas al algoritmului are ordinul de complexitate O k .
< m1 k2
Pentru ecare liter a cuvântului se calculeaz suma i n1 C26i , unde variabilele au sem-
nicaµia prezentat anterior. Num rul de litere este implicat în determinarea valorii combin rii.
A³adar, calculul combin rii se realizeaz în timp liniar. Num rul de combin ri calculate nu de-
pinde de lungimea cuvântului, deci ordinul de complexitate al calcul rii acestei sume este O k .
În total vor calculate k astfel de sume, deci ordinul de complexitate al celui de-al doilea pas
2
al algoritmului este O k O k O k .
Citirea datelor de intrare ³i scrierea celor de ie³ire se realizeaz cu ajutorul unor operaµii
elementare, deci putem considera c au ordinul de complexitate O 1.
În concluzie, ordinul de complexitate al algoritmului de rezolvare a acestei probleme este
2 2
O k O k O k O k având în vedere c num rul literelor din alfabetul englez este
constant.
40 sol(x);
41 end;
42 delete(x,i,1);
43 end;
44 end;
45
46 begin
47 assign(f,’cod.in’);
48 reset(f);
49 ReadLn(f,cuv);
50 close(f);
51 assign(f,’cod.out’);
52 rewrite(f);
53 nr:=0;
54 if verifcuv(cuv) then
55 for l:=1 to length(cuv) do
56 Back(1)
57 else
58 writeln(f,0);
59 close(f);
60 end.
ONI 2001
39.1 Ferma
prof. Maria Niµ ³i prof. Adrian Niµ , Oradea
Un fermier are un teren care are forma unui tablou dreptunghiular lung de M unit µi ³i
lat de N unit µi. Pe teren sunt plantaµi din loc în loc copaci, pe care fermierul nu dore³te s -i
taie. Dorind s -³i supravegheze cultura, fermierul realizeaz un mic robot de form p trat având
latura de 3 unit µi pe care îl poate teleghida prin ferm , parcurgând unitate cu unitate o anumit
suprafaµ .
Robotul se poate mi³ca pe vertical ³i pe orizontal dar, nu poate trece peste copaci, nu îi poate
distruge, nu se poate roti ³i are nevoie pentru mi³care de o suprafaµ corespunz toare dimensiunii
lui.
Cerinµ
Ajutaµi-l pe fermier s determine suprafaµa maxim pe care o poate urm ri, folosind acest
sistem.
Date de intrare
Fi³ier de intrare: FERMA.IN
a Linia 1: N M - dou numere naturale nenule, separate pritr-un spaµiu, reprezentând num rul
de linii (N ), respectiv num rul de coloane (M );
a Liniile 2..N+1: C1 C2 ...CM - aceste N linii codic ferma; ecare linie conµine câte M
caractere (f r s e separate prin spaµii) având semnicaµia:
'.' - teren liber;
'+' - locul în care este plantat un copac;
'R' - centrul robotului.
Date de ie³ire
Fi³ier de ie³ire: FERMA.OUT
a Liniile 1..N: C1 C2 ...CM - aceste N linii codic modul în care fermierul poate s -³i utilizeze
robotul pe terenul s u; ecare linie conµine câte M caractere (f r s e separate prin spaµii)
având semnicaµia:
851
CAPITOLUL 39. ONI 2001 852
45 deplasareDin(ir-1,jr);
46 }
47
48 if(ir+2<=n) // jos
49 if((a[ir+2][jr-1]!=copac)&&(a[ir+2][jr]!=copac)&&(a[ir+2][jr+1]!=copac))
50 if((a[ir+2][jr-1]==liber)||(a[ir+2][jr]==liber)||(a[ir+2][jr+1]==liber))
51 {
52 a[ir+2][jr-1]=a[ir+2][jr]=a[ir+2][jr+1]=robot;
53 deplasareDin(ir+1,jr);
54 }
55
56 if(jr-2>=1) // stanga
57 if((a[ir-1][jr-2]!=copac)&&(a[ir][jr-2]!=copac)&&(a[ir+1][jr-2]!=copac))
58 if((a[ir-1][jr-2]==liber)||(a[ir][jr-2]==liber)||(a[ir+1][jr-2]==liber))
59 {
60 a[ir-1][jr-2]=a[ir][jr-2]=a[ir+1][jr-2]=robot;
61 deplasareDin(ir,jr-1);
62 }
63
64 if(jr+2<=m) // dreapta
65 if((a[ir-1][jr+2]!=copac)&&(a[ir][jr+2]!=copac)&&(a[ir+1][jr+2]!=copac))
66 if((a[ir-1][jr+2]==liber)||(a[ir][jr+2]==liber)||(a[ir+1][jr+2]==liber))
67 {
68 a[ir-1][jr+2]=a[ir][jr+2]=a[ir+1][jr+2]=robot;
69 deplasareDin(ir,jr+1);
70 }
71 }
72
73 static void afism()
74 {
75 int i,j;
76 for(i=1;i<=n;i++)
77 {
78 for(j=1;j<=m;j++) out.print((char) a[i][j]);
79 out.println();
80 }
81 out.println();
82 }
83 }
39.2 Fracµii
prof. Ovidiu Dom³a, Alba Iulia
O proprietate interesant a fracµiilor ireductibile este c orice fracµie se poate obµine dup
urm toarele reguli:
a pe primul nivel se a fracµia 1©1;
a pe al doilea nivel, în stânga fracµiei 1©1 de pe primul nivel, plas m fracµia 1©2 iar în dreapta
ei fracµia 2©1;
nivelul 1: 1©1
nivelul 2: 1©2 2©1
a pe ecare nivel k se plaseaz sub ecare fracµie i©j de pe nivelul de deasupra, fracµia i© i j
în stânga, iar fracµia i j ©j în dreapta.
nivelul 1: 1©1
nivelul 2: 1©2 2©1
nivelul 3: 1©3 3©2 2©3 3©1
Cerinµ
Dându-se o fracµie oarecare prin num r torul ³i numitorul s u, determinaµi num rul nivelului
pe care se a fracµia sau o fracµie echivalent (având aceea³i valoare) cu aceasta.
Date de intrare
Fi³ier de intrare: FRACTII.IN
a Linia 1: N M - dou numere naturale nenule, separate printr-un spaµiu, reprezentând
num r torul ³i numitorul unei fracµii.
Date de ie³ire
Fi³ier de ie³ire: FRACTII.OUT
CAPITOLUL 39. ONI 2001 855
a Linia 1: niv - num r natural nenul, reprezentând num rul nivelului care corespunde fracµiei.
Restricµii
1 $ N, M & 2.000.000.000
Exemple
FRACTII.IN FRACTII.OUT FRACTII.IN FRACTII.OUT
13 8 6 12 8 3
Timp maxim de execuµie: 1 secund /test
39.3 Tablou
prof. Rodica Pintea, Bucure³ti
Generaµi un tablou bidimensional cu propriet µile:
a conµine N linii ³i N coloane;
a elementele sale sunt numere naturale nenule;
a suma elementelor este egal cu num rul natural nenul S;
a pe nici o linie ³i pe nici o coloan nu exist dou elemente identice;
a diferenµa dintre cel mai mare ³i cel mai mic element ale tabloului este minim .
CAPITOLUL 39. ONI 2001 856
Date de intrare
Fi³ier de intrare: TABLOU.IN
a Linia 1: N S - dou numere naturale nenule, separate printr-un spaµiu, reprezentând num rul
de linii ³i de coloane ale tabloului, respectiv valoarea sumei tuturor elementelor din tablou;
Date de ie³ire
Fi³ier de ie³ire: TABLOU.OUT
a Linia 1..N: nr11 nr12 ... nr1N
nr21 nr22 ... nr2N
.........................
nrN 1 nrN 2 ... nrN N
pe aceste N linii se vor scrie elementele tabloului, câte o linie din tablou pe o linie din ³ier;
elementele se vor separa prin câte un spaµiu.
Restricµii ³i preciz ri
a 1 $ N & 100
0$S&2
31
a
a Dac problema nu are soluµie, în ³ierul de ie³ire se va scrie cifra 0.
a Dac problema are mai multe soluµii, în ³ier se va scrie una singur .
Exemplu
TABLOU.IN TABLOU.OUT
3 51 4 6 7
7 4 5
5 7 6
Timp maxim de execuµie: 1 sec/test
23 {
24 a[i][j]=x+(i+j)%n;
25 sp+=a[i][j];
26 }
27 p=s-sp;
28 System.out.println("sp="+sp+" s="+s+" p="+p);
29
30 System.out.println(); afism();
31 k=x+n-1;
32 while(p>0)
33 {
34 i=0;
35 while((p>0)&&(i<n)) // k=valoarea pe care o maresc cu 1
36 {
37 j=(n-i+k-1)%n;
38 System.out.println("k="+k+" i="+i+" j="+j+" p="+p);
39 a[i][j]++;
40 i++; p--;
41 }
42 System.out.println(); afism();
43 k--;
44 }
45 System.out.println(); afism();
46 out.close();
47 }
48
49 static void afism()
50 {
51 int i,j;
52 for(i=0;i<n;i++)
53 {
54 for(j=0;j<n;j++) System.out.print(a[i][j]+" ");
55 System.out.println();
56 }
57 }
58 }
37 k--;
38 }
39 for(i=0;i<n;i++)
40 {
41 for(j=0;j<n;j++) out.print(a[i][j]+" ");
42 out.println();
43 }
44 out.close();
45 }
46 }
39.5 Cuvinte
prof. Maria Niµ ³i prof. Adrian Niµ , Oradea
Se consider o list având un num r cunoscut de cuvinte. Din acest list s-au ales
dou cuvinte oarecare. Se dore³te transformarea primului cuvânt în cel de-al doilea, trecând
prin cuvinte intermediare, existente în lista dat . Trecerea dintr-un cuvânt în altul se poate face
folosind urm toarele operaµii: schimbarea, ad ugarea sau ³tergerea unui singur caracter.
Cerinµ
Dându-se o list de cuvinte ³i dou cuvinte din aceasta, g siµi cea mai scurt secvenµ de
operaµii care transform primul cuvânt în cel de-al doilea folosind operaµiile permise.
Date de intrare
Fi³ierul de intrare: CUVINTE.IN
a Linia 1: N P Q - trei numere naturale nenule, reprezentând num rul cuvintelor din list
(N ), poziµia primului cuvânt în list (P ), respectiv poziµia celui de-al doilea cuvânt în list (Q);
CAPITOLUL 39. ONI 2001 860
a Liniile 2..N+1: cuvânt - aceste N linii conµin ecare câte un cuvânt, aparµinând listei.
Date de ie³ire
Fi³ier de ie³ire: CUVINTE.OUT
a Linia 1: M - num r natural, reprezentând num rul minim de pa³i necesari pentru a ajunge
de la primul cuvânt la al doilea;
a Liniile 2..M+2: cuvânti - pe aceste linii apar în ordine cuvintele dintr-o secvenµ ce respect
cerinµa problemei (câte un cuvânt pe linie), inclusiv primul cuvânt al secvenµei.
Restricµii ³i preciz ri
a 2 & N & 100
a 1 & M, P, Q & 100
a num rul maxim de caractere dintr-un cuvânt este 100;
a dac nu exist soluµie, în ³ierul de ie³ire se va scrie num rul 0 (zero);
a dac sunt mai multe secvenµe de lungime minim , în ³ier se va scrie una singur .
Exemple
CUVINTE.IN CUVINTE.OUT CUVINTE.IN CUVINTE.OUT
715 2 716 0
car car car
cer mar cer
cerc mare cerc
mar mar
mare mare
rosu rosu
inrosit inrosit
Timp maxim de execuµie: 2 secunde/test
21 st.nextToken(); p=(int)st.nval;
22 st.nextToken(); q=(int)st.nval;
23 for(i=1;i<=n;i++) { st.nextToken(); cuvant[i]=st.sval.toString(); }
24 for(i=1;i<n;i++)
25 for(j=i+1;j<=n;j++)
26 a[i][j]=a[j][i]=trece(cuvant[i],cuvant[j]);
27
28 // drum minim intre p si q
29 ic=0; sc=1; coada[ic]=p; // ic==sc ==> coada vida!
30 analizat[p]=1;
31 while(ic!=sc)
32 {
33 i=coada[ic]; ic++;
34 for(j=1;j<=n;j++)
35 {
36 if((analizat[j]==0)&&(a[i][j]==1))
37 {
38 coada[sc]=j; sc++;
39 analizat[j]=1;
40 d[j]=d[i]+1;
41 pr[j]=i;
42 if(j==q) break;
43 }
44 }
45 if(analizat[q]==1) break;
46 }
47 out.println(d[q]);
48 drum(q);
49 out.close();
50 }
51
52 static void drum(int j)
53 {
54 if(pr[j]!=0) drum(pr[j]);
55 out.println(cuvant[j]);
56 }
57
58 static int trece(String x, String y) // lg egale sau diferenta=1
59 {
60 int k,dif;
61 if(Math.abs(x.length()-y.length())>1) return 0;
62 String xy;
63 if(x.length()<y.length()) {xy=x; x=y; y=xy;} // lg.x >= lg.y
64
65 int nx=x.length(), ny=y.length();
66 if(nx==ny)
67 {
68 dif=0;
69 for(k=0;k<nx;k++) if(x.charAt(k)!=y.charAt(k)) dif++;
70 if(dif==1) return 1; else return 0;
71 }
72 else // nx>ny
73 {
74 k=0;
75 while((k<ny)&&(x.charAt(k)==y.charAt(k))) k++;
76 if(k==ny) return 1;
77 else
78 {
79 k++;
80 while((k<ny)&&(x.charAt(k)==y.charAt(k-1))) k++;
81 if(k==ny) return 1; else return 0;
82 }
83 }
84 }
85 }
39.6 Grup
prof. Emanuela Cerchez ³i prof. Marinel erban, Ia³i
Administratorul reµelei cu N calculatoare de la SRI împarte, din motive strategice, aceste
calculatoare în mai multe grupuri. De fapt, important este doar num rul de grupuri ³i num rul de
calculatoare din ecare grup, a³a c împ rµirea este descris prin ³irul numerelor de calculatoare
din ecare grup, ordonat cresc tor.
CAPITOLUL 39. ONI 2001 862
Date de ie³ire
Fi³ier de ie³ire: GRUP.OUT
a p - num rul de grupe din împ rµirea care precede lexicograc imediat împ rµirea dat ;
a h1 h2 ... hp - num rul de calculatoare din cele p grupe ale împ rµirii precedente;
a u - num rul de grupe din împ rµirea care succede lexicograc imediat împ rµirea dat ;
a t1 t2 ... tu - num rul de calculatoare din cele u grupe ale împ rµirii urm toare;
Restricµii ³i preciz ri
a 2 & N & 1000
a g1 g2 ... gk h1 h2 ... hp t1 t2 ... tu N
a 1 & g1 & g2 & ... & gk ; 1 & h1 & h2 & ... & hp ; 1 & t1 & t2 & ... & tu ;
a 1$k$N
a 1 & p, u & N
Exemplu
GRUP.IN GRUP.OUT
14 3 3
266 257
2
2 12
Timp maxim de execuµie: 1 secund /test
(cu excepµia ultimului grup, eventual, care va avea cel puµin g k 1 1 calculatoare dar nu mai
mult de 2g k 1 1 calculatoare).
ONI 2000
40.1 Algoritm
prof. Roxana Tîmplaru, Liceul "tefan Odobleja", Craiova
Georgel scrie un algoritm care conµine structuri de atribuire, alternative, de selecµie,
repetitive ³i compuse. Dup scrierea algoritmului vrea s -l testeze pentru toate cazurile posibile.
Pentru aceasta trebuie s cunoasc num rul minim de date de test necesare.
Pentru descrirea structurilor se utilizeaz urm toarele cuvinte cheie:
- pentru atribuire ATRIB
- pentru alternativ DACA
ATUNCI
ALTFEL unde ALTFEL poate lipsi
- pentru selecµie ALEGE
CAZ
CAZ_IMPLICIT unde CAZ_IMPLICIT poate lipsi
- pentru repetitive 1) CAT_TIMP
2) REPETA
PANA_CAND
3) PENTRU
- pentru compus INCEPUT
SFARSIT
Nu se face diferenµ între literele mari ³i literele mici. Un algoritm începe cu cuvântul cheie
INCEPUT, se termin cu SFARSIT ³i nu conµine structuri vide. De asemenea o structur compus
începe cu cuvântul cheie INCEPUT ³i se termin cu SFARSIT.
Cerinµ
S se calculeze num rul minim de date de test necesare pentru vericarea algoritmului.
Date de intrare:
Din ³ierul text ALGOR.IN se cite³te algoritmul.
Fi³ierul conµine pe ecare linie câte un singur cuvânt cheie.
Nu exist linii vide.
Algoritmul respect principiile program rii structurate ³i este scris corect.
Date de ie³ire:
În ³ierul ALGOR.OUT se va scrie pe prima linie num rul minim de date de test necesare
pentru vericarea algoritmului. Vericarea se bazeaz pe principiul "cutiei transparente", ceea ce
864
CAPITOLUL 40. ONI 2000 865
înseamn c testele se compun astfel încât s e posibil executarea algoritmului pe toate ramurile
posibile.
De exemplu, în cazul unei structuri repetitive CAT_TIMP care conµine în corpul s u un singur
ATRIB, un test vizeaz o execuµie f r s se intre în corpul structurii, altul pentru a trece cel
puµin o dat ³i prin corpul acestuia.
În mod similar se trateaz ³i structura PENTRU.
Restricµii ³i preciz ri
a Dup cuvintele cheie
ATUNCI, ALTFEL,
CAZ, CAZ_IMPLICIT,
CAT_TIMP, REPETA, PENTRU
trebuie s existe obligatoriu o structur de atribuire, alternativ , de decizie, repetitiv sau
compus .
Exemplul 1:
ALGOR.IN ALGOR.OUT
INCEPUT 2
atrib
DACA
atunci
ATRIB
SFARSIT
Exemplul 2:
ALGOR.IN ALGOR.OUT OBS.
INCEPUT 1 REPETA se execut cel puµin o dat
ATRIB
REPETA
inceput
atrib
atrib
SFARSIT
pana_cand
SFARSIT
Exemplul 3:
ALGOR.IN ALGOR.OUT OBS.
INCEPUT 3 - se execut ATRIB de la primul CAZ
ATRIB - se execut ATRIB de la al doilea CAZ
ALEGE - nu se execut nici primul CAZ,
CAZ nici al doilea
ATRIB
CAZ
INCEPUT
ATRIB
ATRIB
SFARSIT
SFARSIT
Exemplul 4:
ALGOR.IN ALGOR.OUT OBS.
INCEPUT 3 - se execut ATRIB
ATRIB de la primul CAZ
ALEGE - se execut ATRIB
CAZ de la al doilea CAZ
ATRIB - se execut ATRIB
CAZ de la CAZ_IMPLICIT
ATRIB
CAZ_IMPLICIT
ATRIB
SFARSIT
Exemplul 5:
CAPITOLUL 40. ONI 2000 866
48 end;
49 nr := nrAtunci + nrAltfel;
50 end
51
52 else if atom = ’alege’ then begin
53 AnaLex;
54 implicit := false;
55 nr := 0;
56 while (atom = ’caz’) or (atom = ’caz_implicit’) do begin
57 if (atom = ’caz_implicit’) then implicit := true;
58 AnaLex;
59 nrCaz := Instr;
60 nr := nr + nrCaz;
61 end;
62 if not implicit then inc(nr);
63 end
64
65 else if atom = ’cat_timp’ then begin
66 AnaLex;
67 nr := Instr+1;
68 end
69
70 else if atom = ’repeta’ then begin
71 AnaLex;
72 nr := Instr;
73 AnaLex;
74 end
75
76 else if atom = ’pentru’ then begin
77 AnaLex;
78 nr := Instr+1;
79 end
80
81 else if atom = ’inceput’ then begin
82 contor := 0;
83 repeat
84 if atom = ’inceput’ then begin
85 AnaLex;
86 inc(contor)
87 end
88 else if atom = ’sfarsit’ then begin
89 AnaLex;
90 dec(contor);
91 end
92 else begin
93 nrTemp := Instr;
94 nr := nr * nrTemp;
95 end
96 until contor = 0;
97 end
98
99 else nr := 1;
100
101 Instr := nr;
102 end;
103
104 begin
105 { Deschidere fisiere }
106 assign(fin, ’Algor.in’);
107 reset(fin);
108 assign(fout, ’Algor.out’);
109 rewrite(fout);
110
111 { Calcul }
112 AnaLex;
113 writeln(fout,Instr);
114 close(fout);
115 close(fin);
116 end.
1 import java.io.*;
2 class Algoritm1
3 {
4 static String atom;
5 static String fin="algor.in";
6 static String fout="algor.out";
7 static StreamTokenizer st;
8 static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
9 static String pauza;
10
11 public static void main(String[] args) throws IOException
12 {
13 st=new StreamTokenizer(
14 new BufferedReader( new FileReader(fin)));
15 st.wordChars((int)’_’,(int)’_’);
16
17 PrintWriter out=new PrintWriter(
18 new BufferedWriter(new FileWriter(fout)));
19
20 readAtom();
21 out.println(nrTeste()); // "inceput" bloc
22 out.close();
23 }// main
24
25 static int nrTeste() throws IOException
26 {
27 int nr, nrTesteAtunci, nrTesteAltfel, nrTesteCaz;
28 int nrBlocuriDeschise; // inceput
29 boolean implicit;
30
31 String atomr=new String(atom);
32 System.out.println(" ***> "+atomr);
33
34 if(atom.equals("inceput")) // inceput bloc
35 {
36 nr=1; // initializare pentru produsul: nr=nr*nrTeste();
37 nrBlocuriDeschise=1;
38 readAtom();
39 while(nrBlocuriDeschise!=0)
40 {
41 if(atom.equals("inceput")) {nrBlocuriDeschise++; readAtom();}
42 else if(atom.equals("sfarsit")) {nrBlocuriDeschise--; readAtom();}
43 else nr=nr*nrTeste();
44 }
45 }
46 else if(atom.equals("atrib")) { readAtom(); nr=1; }
47 else if(atom.equals("daca"))
48 {
49 readAtom(); // citeste "atunci"
50 readAtom(); nrTesteAtunci=nrTeste();
51 nrTesteAltfel=1;
52 if(atom.equals("altfel")) {readAtom(); nrTesteAltfel=nrTeste();}
53 nr=nrTesteAtunci+nrTesteAltfel;
54 }
55 else if(atom.equals("alege"))
56 {
57 implicit=false;
58 nr=0;
59 readAtom();
60 while(atom.equals("caz")||atom.equals("caz_implicit"))
61 {
62 if(atom.equals("caz_implicit")) implicit = true;
63 readAtom(); nrTesteCaz=nrTeste();
64 nr=nr+nrTesteCaz;
65 }
66 if(!implicit) nr++;
67 }
68 else if(atom.equals("cat_timp")) {readAtom(); nr=nrTeste()+1;}
69 else if(atom.equals("repeta"))
70 {
71 readAtom(); nr=nrTeste();
72 readAtom(); // citeste ce urmeaza dupa "pana_cand"
73 }
74 else if(atom.equals("pentru")) {readAtom(); nr=nrTeste()+1;}
75 else nr=1; // la eof
CAPITOLUL 40. ONI 2000 869
76
77 System.out.println(" <*** "+atomr);
78 return nr;
79 }
80
81 static void readAtom() throws IOException
82 {
83 if(st.nextToken()==StreamTokenizer.TT_EOF) atom="eof";
84 else atom=st.sval.toString().toLowerCase();
85
86 System.out.println("readAtom() "+atom);
87 pauza=br.readLine();
88 }
89 }// class
59 nr=nr+nrTesteCaz;
60 }
61 if(!implicit) nr++;
62 }
63 else if(atom.equals("cat_timp")) {readAtom(); nr=nrTeste()+1;}
64 else if(atom.equals("repeta"))
65 {
66 readAtom(); nr=nrTeste();
67 readAtom(); // citeste ce urmeaza dupa "pana_cand"
68 }
69 else if(atom.equals("pentru")) {readAtom(); nr=nrTeste()+1;}
70 else nr=1; // pentru "eof"
71
72 return nr;
73 }
74
75 static void readAtom() throws IOException
76 {
77 if(st.nextToken()==StreamTokenizer.TT_EOF) atom="eof";
78 else atom=st.sval.toString().toLowerCase();
79 }
80 }// class
Date de ie³ire
Fi³ierul de ie³ire COD.OUT va conµine o singur linie pe care se va aa codul urm tor; dac
nu exist un astfel de cod, atunci în ³ier se va scrie "Este ultimul cod."
Restricµii ³i preciz ri
a Codurile sunt formate din cel mult 100 de litere mici ale alfabetului latin.
Exemple:
COD.IN COD.OUT COD.IN COD.OUT
amaaxm amamax xmmaaa Este ultimul cod.
Timp de execuµie: 1 secund /test.
Se determin cel mai mare indice i pentru care cod[i]<cod[i+1]. Caracterele de pe ultimile
poziµii din cod, incepând cu poziµia i inclusiv, se scriu în noul cod în ordine cresc toare.
2 label e;
3 var
4 cod,cod_temp:string;
5 i,j:byte;
6 t:text;
7
8 function nedes(s:string):boolean;
9 var
10 i:byte;
11 begin
12 nedes:=false;
13 for i:=1 to length(s)-1 do
14 if s[i]<s[i+1] then
15 begin
16 nedes:=true;
17 break;
18 end;
19 end;
20
21 procedure next(pos:byte);
22 var
23 i,start,j:byte;
24 next_min:byte;
25 ch:char;
26
27 begin
28 for i:=pos+1 to length(cod) do if cod[i]>cod[pos] then
29 begin
30 next_min:=i;
31 break;
32 end;
33 if next_min<length(cod) then
34 begin
35 start:=next_min+1;
36 for i:=start to length(cod) do
37 if (cod[i]>cod[pos]) and (cod[i]<cod[next_min]) then next_min:=i;
38 ch:=cod[pos];
39 cod[pos]:=cod[next_min];
40 cod[next_min]:=ch;
41 if pos+1<length(cod) then
42 for i:=pos+1 to length(cod)-1 do
43 begin
44 start:=i;
45 for j:=i+1 to length(cod) do
46 if cod[start]>cod[j] then start:=j;
47 ch:=cod[i];
48 cod[i]:=cod[start];
49 cod[start]:=ch;
50 end;
51 end
52 else
53 begin
54 ch:=cod[length(cod)];
55 cod[length(cod)]:=cod[length(cod)-1];
56 cod[length(cod)-1]:=ch;
57 end;
58 end;
59
60 begin
61 assign(t,’cod.in’);
62 reset(t);
63 read(t,cod);
64 close(t);
65 assign(t,’cod.out’);
66 rewrite(t);
67 if nedes(cod)=true then
68 begin
69 for i:=length(cod)-1 downto 1 do
70 begin
71 for j:=i to length(cod) do cod_temp:=cod_temp+cod[j];
72 if nedes(cod_temp) then
73 begin
74 next(i);
75 writeln(t,cod);
76 goto e;
77 end;
CAPITOLUL 40. ONI 2000 872
78 end;
79 if i=1 then
80 begin
81 writeln(t,’Este ultimul cod’);
82 goto e;
83 end;
84 end
85 else writeln(t,’Este ultimul cod’);
86 e:close(t);
87 end.
1 import java.io.*;
2 class Cod1
3 {
4 static String cod;
5 static int n;
6 static int[] nrl=new int[26];
7
8 public static void main(String[] args) throws IOException
9 {
10 int i;
11 BufferedReader br=new BufferedReader(new FileReader("cod.in"));
12 PrintWriter out=new PrintWriter(
13 new BufferedWriter(new FileWriter("cod.out")));
14 cod=br.readLine();
15 n=cod.length();
16
17 System.out.println(cod);
18 for(i=0;i<n;i++) System.out.print(cod.charAt(i)+"\t ");
19 System.out.println();
20 for(i=0;i<n;i++) System.out.print((byte)cod.charAt(i)+"\t ");
21 System.out.println();
22 for(i=0;i<n;i++) System.out.print(((byte)cod.charAt(i)-’a’)+"\t ");
23 System.out.println();
24 for(i=0;i<n;i++) nrl[(byte)cod.charAt(i)-’a’]++;
25 System.out.println();
26 for(i=0;i<26;i++)
27 if(nrl[i]>0) System.out.println(i+"\t"+(char)(i+’a’)+"\t"+nrl[i]);
28 out.close();
29 }
30 }
40.3 Comoara
Mihai Stroe, student, Universitatea Politehnica, Bucure³ti
Cei K membri ai unui grup de c ut tori de comori se a într-un complex dreptunghiular
format din camere p trate de latur 1.
În mod normal toate camerele ar trebui s e deschise, dar o parte dintre ele sunt închise ³i
pot deschise doar cu ajutorul unor cartele speciale. Astfel, ecare camer ³i ecare cartel are
asociat un num r între 0 ³i 20; o camer cu num rul asociat 0 este deschis de la început, în
timp ce una cu num rul asociat diferit de 0 este iniµial închis , poate deschis din interior sau
din exterior dintr-o camer vecin cu o cartel cu num rul corespunz tor ³i va r mâne deschis
ulterior.
Cartelele cu num rul asociat 0 nu au nici o întrebuinµare practic . Un num r poate asociat
mai multor cartele, respectiv camere. Dintr-o camer se poate trece în alta numai dac ele sunt
vecine ³i ambele sunt deschise. Dou camere se consider vecine dac au un perete (deci o latur )
în comun.
În ecare camer se a comori cu o valoare între 0 ³i 10000. De asemenea, în ecare camer
se a exact o cartel de acces (cu num rul asociat între 0 ³i 20); un c ut tor de comori poate
ridica ³i folosi cartelele din camerele prin care trece, dar nu le poate da unui alt c ut tor decât
dac respectivul se a în aceea³i camer cu el.
Cerinµ
Cunoscându-se conguraµia complexului ³i poziµiile iniµiale ale c ut torilor de comori, s se
determine valoarea maxim a comorilor adunate de ace³tia.
Datele de intrare
se citesc din ³ierul COMOARA.IN care are urm torul format:
pe prima linie dimensiunile complexului, m ³i n
pe urm toarele m linii numerele asociate ec rei camere
pe urm toarele m linii valorile comorilor din ecare camer
pe urm toarele m linii numerele asociate cartelelor din ecare camer
pe urm toarea linie num rul K al membrilor grupului
pe urm toarele K linii poziµiile iniµiale ale membrilor grupului în complex
Datele de ie³ire:
În ³ierul COMOARA.OUT se va a³a valoarea total a comorilor care pot strânse de cei
K membri ai grupului.
Restricµii ³i preciz ri
a m, n & 40, k & 10
Exemple
CAPITOLUL 40. ONI 2000 876
COMOARA.IN COMOARA.OUT
33 23909
0 0 11
14 0 10
19 0 0
5162 4331 1390
5230 1955 9796
5507 6210 1021
000
19 0 0
000
2
32
21
Observaµie: al doilea c utator de comori nu poate p trunde în camera 3, 1, de³i are cartela
corespunz toare, pentru c nu poate p r si camera 2, 1 în care este plasat iniµial.
Timp maxim de execuµie pe test: 1 secund
Se folose³te un algoritm de tip ll (umplere) pentru ecare c ut tor de comori, în mod repetat,
pân când nu mai apar îmbun t µiri ale soluµiei. Pe parcurs, unele camere devin ³i r mân deschise.
Pentru ecare c ut tor de comori se p streaz informaµii referitoare la cheile pe care le are la un
moment dat (în momentul în care poate p trunde într-o camer , el ia cheia existent în acea
camer ).
36 read(fi,key[i,j]);
37 readln(fi);
38 end;
39 readln(fi,k);
40 for i:=1 to k do
41 readln(fi,x[i],y[i]);
42 close(fi);
43 end;
44
45 procedure init;
46 begin
47 s:=0;
48 for ii:=1 to k do
49 begin
50 ok[ii,x[ii],y[ii]]:=1;
51 chei[ii]:=[0];
52 end;
53 for i:=1 to m do
54 for j:=1 to n do
55 suma:=suma+v[i,j];
56 end;
57
58 procedure fill(x,i,j:integer);
59
60 begin
61 if (ok[x,i,j]=0)and(not(a[i,j] in chei[x])) then exit;
62 if(i<0)or(i>m)or(j<0)or(j>n) then exit;
63 if p[i,j]=1 then exit;
64 p[i,j]:=1;
65 if ok[x,i,j]=0 then gata:=false;
66 ok[x,i,j]:=1;
67 chei[x]:=chei[x]+[key[i,j]];
68 if a[i,j] in chei[x] then
69 a[i,j]:=0;
70 s:=s+v[i,j];
71 v[i,j]:=0;
72 if a[i,j] in chei[x] then
73 begin
74 fill(x,i-1,j);
75 fill(x,i+1,j);
76 fill(x,i,j-1);
77 fill(x,i,j+1);
78 end;
79 end;
80
81 procedure expand;
82 begin
83 gata:=true;
84 for ii:=1 to k do
85 begin
86 fillchar(p,sizeof(p),0);
87 fill(ii,x[ii],y[ii]);
88 end;
89
90 end;
91
92 procedure dump;
93 begin
94 for i:=1 to m do
95 for j:=1 to n do
96 begin
97 l:=0;
98 for ii:=1 to k do
99 if ok[ii,i,j]=1 then
100 l:=1;
101 if l=1 then
102 d[i,j]:=1;
103 end;
104 for i:=1 to m do
105 begin
106 for j:=1 to n do
107 write(fo,d[i,j],’ ’);
108 writeln(fo);
109 end;
110
111 end;
CAPITOLUL 40. ONI 2000 878
112
113 procedure solve;
114 begin
115 init;
116 gata:=false;
117 while not gata do
118 expand;
119 rewrite(fo);
120 writeln(fo,s);
121 { dump;}
122 close(fo);
123 end;
124
125 begin
126 readdata;
127 solve;
128 end.
53 for(i=1;i<=k;i++)
54 {
55 st.nextToken(); lin[i]=(int)st.nval;
56 st.nextToken(); col[i]=(int)st.nval;
57 }
58 }
59
60 static void rezolvare()
61 {
62 int i;
63 s=0;
64 for(i=1;i<=k;i++) arecheia[i][0]=true;
65 for(i=1;i<=k;i++) amaifost[i][lin[i]][col[i]]=true;
66
67 gata=false;
68 while(!gata) alteCautari();
69 }
70
71 static void alteCautari()
72 {
73 int i;
74 gata=true;
75 for(i=1;i<=k;i++)
76 {
77 curatTraseu();
78 cauta(i,lin[i],col[i]);
79 }
80 }
81
82 static void curatTraseu()
83 {
84 int i,j;
85 for(i=1;i<=m;i++) for(j=1;j<=n;j++) traseu[i][j]=false;
86 }
87
88 static void cauta(int x, int i, int j) // alg "fill" (de umplere)
89 {
90 if((i<1)||(i>m)||(j<1)||(j>n)) return;
91 if(traseu[i][j]) return; // a mai trecut pe aici
92 if((!amaifost[x][i][j])&& // nu a mai fost aici
93 (!arecheia[x][codCamera[i][j]])) return; // nu are cheia de intrare aici
94
95 traseu[i][j]=true;
96 if(!amaifost[x][i][j]) gata=false; // face o imbunatatire
97 amaifost[x][i][j]=true;
98
99 arecheia[x][cheiaDinCamera[i][j]]=true; // ia cheia din camera
100 s=s+valc[i][j]; // ia valorile
101 valc[i][j]=0; // raman valori zero
102
103 if(arecheia[x][codCamera[i][j]]) // daca are cheia camerei
104 {
105 codCamera[i][j]=0; // camera ramane deschisa
106 cauta(x,i-1,j);
107 cauta(x,i+1,j);
108 cauta(x,i,j-1);
109 cauta(x,i,j+1);
110 }
111 }
112
113 static void afisare() throws IOException
114 {
115 out=new PrintWriter(
116 new BufferedWriter(new FileWriter("comoara.out")));
117 out.println(s);
118 out.close();
119 }
120 }
40.4 Cuburi
prof. Ovidiu Dom³a, Colegiul "Horea, Clo³ca ³i Cri³an", Alba Iulia
Un joc nou este format din n cuburi identice, numerotate de la 1 la n. Fiecare cub are
CAPITOLUL 40. ONI 2000 880
Date de intrare
Fisierul CUBURI.IN conµine pe prima linie valoarea lui n.
Pe urm toarele n 1 linii, se a o succesiune de a³ezare a cuburilor, pentru ecare cub
specicând:
num r_cub biletel zar
valori separate prin câte un spatiu.
Date de ie³ire
Fi³ierul de iesire CUBURI.OUT va conµine pe dou linii rezultatele de la punctul a ³i respectiv
b dup cum urmeaz :
a Dac succesiunea este valid , prima linie va contine valoarea 0. În caz contrar, prima linie
va contine num rul cubului ce nu poate alipit, num rul cubului ³i num rul feµei la care nu se
poate alipi, precum si codul de eroare:
1 pentru alipire la cub inexistent;
2 pentru alipire pe o faµ ocupat .
b Dac obiectul nu este paralelipiped plin, sau dac succesiunea nu este valid , a doua linie a
³ierului va conµine valoarea 0.
Dac obiectul este paralelipiped plin, a doua linie a ³ierului va conµine dimensiunile acestuia,
m surate în num r de cuburi, în ordinea:
num r de cuburi pe directiile sus-jos, stânga-dreapta, faµ -spate
separate prin câte un spatiu.
Restricµii ³i precizri
a 2 & n & 1000;
a pe o dimensiune se alipesc cel mult 10 cuburi.
Exemple
CUBURI.IN CUBURI.OUT CUBURI.IN CUBURI.OUT
6 0 4 0
211 321 211 0
324 421
514 324
631
463
CUBURI.IN CUBURI.OUT CUBURI.IN CUBURI.OUT
8 6361 8 8732
211 0 211 0
514 426
636 324
762 636
324 762
426 516
873 873
Timp maxim de execuµie: 1 secund /test
Identic m poziµia cubului în obiect prin coordonatele sale din (stanga, jos, faµ ). De aseme-
nea, pentru c pe o dimensiune se alipesc cel mult 10 cuburi, folosim un tablou tridimensional
pentru a reµine num rul de ordine al cubului care este plasat în oricare punct al spaµiului în care
poate s e construit corpul respectiv.
65 i:=i+1;
66 if i>maxi then
67 maxi:=i;
68 end;
69 3: begin
70 j:=j-1;
71 if j<minj then
72 minj:=j;
73 end;
74 4: begin
75 j:=j+1;
76 if j>maxj then
77 maxj:=j;
78 end;
79 5: begin
80 k:=k-1;
81 if k<mink then
82 mink:=k;
83 end;
84 6: begin
85 k:=k+1;
86 if k>maxk then maxk:=k;
87 end;
88 end;
89 if a[i,j,k]=0 then
90 begin
91 a[i,j,k]:=ll;
92 end
93 else
94 begin
95 writeln(g,ll,’ ’,c,’ ’,d,’ 2’ );
96 writeln(g,0);
97 { afiscub;}
98 CLOSE(g);
99 CLOSE(F);
100 halt(1);
101 end;
102 end;
103 if (maxi-mini+1)*(maxj-minj+1)*(maxk-mink+1)=n then
104 begin
105 { afiscub;}
106 writeln(g,0);
107 write(g,(maxi-mini+1),’ ’,(maxj-minj+1),’ ’,(maxk-mink+1))
108 end
109 else
110 begin
111 writeln(g,0);
112 writeln(g,0);
113 {afiscub}
114 end;
115 close(f);
116 CLOSE(g);
117 end.
17 boolean ok=true;
18
19 StreamTokenizer st=new StreamTokenizer(
20 new BufferedReader(new FileReader("cuburi.in")));
21 PrintWriter out=new PrintWriter(
22 new BufferedWriter(new FileWriter("cuburi.out")));
23
24 st.nextToken(); n=(int)st.nval;
25 x=new int[n+1];
26 y=new int[n+1];
27 z=new int[n+1];
28 eplasat=new boolean[n+1];
29
30 x[1]=11; y[1]=11; z[1]=11; // coordonatele cubului 1
31 ecubul[x[1]][y[1]][z[1]]=1; // aici e cubul 1
32 eplasat[1]=true; // cubul 1 este plasat in obiect
33 minx=maxx=x[1];
34 miny=maxy=y[1];
35 minz=maxz=z[1];
36
37 for(i=2;i<=n;i++)
38 {
39 st.nextToken(); cubnou=(int)st.nval;
40 st.nextToken(); cubvechi=(int)st.nval;
41 st.nextToken(); fatacubvechi=(int)st.nval;
42 if(!eplasat[cubvechi]) // alipire la cub inexisent
43 {
44 out.println(cubnou+" "+cubvechi+" "+fatacubvechi+" 1");
45 out.println("0"); // succesiunea nu e valida
46 ok=false;
47 break; // iese din for ==> nu mai pun "else" !
48 }
49
50 x[cubnou]=x[cubvechi];
51 y[cubnou]=y[cubvechi];
52 z[cubnou]=z[cubvechi];
53 switch(fatacubvechi)
54 {
55 case sus: z[cubnou]++; if(z[cubnou]>maxz) maxz++; break;
56 case jos: z[cubnou]--; if(z[cubnou]<minz) minz--; break;
57 case stanga: x[cubnou]--; if(x[cubnou]<minx) minx--; break;
58 case dreapta: x[cubnou]++; if(x[cubnou]>maxx) maxx++; break;
59 case fata: y[cubnou]++; if(y[cubnou]>maxy) maxy++; break;
60 case spate: y[cubnou]--; if(y[cubnou]<miny) miny--; break;
61 default: System.out.println("Date de intrare eronate!");
62 }
63 if(ecubul[x[cubnou]][y[cubnou]][z[cubnou]]!=0)// fata ocupata
64 {
65 out.println(cubnou+" "+cubvechi+" "+fatacubvechi+" 2");
66 out.println("0"); // succesiunea nu e valida
67 ok=false;
68 break; // iese din for ==> nu mai pun "else" !
69 }
70 ecubul[x[cubnou]][y[cubnou]][z[cubnou]]=cubnou;
71 eplasat[cubnou]=true;
72 }
73 if(ok)
74 if((maxx-minx+1)*(maxy-miny+1)*(maxz-minz+1)==n)
75 {
76 out.println("0");
77 out.println((maxz-minz+1)+" "+(maxx-minx+1)+" "+(maxy-miny+1));
78 }
79 else
80 {
81 out.println("0");
82 out.println("0");
83 }
84 out.close();
85 }
86 }
40.5 Fibo
prof. Marinel erban, Liceul de Informatic , Ia³i
CAPITOLUL 40. ONI 2000 884
Se determin cel mai mare num r din ³irul Fibonacci care este mai mic sau egal cu num rul
dat. Acesta este primul num r din soluµie. Se determin cel mai mare num r din ³irul Fibonacci
care este mai mic sau egal cu diferenµa dintre num rul dat ³i primul num r din soluµie. Acesta
este al doilea num r din soluµie. Se repet acest algoritm pân când num rul r mas devine zero.
Se folosesc operaµiile de adunare, sc dere ³i comparare cu numere mari.
34 var fout:text;
35 i:LongInt;
36 begin
37 assign (fout, ’fib.out’); rewrite(fout);
38 i:=Nr;
39 repeat
40 while F[i]>n do dec(i);
41 writeln (fout, F[i]);
42 n:=n-F[i];
43 until n=0;
44 close(fout);
45 end;
46
47 begin
48 Citire;
49 Fibonacci;
50 Determina;
51 end.
15 char[] a=br.readLine().toCharArray();
16 int nx=a.length;
17 x=new int[nx];
18
19 for(i=0;i<a.length;i++) x[nx-1-i]=a[i]-’0’;
20
21 f[0]=nr2v(0);
22 f[1]=nr2v(1);
23 f[2]=nr2v(1);
24 for(k=3;k<=nf;k++) f[k]=suma(f[k-1],f[k-2]);
25
26 while(compar(x,nr2v(0))>0)
27 {
28 iy=maxFibo(x);
29 afisv(f[iy]);
30 x=scade(x,f[iy]);
31 }
32 out.close();
33 }
34
35 static int maxFibo(int[] nr)
36 {
37 int k;
38 for(k=1;k<=nf;k++) if (compar(f[k],nr)>0) break;
39 return k-1;
40 }
41
42 static int compar(int[] a, int[] b) //-1, 0, 1 ... a < = > b
43 {
44 int na=a.length;
45 int nb=b.length;
46 if(na>nb) return 1; else if(na<nb) return -1;
47
48 int i=na-1;
49 while((i>=0)&&(a[i]==b[i])) i--;
50 if(i==-1) return 0;
51 else if(a[i]>b[i]) return 1; else return -1;
52 }
53
54 static int[] scade(int[] x,int[] y) // z=x-y unde x>=y
55 {
56 int nx=x.length;
57 int ny=y.length;
58 int nz=nx;
59 int t,i;
60 int[] z=new int[nz];
61 int[] yy=new int[nz];
62 for(i=0;i<ny;i++) yy[i]=y[i];
63 t=0;
64 for(i=0;i<nz;i++)
65 {
66 z[i]=x[i]-yy[i]-t;
67 if(z[i]<0) {z[i]+=10; t=1;} else t=0;
68 }
69 if(z[nz-1]!=0) return z;
70 else
71 {
72 int[] zz=new int[nz-1];
73 for(i=0;i<nz-1;i++) zz[i]=z[i];
74 return zz;
75 }
76 }
77
78 static int[] suma(int[] x,int[] y)
79 {
80 int nx=x.length;
81 int ny=y.length;
82 int nz;
83 if(nx>ny) nz=nx+1; else nz=ny+1;
84 int t,i;
85 int[] z=new int[nz];
86 int[] xx=new int[nz];
87 int[] yy=new int[nz];
88 for(i=0;i<nx;i++) xx[i]=x[i];
89 for(i=0;i<ny;i++) yy[i]=y[i];
90 t=0;
CAPITOLUL 40. ONI 2000 888
91 for(i=0;i<nz;i++)
92 {
93 z[i]=xx[i]+yy[i]+t;
94 t=z[i]/10;
95 z[i]=z[i]%10;
96 }
97 if(z[nz-1]!=0) return z;
98 else
99 {
100 int[] zz=new int[nz-1];
101 for(i=0;i<nz-1;i++) zz[i]=z[i];
102 return zz;
103 }
104 }
105
106 static int[] nr2v(int nr)
107 {
108 int nrr=nr,nc=0,i;
109 while(nr!=0) { nc++; nr=nr/10; }
110 int[] nrv=new int[nc];
111 nr=nrr;
112 for(i=0;i<nc;i++) { nrv[i]=nr%10; nr=nr/10; }
113 return nrv;
114 }
115
116 static void afisv(int[] x)
117 {
118 int i;
119 for(i=x.length-1;i>=0;i--) out.print(x[i]);
120 out.println();
121 }
122 }
40.6 Kommando
prof. Marinel erban, Liceul de Informatic , Ia³i
Într-o cl dire cu h etaje sunt deµinuµi, la parter, câµiva prizonieri de c tre T terori³ti.
Fiecare etaj al cl dirii are m n camere identice. Fiecare camer are un cod numeric (nu neap rat
unic) exprimat printr-un num r din intervalul 0 255.
O trup de komando, format din K speciali³ti în luptele antitero, trebuie s elibereze prizo-
nierii. Trupa de komando este para³utat pe cl dire ³i încearc s ajung la parter. Se cunoa³te
locul x, y unde ecare membru al trupei a aterizat pe acoperi³.
Greutatea ec rui membru al trupei este exprimat în unit µi din intervalul 1 255. Un
membru al trupei poate trece "în jos" printr-o camer a cl dirii doar dac "greutatea lui trece
prin camera respectiv ", conform urm toarei deniµii.
Deniµie: Spunem c "a trece prin b" (a %% b) dac , în reprezentare binar , num rul de cifre
1 a lui a este mai mic sau egal cu num rul de cifre 1 a lui b ³i cifrele 1 ale lui a sunt comune cu
unele cifre 1 ale lui b.
Exemplu: "44 trece prin 174" (44 %% 174) deoarece
44 = 00101100
174 = 10101110
Pentru detectarea unei camere prin care s poat trece, un membru al trupei de komando se
poate, eventual, deplasa cu un "pas" în cele 8 direcµii al turate poziµiei curente în care a ajuns prin
aterizare sau trecerea "în jos". Prin "pas"-ul respectiv se ajunge la una din cele 8 camere vecine.
Prizonierii pot eliberaµi doar dac la parter ajung minim T membri ai trupei de komando.
Cerinµ :
S se determine dac prizonierii pot eliberaµi sau nu, precum ³i num rul de membri ai trupei
de komando care pot s ajung la parter.
Date de intrare
Fi³ierul text KOMMANDO.IN are structura urm toare:
a pe prima linie valorile m, n, h, K , T desp rµite prin câte un spaµiu, cu semnicaµiile descrise
mai sus;
a urm toarele h linii reprezint codurile celor m n camere ale unui etaj, desp rµite prin câte
un spaµiu;
CAPITOLUL 40. ONI 2000 889
Restricµii ³i preciz ri
a 2 & m, n, h & 35 1 & xi & m 1 & yi &n
a 1 & T, K, Gi & 255
a 0 & cijk & 255
a Toate valorile sunt întregi.
Exemplu:
KOMMANDO.IN KOMMANDO.OUT
55532 DA
0 0 0 0 0 0 0 33 0 0 0 02 0000030 00000 2
00000 01 0000 44 2 0 0 0 0 0 3 0 0 0 0 0 0
0 0 0 0 0 11 0 0 0 0 0 0 2 22 0 0 0 0 0 3 0 0 0 0 0
00000 00 0000 66 2 0 0 0 0 0 7 0 15 0 0 0 0
00000 00 0000 00 0000000 00000
122
233
344
Timp maxim de execuµie pe test: 5 secunde
În ³ierul de intrare etajele sunt de sus în jos (primul etaj este lâng acoperi³)!
Pentru ecare soldat se face o parcurgere în adâncime (folosind recursivitatea) sau o parcurgere
în l µime (eventual folosind o structur de tip coad ) pentru un algoritm de tip ll (umplere).
4
5 Const DimMax = 35;
6 MaxK = 200;
7 Dx: Array[1..9] Of -1..1 = (0, 0, 1,1,1,0,-1,-1,-1);
8 Dy: Array[1..9] Of -1..1 = (0,-1,-1,0,1,1, 1, 0,-1);
9
10 Type Dim = 0..DimMax+1;
11 Komando = Record
12 x, y: Dim; {locul de pornire de pe acoperis}
13 Greu: Byte; {greutatea}
14 Ajuns: Boolean; {initial FALSE pentru toti}
15 End;
16 Cladire = Array[Dim, Dim, Dim] Of Byte;
17
18 Var c : Cladire;
19 Com : Array[1..MaxK] Of Komando;
20 ContorAjunsi: Byte;
21 m, n, h : Byte;
22 Kapa, K, T : Byte;
23 g : Text;
24 a, b : Array[0..DimMax+1, 0..DimMax+1] Of Byte;
25
26 Procedure Citeste_Date;
27 Var f: Text;
28 i, j, l: Byte;
29 Begin
30 Assign(f, ’kommando.in’); Reset(f);
31 ReadLn(f, m, n, h, K, T);
32 For i := 1 To h Do {citeste un etaj}
33 Begin
34 For j := 1 To m Do {citeste m linii}
35 For l := 1 To n Do {citeste n coloane}
36 Read(f, c[j, l, i]);
37 ReadLn(f)
38 End;
39 For i := 1 To K Do {citeste cei K Komandisti}
40 With Com[i] Do
41 Begin
42 ReadLn(f, Greu, x, y);
43 Ajuns := False
44 End;
45 Close(f)
46 End;
47
48 Procedure Trece;
49 Var Niv, i, j, xx: Byte;
50 Begin
51 FillChar(a, SizeOf(a), 0);
52 a[Com[Kapa].x, Com[Kapa].y] := 1;
53 For Niv := 2 To h Do
54 Begin
55 FillChar(b, SizeOf(b), 0);
56 For i := 1 To m Do
57 For j := 1 To n Do
58 If a[i, j] = 1 Then
59 For xx := 1 To 9 Do
60 If c[i+Dx[xx], j+Dy[xx], Niv-1] and
61 Com[Kapa].greu = Com[Kapa].greu
62 Then
63 b[i+Dx[xx], j+Dy[xx]] := 1;
64 a := b;
65 End;
66 For i := 1 To m Do
67 For j := 1 To n Do
68 If a[i, j] = 1 Then
69 Com[Kapa].Ajuns := true;
70 End;
71
72 Begin
73 Citeste_Date;
74 Assign(g, ’KOMMANDO.OUT’); ReWrite(g);
75 For Kapa := 1 To K Do {pentru fiecare din cei K Komandisti}
76 Trece; {plec de pe nivelul 1}
77 For Kapa := 1 To K Do {contorizez cei ajunsi}
78 If Com[Kapa].Ajuns Then Inc(ContorAjunsi);
79 If ContorAjunsi >= T Then WriteLn(g, ’DA’)
CAPITOLUL 40. ONI 2000 893
73 for(i=-1;i<=1;i++)
74 for(j=-1;j<=1;j++)
75 if((x+i>=1)&&(x+i<=m)&&(y+j>=1)&&(y+j<=n))
76 if(trece(G[soldat],codCamera[etaj][x+i][y+j]))
77 coboara(soldat, etaj+1, x+i, y+j);
78 }
79
80 static boolean trece(int a, int b) // a trece prin b ?
81 {
82 int k;
83 for(k=0;k<=7;k++)
84 if(((1<<k)&a)!=0) // pozitia k in a este 1
85 if(((1<<k)&b)==0) // pozitia k in b este 0
86 return false;
87 return true;
88 }
89
90 static void afisare() throws IOException
91 {
92 out=new PrintWriter(
93 new BufferedWriter(new FileWriter("kommando.out")));
94 if(ns>=T) out.println("DA"); else out.println("NU");
95 out.println(ns);
96 out.close();
97 }
98 }
47 for(etaj=1;etaj<=h;etaj++)
48 for(x=1;x<=m;x++)
49 for(y=1;y<=n;y++)
50 {
51 st.nextToken();
52 codCamera[etaj][x][y]=(int)st.nval;
53 }
54
55 for(k=1;k<=K;k++)
56 {
57 st.nextToken(); G[k]=(int)st.nval;
58 st.nextToken(); xk[k]=(int)st.nval;
59 st.nextToken(); yk[k]=(int)st.nval;
60 }
61 }
62
63 static void rezolvare() throws IOException
64 {
65 int soldat;
66 for(soldat=1;soldat<=K;soldat++)
67 {
68 curatTraseu();
69 aajunslaparter=false;
70 coboara(soldat,1,xk[soldat],yk[soldat]);
71 if(aajunslaparter) ns++;
72 }
73 }
74
75 static void curatTraseu()
76 {
77 int etaj, x, y;
78 for(etaj=1;etaj<=h;etaj++)
79 for(x=1;x<=m;x++)
80 for(y=1;y<=n;y++)
81 traseu[etaj][x][y]=false;
82 }
83
84 static void coboara(int soldat, int etaj, int x, int y)
85 {
86 if((x<1)||(x>m)||(y<1)||(y>n)) return;
87 if(aajunslaparter) return;
88 if(etaj==h) {aajunslaparter=true; return;}
89 if(traseu[etaj][x][y]) return; // a mai trecut pe aici
90 traseu[etaj][x][y]=true;
91
92 int i,j;
93 for(i=-1;i<=1;i++)
94 for(j=-1;j<=1;j++)
95 if((x+i>=1)&&(x+i<=m)&&(y+j>=1)&&(y+j<=n))
96 if(trece(G[soldat],codCamera[etaj][x+i][y+j]))
97 coboara(soldat, etaj+1, x+i, y+j);
98 }
99
100 static boolean trece(int a, int b) // a trece prin b ?
101 {
102 int k;
103 for(k=0;k<=7;k++)
104 if(((1<<k)&a)!=0) // pozitia k in a este 1
105 if(((1<<k)&b)==0) // pozitia k in b este 0
106 return false;
107 return true;
108 }
109
110 static void afisare() throws IOException
111 {
112 out=new PrintWriter(
113 new BufferedWriter(new FileWriter("kommando.out")));
114 if(ns>=T) out.println("DA"); else out.println("NU");
115 out.println(ns);
116 out.close();
117 }
118 }
77 for(y=1;y<=n;y++)
78 if(ok[etaj][x][y]) coboara(soldat,etaj,x,y);
79 if(aajunslaparter) ns++;
80 }
81 }
82
83 static void coboara(int soldat, int etaj, int x, int y)
84 {
85 if(etaj==h) {aajunslaparter=true; return;}
86 int i,j;
87 for(i=-1;i<=1;i++)
88 for(j=-1;j<=1;j++)
89 if((x+i>=1)&&(x+i<=m)&&(y+j>=1)&&(y+j<=n))
90 if(trece(G[soldat],codCamera[etaj][x+i][y+j]))
91 ok[etaj+1][x+i][y+j]=true;
92 }
93
94 static boolean trece(int a, int b) // a trece prin b ?
95 {
96 int k;
97 for(k=0;k<=7;k++)
98 if(((1<<k)&a)!=0) // pozitia k in a este 1
99 if(((1<<k)&b)==0) // pozitia k in b este 0
100 return false;
101 return true;
102 }
103
104 static void curatTraseu()
105 {
106 int etaj, x, y;
107 for(etaj=1;etaj<=h;etaj++)
108 for(x=1;x<=m;x++)
109 for(y=1;y<=n;y++)
110 ok[etaj][x][y]=false;
111 }
112
113 static void afisare() throws IOException
114 {
115 out=new PrintWriter(
116 new BufferedWriter(new FileWriter("kommando.out")));
117 if(ns>=T) out.println("DA"); else out.println("NU");
118 out.println(ns);
119 out.close();
120 }
121 }
28 }
29
30 static void citire() throws IOException
31 {
32 int x,y,etaj,k;
33 st=new StreamTokenizer(
34 new BufferedReader(new FileReader("10.in")));
35 st.nextToken(); m=(int)st.nval;
36 st.nextToken(); n=(int)st.nval;
37 st.nextToken(); h=(int)st.nval;
38 st.nextToken(); K=(int)st.nval;
39 st.nextToken(); T=(int)st.nval;
40
41 codCamera=new int[h+1][m+1][n+1];
42 ok=new boolean[h+1][m+1][n+1];
43 traseu=new boolean[h+1][m+1][n+1];
44
45 xk=new int[K+1];
46 yk=new int[K+1];
47 G=new int[K+1];
48
49 for(etaj=1;etaj<=h;etaj++)
50 for(x=1;x<=m;x++)
51 for(y=1;y<=n;y++)
52 {
53 st.nextToken();
54 codCamera[etaj][x][y]=(int)st.nval;
55 }
56
57 for(k=1;k<=K;k++)
58 {
59 st.nextToken(); G[k]=(int)st.nval;
60 st.nextToken(); xk[k]=(int)st.nval;
61 st.nextToken(); yk[k]=(int)st.nval;
62 }
63 }
64
65 static void rezolvare() throws IOException
66 {
67 int soldat,etaj,x,y;
68 for(soldat=1;soldat<=K;soldat++)
69 {
70 curatTraseu();
71 aajunslaparter=false;
72 etaj=0;
73 x=xk[soldat];
74 y=yk[soldat];
75 coboara(soldat,etaj,x,y);
76 for(etaj=1;etaj<=h;etaj++)
77 for(x=1;x<=m;x++)
78 for(y=1;y<=n;y++)
79 if(ok[etaj][x][y]) coboara(soldat,etaj,x,y);
80 if(aajunslaparter) ns++;
81 }
82 }
83
84 static void coboara(int soldat, int etaj, int x, int y)
85 {
86 if(etaj==h) {aajunslaparter=true; return;}
87 int i,j;
88 for(i=-1;i<=1;i++)
89 for(j=-1;j<=1;j++)
90 if((x+i>=1)&&(x+i<=m)&&(y+j>=1)&&(y+j<=n))
91 if(!traseu[etaj+1][x+i][y+j])
92 {
93 traseu[etaj+1][x+i][y+j]=true;
94 if(trece(G[soldat],codCamera[etaj+1][x+i][y+j]))
95 ok[etaj+1][x+i][y+j]=true;
96 }
97 }
98
99 static boolean trece(int a, int b) // a trece prin b ?
100 {
101 int k;
102 for(k=0;k<=7;k++)
103 if(((1<<k)&a)!=0) // pozitia k in a este 1
CAPITOLUL 40. ONI 2000 900
Un pic de matematic !
A.1 ...
...
A.1.2 Exemple
...
902
Anexa B
Un pic de programare!
B.1 ...
...
B.1.2 Exemple
...
903
Glosar
19
10 , 573 directie, 80
'¯n', 13 distanµa Manhattan, 377
=, 442 doi pointeri, 435
³ir al frecvenµelor, 678
³ir circular, 655 emplace_back, 53
empty(), 478, 581
1LL, 358
end(), 53, 186, 335, 336, 338, 358, 360, 404,
1LL $$ 62, 13
475, 478, 514
accumulate, 401 erase, 186, 336, 514
aib, 475 exponenµiere logaritmic , 642
AIB 2D, 473 rst, 53, 76, 338, 478, 581
algorimul lui Euclid, 649 fracµie continu , 367
algoritm de interclasare, 515 freopen, 11
algoritm de tip mars, 354 front(), 358, 478
algoritm de tip greedy, 473
algoritmul lui Eratostene, 534 gcd, 307
algoritmul lui Euclid, 367 getchar(), 438
assert, 59 greedy, 478
auto, 41, 307, 309, 338, 366, 382, 395
heap, 25
auto&, 309, 338, 419
I.d.k.:
back(), 336, 358, 404, 478 I don't know who the author is., v
begin(), 53, 90, 186, 335, 336, 338, 358, 360, ifndef, 204
404, 475, 478, 514 ifstream, 13
binarySearch, 76 inline, 150
bitset, 132, 454, 476 insert, 186, 358
bool, 186, 359, 360, 395, 445, 514 int32_t, 335, 336, 358
bool operator, 475 int64_t, 336
brute-force, 349 isdigit, 438
BUF_SIZE 1 $$ 17, 25 iterator, 186
c utare binar , 3, 26, 27, 113, 115, 354, 374, lambda, 90, 319
405, 416, 429, 434, 473, 502, 516, lazy, 53
564, 655 liniarizare matrice, 648
char, 401, 404, 438 liniarizarea matricei, 480
ciclu, 648 long long, 13
cin vs scanf, 11 lower_bound, 41, 514
ciurul lui Eratostene, 330, 427, 451, 454, make_pair, 39, 581
530, 583, 628 matrice, 372
clear(), 338 mediana ³irului, 669
cmmdc, 413, 414 memset, 116, 139, 296
const, 360, 382, 419, 445, 475 min, 438
const auto&, 475 min_element, 401, 404
count, 338 multiplu comun, 649
cout vs ofstream, 16
cout vs printf, 11 nth_element, 517
num rul de divizori, 254
deque, 478 numeric_limits, 336
descompunere în factori primi, 254, 330 <int>::max(), 336
904
GLOSAR 905
[2] Andreica M.I.; Elemente de algoritmic - probleme ³i soluµii, Cibernetica MC, 2011
[3] Andonie R., Gârbacea I.; Algoritmi fundamentali, o perspectiv C++, Ed. Libris, 1995
[5] Bell D., Perr M.; Java for Students, Second Edition, Prentice Hall, 1999
[7] Cerchez, E., erban, M.; Informatic - manual pentru clasa a X-a., Ed. Polirom, 2000
[8] Cerchez, E.; Informatic - Culegere de probleme pentru liceu, Ed. Polirom, 2002
[9] Cerchez, E., erban, M.; Programarea în limbajul C/C++ pentru liceu, Ed. Polirom, 2005
[10] Cori, R.; Lévy, J.J.; Algorithmes et Programmation, Polycopié, version 1.6;
http://w3.edu.polytechnique.fr/informatique/
[11] Cormen, T.H., Leiserson C.E., Rivest, R.L.; Introducere în Algoritmi, Ed Agora, 2000
[12] Cormen, T.H., Leiserson C.E., Rivest, R.L.; Pseudo-Code Language, 1994
[13] Cristea, V.; Giumale, C.; Kalisz, E.; Paunoiu, Al.; Limbajul C standard, Ed. Teora, Bucure³ti,
1992
[16] Giumale C., Negreanu L., C linoiu S.; Proiectarea ³i analiza algoritmilor. Algoritmi de sortare,
Ed. All, 1997
[18] Knuth, D.E.; Arta program rii calculatoarelor, vol. 1: Algoritmi fundamentali, Ed. Teora,
1999.
[19] Knuth, D.E.; Arta programarii calculatoarelor, vol. 2: Algoritmi seminumerici, Ed. Teora,
2000.
[20] Knuth, D.E.; Arta programarii calculatoarelor, vol. 3: Sortare ³i c utare, Ed. Teora, 2001.
[21] Knuth, D.E.; The art of computer programming, vol. 4A: Combinatorial algorithms, Part 1,
Addison Wesley, 2011.
[22] Lambert,K. A., Osborne,M.; Java. A Framework for Programming and Problem Solving,
PWS Publishing, 1999
[24] Livovschi, L.; Georgescu H.; Analiza ³i sinteza algoritmilor. Ed. Enciclopedic , Bucure³ti,
1986.
906
BIBLIOGRAFIE 907
[26] Od gescu, I., Smeureanu, I., tef nescu, I.; Programarea avansat a calculatoarelor personale,
Ed. Militar , Bucure³ti 1993
[27] Od gescu, I.; Metode ³i tehnici de programare, Ed. Computer Lobris Agora, Cluj, 1998
[28] Popescu Anastasiu, D.; Puncte de articulaµie ³i punµi în grafuri, Gazeta de Informatic nr.
5/1993
[35] Tomescu, I.; Probleme de combinatoric ³i teoria grafurilor, Editura Didactic ³i Pedagogic ,
Bucure³ti, 1981
[36] Tomescu, I.; Leu, A.; Matematic aplicat în tehnica de calcul, Editura Didactic ³i Pedago-
gic , Bucure³ti, 1982
[37] Tudor, S.; Informatic - prolul real intensiv, varianta C++; Editura L&S, Bucure³ti, 2004
[38] Tudor, S.; Hutanu, V,; Informatic intensiv; Editura L&S, Bucure³ti, 2006
[40] Vi³inescu, R.; Vi³inescu, V.; Programare dinamic - teorie ³i aplicaµii; GInfo nr. 15/4 2005
[41] Vlada, M.; Conceptul de algoritm - abordare modern , GInfo, 13/2,3 2003
[43] Vlada, M.; Gândirea Algoritmic - O Filosoe Modern a Matematicii ³i Informaticii, CNIV-
2003, Editura Universit µii din Bucure³ti, 2003
[44] Weis, M.A.; Data structures and Algorithm Analysis, Ed. The Benjamin/Cummings Pu-
blishing Company. Inc., Redwoods City, California, 1995.
[46] Wirth N.; Algorithms + Data Structures = Programs, Prentice Hall, Inc 1976
909