Professional Documents
Culture Documents
cls5 2023 10
cls5 2023 10
Olimpiada - cls5
2023-10
PROBLEME DE INFORMATICĂ
date la olimpiade
OJI + ONI
ı̂n
Dacă ştii să rezolvi problemele date ı̂n ultimii 10-20 de ani
atunci vei şti să rezolvi problemele care se vor da ı̂n acest an!
”O imagine valorează
cât 1000 de cuvinte!” 1
x1 x1
x3 x3
x2 x2
elevii f = aleg ”şeful” elevi
ı̂n clasă ı̂n clasă
fac echipe echipei
y1 y1
y3 y3
y2 y2
1
I.d.k.: ”I don’t know who the author is.”
Dedication
( in ascending order! )
2
https://www.femalefirst.co.uk/books/carol-lynne-fighter-1034048.html
3
https://otiliaromea.bandcamp.com/track/dor-de-el
4
https://en.wikipedia.org/wiki/To_be,_or_not_to_be
5
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 fiecare 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!.
6
Sunt convins că este important să studiem cu atenţie cât mai multe probleme rezolvate! . Cred
că sunt utile şi primele versiuni ale acestor cărţi ... ı̂n care sunt prezentate numai enunţurile şi
indicaţiile ”oficiale” de rezolvare. Acestea se găsesc ı̂n multe locuri; aici ı̂ncerc să le pun pe ”toate
la un loc”! Fiecare urcă spre vârf ... cât poate! Sunt multe poteci care duc spre vârf iar această
carte este ... una dintre ele!
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
7 8
dificilă! :-) Vezi, de exemplu, IOI2020 şi IOI2019 , IOI2015 . (Numai GCC a fost mereu!)
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
9
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 fi posibil ... aşa că, de această dată, anii sunt
ı̂n ordine ... descrescătoare! :-)
”Codurile sursă” sunt cele ”oficiale” (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
10
disponibil şi, oricum, calculatoarele folosite la olimpiade ı̂nainte de 2010 erau ceva mai ’slabe’ şi
iii
În perioada 2017-2020 cele mai puternice calculatoare din lume au fost: ı̂n noiembrie 2017
11
ı̂n China, ı̂n noiembrie 2019 ı̂n SUA şi ı̂n iunie 2020 ı̂n Japonia. În iunie 2022 ”Frontier”
12
depăşeşte pragul ”exascale”! (1.102 Exaflop/s). ”Peta” a fost depăşit ı̂n 2008, ”tera” ı̂n 1997,
13
”giga” ı̂n 1972. . Pentru ce a fost mai ı̂nainte, vezi https://en.wikipedia.org/wiki/Li
st_of_fastest_computers.
14
O mică observaţie: ı̂n 2017 a fost prima ediţie a olimpiadei EJOI ı̂n Bulgaria şi ... tot
15
ı̂n Bulgaria a fost şi prima ediţie a olimpiadei IOI ı̂n 1989. Dar ... prima ediţie a olimpiadei
16
IMO (International Mathematical Olympiad) a fost ı̂n România ı̂n 1959. Tot ı̂n România s-au
ţinut ediţiile din anii 1960, 1969, 1978, 1999 şi 2018. Prima ediţie a olimpiadei BOI (Balkan
Olympiad in Informatics) a fost ı̂n România ı̂n 1993 la Constanţa. Prima ediţie a olimpiadei
CEOI (Central-European Olympiad in Informatics) a fost ı̂n România ı̂n 1994 la Cluj-Napoca.
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!). Acum, ı̂n martie 2022, am ı̂nceput şi
redactarea unei culegeri de probleme date la bacalaureat ı̂n ultimii câţiva ani (câţi voi putea!).
Î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) sigur nu au nevoie de ajutorul meu! Se descurcă singuri!
”ALGORITMI utili la olimpiadele de informatică”, separat pentru gimnaziu şi liceu, sper să
fie de folos, aşa cum cred că sunt [1] - [28], [34] - [47], [57] - [83], ... şi multe alte cărţi şi site-uri!.
Ar fi interesant să descoperim noi ı̂nşine cât mai mulţi algoritmi ... ı̂n loc să-i ı̂nvăţăm pur şi
simplu!
O altă mică observaţie: ce am strâns şi am scris ı̂n aceste
cărţi se adresează ”ı̂ncepătorilor” interesaţi de aceste teme! Nu se
adresează ”avansaţilor” şi nici cârcotaşilor! Sunt evidente sursele
”de pe net” (şi locurile ı̂n care au fost folosite); cred că nu sunt
necesare ”ghilimele anti-plagiat” şi precizări la fiecare pas!
Şi un ultim gând: criticile şi sfaturile sunt utile dacă au valoare
reală! Dacă sunt numai aşa ... cum critică lumea la un meci de
fotbal ... sau cum, pe bancă ı̂n parc, unul ”ı̂şi dă cu părerea”
despre rezolvarea problemelor economice ale ţării ... atunci ... !!!
17
”I’m only responsible for what I say, not for what you understand.”
Adrese interesante (rezultatele elevilor români):
https://stats.ioinformatics.org/halloffame/
https://stats.ioinformatics.org/tasks/
http://stats.ioinformatics.org/results/ROU
11
https://www.top500.org/lists/top500/2022/06/
12
https://en.wikipedia.org/wiki/Metric_prefix/
13
https://en.wikipedia.org/wiki/Computer_performance_by_orders_of_magnitude
14
https://ejoi.org/about/
15
https://stats.ioinformatics.org/olympiads/
16
https://en.wikipedia.org/wiki/International_Mathematical_Olympiad
17
https://www.facebook.com/johnwayne/photos/a.156450431041410/2645523435467418/?type=3
”Acknowledgements”
and
and/or
suggestions!
18
I.d.k.: ”I don’t know who the author is.”
19
donation/donaţie:
. name: RABAEA AUREL ADRIAN, IBAN: RO22BRDE060SV11538970600, SWIFT: BRDEROBUXXX
v
Despre autor
20
nume: Răbâea Aurel-Adrian, 18.03.1953 - ...
vi
Dhawan Sanjeev, Kulvinder Singh, Eduard-Marius Craciun, Adrian Răbâea, Amit Batra;
Next-Cart Recommendation by Utilizing Personalized Item Frequency Information in Online Web
Portals, Neural Processing Letters, 2023; https://doi.org/10.1007/s11063-023-11207-2
https://scholar.google.com/citations?user=-sSE_1wAAAAJ&hl=en
https://www.scopus.com/authid/detail.uri?origin=resultslist&authorId=56122389200&zone=
http://www.facebook.com/adrian.rabaea
Cuprins
Prefaţă iii
Cuprins viii
Lista figurilor xv
2 OJI 2022 13
2.1 ceas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.1.1 Indicaţii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.1.2 *Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.1.3 Rezolvare detaliată . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.2 sss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.2.1 Indicaţii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.2.2 *Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.2.3 Rezolvare detaliată . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4 OJI 2020 32
4.1 cartonase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.1.1 Indicaţii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.1.2 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.1.3 *Rezolvare detaliată . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.2 tai . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.2.1 Indicaţii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
viii
4.2.2 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.2.3 *Rezolvare detaliată . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5 OJI 2019 48
5.1 Aur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
5.1.1 Indicaţii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
5.1.2 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
5.1.3 Rezolvare detaliată . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.2 Cartele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
5.2.1 Indicaţii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
5.2.2 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
5.2.3 Rezolvare detaliată . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
6 OJI 2018 71
6.1 Patrate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
6.1.1 Indicaţii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
6.1.2 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
6.1.3 *Rezolvare detaliată . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
6.2 forus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
6.2.1 Indicaţii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
6.2.2 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
6.2.3 *Rezolvare detaliată . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
7 OJI 2017 83
7.1 numere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
7.1.1 Indicaţii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
7.1.2 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
7.1.3 *Rezolvare detaliată . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
7.2 robot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
7.2.1 Indicaţii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
7.2.2 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
7.2.3 *Rezolvare detaliată . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
8 OJI 2016 96
8.1 colier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
8.1.1 Indicaţii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
8.1.2 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
8.1.3 *Rezolvare detaliată . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
8.2 Palindrom . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
8.2.1 Indicaţii de rezolvare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
8.2.2 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
8.2.3 *Rezolvare detaliată . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
Index 417
Bibliografie 419
6.1 Patrate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
6.2 forus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
7.1 Numere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
7.2 Robot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
xv
25.1 greieri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
xviii
Lista programelor
xix
7.1.3 numere jakab.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
7.1.4 numere sandor.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
7.1.5 numere vladescu.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
7.2.1 robot cerchez.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
7.2.2 robot cerchez ok.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
7.2.3 robot jakab.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
8.1.1 colier gina.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
8.1.2 colier Marius.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
8.1.3 colier Miana.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
8.1.4 colier sanda.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
8.2.1 palindrom Marius.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
8.2.2 palindrom Sanda.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
9.1.1 cuart dl.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
9.1.2 cuart dt.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
9.1.3 cuart la.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
9.1.4 cuartAI.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
9.1.5 cuartAI ecuatie.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
9.2.1 speciale dc.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
9.2.2 speciale fin dt.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
9.2.3 speciale SJ.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
9.2.4 specialedl.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
10.1.1 mAna.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
10.1.2 mCarmen.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
10.1.3 mCristina.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
10.1.4 mMarilena.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
10.1.5 mRaluca.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
10.2.1 p s CM.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
10.2.2 p v CM.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
10.2.3 pAna.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
10.2.4 pCristina.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
10.2.5 pGina.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
10.2.6 pMarilena.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
10.2.7 pRaluca.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
11.1.1 bete OFICIAL.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
11.1.2 bete vectori.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
11.2.1 chibrituri OFICIAL.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
11.2.2 chibrituri v.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
12.1.1 alice CM2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
12.1.2 alice CS.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
12.1.3 alice SJ.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
12.2.1 p100 AS.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
12.2.2 p100 CL.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
12.2.3 p100 CM1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
12.2.4 p100 CM2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
12.2.5 p100 CS.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
12.2.6 p100 DT.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
12.2.7 p100 JIT.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
13.1.1 CARACTER.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
13.1.2 magic DM.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
13.1.3 MAGIC S.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
13.1.4 magicAna.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
13.1.5 MAGICDT3.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
13.2.1 A1 Numer.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
13.2.2 D NUMERU.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
13.2.3 S Numeru.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
14.1.1 sir.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
14.1.2 sirana.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
14.1.3 SIRcris.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
14.1.4 SIRcris2.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
14.1.5 SIRcris2.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
14.1.6 SIRVECT.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
14.2.1 Ana.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
14.2.2 Carmen.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
14.2.3 Cris1.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
14.2.4 Cris2.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
14.2.5 Cris3.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
14.2.6 Dana.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
15.1.1 5 cadouri.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
15.2.1 5 legos.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
15.3.1 5 patinaj.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
19.1.1 copii cpp.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
19.1.2 Copii - Etapa nr. 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
19.1.3 Copii - Etapa nr. 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
19.1.4 Copii - Etapa nr. 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
19.2.1 numere cpp.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
19.2.2 Numere - Etapa nr. 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
19.2.3 Numere - Etapa nr. 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
19.2.4 Numere - Etapa nr. 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
19.2.5 Numere - Etapa nr. 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
19.2.6 Numere - Etapa nr. 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
19.2.7 Numere - Etapa nr. 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
19.3.1 trio cpp.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
19.3.2 Trio - Etapa nr. 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236
19.3.3 Trio - Etapa nr. 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
19.3.4 Trio - Etapa nr. 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
19.3.5 Trio - Etapa nr. 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
21.1.1 prime cp.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
21.1.2 prime em.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
21.1.3 prime fara ciur sn.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
21.2.1 robot adriana.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254
21.2.2 robot cp.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
21.2.3 robot ema.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
21.2.4 robot-JT.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
21.3.1 roua cardas.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
21.3.2 roua cp.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
21.3.3 roua jt.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
22.1.1 norocos.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
22.2.1 oglinda.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
22.3.1 perechi.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
23.1.1 iepuras 1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
23.1.2 iepuras 2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
23.1.3 iepuras 3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
23.1.4 iepuras 4.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
23.1.5 iepuras 5.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
23.1.6 iepuras 6.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
23.2.1 inventie 1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
23.2.2 inventie 2cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
23.2.3 inventie 3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
23.2.4 inventie 4 20p.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290
23.2.5 inventie 5 45p.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
23.2.6 inventie 6.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
23.2.7 inventie 7.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
23.2.8 inventie 8 35p.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294
23.3.1 mesaj 1.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
23.3.2 mesaj 2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298
23.3.3 mesaj 3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
23.3.4 mesaj 4.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
23.3.5 mesaj 5.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
23.3.6 mesaj 6.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304
23.3.7 mesaj 7.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
24.1.1 2048.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
24.1.2 2048A.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
24.1.3 2048F.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
24.1.4 2048G.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
24.1.5 2048L.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
24.1.6 2048R.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
24.2.1 babilon.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
24.2.2 babilonA.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
24.2.3 babilonC.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
24.2.4 babilonL.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320
24.3.1 iepurasi AI.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
24.3.2 iepurasi CS.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
24.3.3 iepurasi gina.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
24.3.4 iepurasi lucia.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
24.3.5 iepurasiM.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
26.1.1 culegere 2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336
26.1.2 culegere 3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336
26.2.1 culori 1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
26.2.2 culori 2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
26.3.1 stele 1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
26.3.2 stele 2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
26.3.3 stele 3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
27.1.1 fagure.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
27.2.1 GOE.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
27.3.1 papusa.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
28.1.1 cluburi CS.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
28.1.2 cluburi fara vectori.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
28.1.3 cluburi SG.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
28.2.1 domino AS 1.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
28.2.2 domino AS 2.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361
28.2.3 domino CM.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361
28.2.4 domino CS.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
28.2.5 domino SG.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363
28.3.1 MAX CM.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
28.3.2 MAX CS.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
28.3.3 MAX SG.CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368
B.1.1 sss1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
B.1.2 sss2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
D.4.1 exponentiere rapida1.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
D.4.2 exponentiere rapida2.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402
D.4.3 exponentiere rapida3.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
D.4.4 exponentiere rapida MOD.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
D.5.1 exponentiere naiva MOD.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
D.5.2 exponentiere rapida MOD.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
D.6.1 secventa cod.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406
E.2.1 cautare binara-v1-iterativ.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
E.2.2 cautare binara-v1-recursiv.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
E.3.1 cautare binara-v2-iterativ.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410
E.3.2 cautare binara-v2-recursiv.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
E.4.1 cautare binara-v3-iterativ.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412
E.4.2 cautare binara-v3-recursiv.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414
Part I
1
Capitolul 1
OJI 2023
1.1 aeriana
Problema 1 - Aeriana 100 de puncte
O companie aeriană are planificate N zboruri. Fiecare zbor are asociate câte şase numere
naturale cu următoarea semnificaţie: primul număr A1 identifică aeroportul de decolare, cel de-al
doilea număr A2 identifică aeroportul de aterizare, următoarele patru numere naturale H1, M1, H2
şi M2, reprezintă ı̂n ordine ora şi minutul decolării, respectiv ora şi minutul aterizării. Aterizarea
poate să fie ı̂n ziua curentă sau ı̂n ziua următoare.
Un zbor poate să dureze maximum 23 de ore şi 59 de minute. De exemplu, pentru H1 = 10,
M1 = 5, H2 = 15, M2 = 20 aterizarea are loc ı̂n aceeaşi zi cu decolarea (zborul durează 5 ore şi
15 minute), iar pentru H1 = 23, M1 = 5, H2 = 1, M2 = 15 aterizarea are loc ı̂n ziua următoare
(zborul durează 2 ore şi 10 minute).
Un virus informatic s-a infiltrat ı̂n sistemele de calcul ale companiei şi a inversat momentul
de decolare cu cel de aterizare al zborurilor pe care le consideră speciale. Un zbor este considerat
special de către acest virus ı̂n cazul ı̂n care codul aeroportului de decolare, A1, este un număr
prim, iar codul aeroportului de aterizare, A2, se divide cu suma cifrelor lui A1.
Cerinţe
Cunoscându-se numărul de zboruri N şi datele fiecăruia, ı̂nainte de intervenţia virusului, să se
determine:
Date de intrare
Fişierul aeriana.in conţine pe prima linie valoarea C (numărul cerinţei, poate fi 1 sau 2), pe
a doua linie valoarea N (numărul de zboruri). Pe fiecare dintre următoarele N linii sunt câte şase
numere naturale A1, A2, H1, M1, H2, M2, ı̂n această ordine, despărţite prin câte un spaţiu, cu
semnificaţia din enunţ.
Date de ieşire
Fişierul aeriana.out va conţine pe prima linie două numere naturale separate printr-un spaţiu,
reprezentând numărul de ore şi respectiv numărul de minute ale zborului de durată maximă, ı̂n
condiţiile cerinţei specificate.
2
CAPITOLUL 1. OJI 2023 1.1. AERIANA 3
# Punctaj Restricţii
1 19 C 1 şi toate zborurile se desfăşoară ı̂n aceeaşi zi
2 17 C 1, M 1 0, M 2 0 pentru toate zborurile
3 17 C 1, fără alte precizări
4 47 C 2
Exemple:
Avem două zile consecutive. Decolarea se face ı̂n mod obligatoriu ı̂n prima zi. Aterizarea poate
să fie ı̂n prima zi sau ı̂n a doua zi.
Trebuie să fim atenţi la valorile datelor de intrare! Observăm că N poate avea valoarea 1000
şi A1 poate avea valoarea 1 000 000 000. Un miliard ”ı̂ncape” ı̂ntr-un int dar o valoare de 1000
de miliarde nu ”ı̂ncape” decât ı̂ntr-un long long.
Şi o ultimă observaţie: este util să ”ı̂mpănăm ” programul cu mesaje care să afişeze pe ecran
valorile intermediare obţinute! ı̂n acest fel putem să observăm repede dacă am greşit pe undeva.
Iar când am terminat şi este totul ok, vom comenta aceste mesaje (nu este bine să le ştergem
pentru că, din greşeală, putem să ştergem ce nu trebuie!).
//ifstream fin("aeriana.in");
//ifstream fin("aeriana1.in");
//ifstream fin("aeriana2.in");
//ifstream fin("..//..//teste_aeriana//input.01-aeriana");
ifstream fin("../../teste_aeriana/input.29-aeriana");
ofstream fout("aeriana.out");
int C; // cerinta
int N; // nr de zboruri
int A1, A2; // aeroporturi
int H1, H2; // ora decolare/aterizare
int M1, M2; // minut decolare/aterizare
minut1=H1*60+M1;
minut2=H2*60+M2;
//cout<<"minut1 = "<<minut1<<" minut2 = "<<minut2<<endl;
if(minut2==0) minut2=24*60;
//cout<<"minut1 = "<<minut1<<" minut2 = "<<minut2<<endl;
rora=max1/60;
rminut=max1%60;
//cout<<rora<<" "<<rminut;
fout<<rora<<" "<<rminut;
return 0;
} // sf calcul1()
fin>>A1>>A2;
fin>>H1>>M1;
fin>>H2>>M2;
//cout<<A1<<" "<<A2<<" "<<H1<<" "<<M1<<" "<<H2<<" "<<M2<<endl;
{
//cout<<"verific daca A1 = "<<A1<<" este prim"<<endl;
A1prim=1; // presupun ca A1 este prim
d=3;
while(d*d <= N && A1prim==1)
{
if(A1%d==0) A1prim=0; // A1 se divide cu d
d=d+2; // trec la urmatorul numar impar
}
}
if(A1prim==1)
{
// verific daca A2 se divide cu suma cifrelor lui A1
A1c=A1;
scifA1=0;
while(A1c > 0) // A1c mai are cifre
{
scifA1=scifA1 + A1c%10; // adun ultima cifra
A1c=A1c/10; // sterg ultima cifra
}
//cout<<"A1 = "<<A1<<" scifA1 = "<<scifA1<<endl;
if(A2 % scifA1 == 0)
{
//cout<<A2<<" % "<<scifA1<<" == 0"<<endl;
inversez=1;
}
else // aici A2 nu se divide cu suma cifrelor lui A1
{
//cout<<A2<<" % "<<scifA1<<" != 0"<<endl;
inversez=0;
}
}// sf if
else // aici A1 nu este prim
{
inversez=0; // nu trebuie sa le inversez
//cout<<A1<<" nu este prim"<<endl;
}
if(inversez==1)
{
//cout<<"le inversez ..."<<endl;
aux=H1; H1=H2; H2=aux;
aux=M1; M1=M2; M2=aux;
//cout<<A1<<" "<<A2<<" "<<H1<<" "<<M1<<" "<<H2<<" "<<M2<<endl;
}
minut1=H1*60+M1;
minut2=H2*60+M2;
//cout<<"minut1 = "<<minut1<<" minut2 = "<<minut2<<endl;
if(minut2==0) minut2=24*60;
//cout<<"minut1 = "<<minut1<<" minut2 = "<<minut2<<endl;
rora=max2/60;
rminut=max2%60;
CAPITOLUL 1. OJI 2023 1.2. CASTEL 7
//cout<<rora<<" "<<rminut;
fout<<rora<<" "<<rminut;
return 0;
} // sf calcul2()
int main()
{
fin>>C; //cout<<"C = "<<C<<endl;
fin>>N; //cout<<"N = "<<N<<endl<<endl;
if(C==1)
calcul1();
else
calcul2();
fin.close();
fout.close();
return 0;
}
int main()
{
int argc=4;
char* argv[] =
{
(char*)"checker",
(char*)"../../teste_aeriana/input.29-aeriana", // input
(char*)"../../teste_aeriana/output.29-aeriana", // rezultat corect
(char*)"aeriana.out", // rezultat de verificat si acordat punctaj
};
cout<<"argc = "<<argc<<"\n";
for(int kk=0;kk<argc;kk++)
cout<<argv[kk]<<"\n";
cout<<"----------------------\n";
compareRemainingLines();
}
1.2 castel
Problema 2 - Castel 100 de puncte
Un joc dispune de N cuburi galbene şi N cuburi albastre, de
dimensiuni identice; pe fiecare cub galben este scris un număr nat-
ural nenul, de cel mult 9 cifre.
Jocul urmăreşte construirea unui castel alcătuit din mai multe
rânduri de cuburi, ı̂n care rândul de sus este format dintr-un singur
cub, de culoare galbenă, iar fiecare dintre celelalte rânduri ı̂ncep
şi se termină cu câte un cub de culoare galbenă.
Oricare două cuburi vecine pe acelaşi rând au câte o latură comună şi fiecare cub, cu excepţia
celor galbene de pe margine, are o latură comună cu un cub care aparţine rândului de deasupra.
Oricare două cuburi cu o latură comună au culori diferite.
Rândurile de cuburi sunt numerotate de jos ı̂n sus, ı̂ncepând de la 1. Pentru construcţia
castelului se preiau cuburile galbene ı̂n ordinea ı̂n care acestea sunt date, iar cele albastre ı̂ntr-o
ordine oarecare, şi sunt plasate pe rânduri, de jos ı̂n sus, şi pe fiecare rând de la stânga la dreapta,
astfel: primul cub se plasează pe rândul de la bază (numerotat cu 1), apoi fiecare cub (galben sau
CAPITOLUL 1. OJI 2023 1.2. CASTEL 8
albastru) se plasează fie ı̂n continuare, pe rândul curent, la dreapta, fie pe un rând nou, peste un
cub al rândului curent.
După plasarea cubului din vârful castelului, pe fiecare cub albastru se scrie un număr egal cu
suma numerelor scrise pe cei doi vecini galbeni situaţi pe acelaşi rând, ı̂n stânga şi ı̂n dreapta sa.
Pentru a câs,tiga jocul, castelul obţinut trebuie să aibă un număr maxim de rânduri, chiar dacă
poate nu foloses,te toate cuburile date.
Cerinţe
Cunoscând numerele scrise pe cele N cuburi galbene, ı̂n ordinea dată, scrieţi un program care
să determine:
1. numărul cuburilor galbene, dintre cele N date, pe care sunt scrise valori de o singură cifră;
2. rândul pe care se află cubul din vârful castelului şi numărul scris pe acest cub;
3. numărul cuburilor albastre din care este alcătuit castelul şi suma tuturor numerelor de pe
acestea.
Date de intrare
pe prima linie două numere naturale C şi N , ı̂n această ordine, despărţite printr-un spaţiu,
unde C reprezintă numărul cerinţei şi poate avea valorile 1, 2 sau 3, iar N are semnificaţia
din enunţ;
pe a doua linie, N numere naturale despărţite prin câte un spaţiu, reprezentând numerele
scrise pe cuburile galbene, ı̂n ordinea ı̂n care sunt preluate.
Date de ieşire
Exemple:
Propusă de: prof. Iordaiche Eugenia-Cristiana, Liceul Teoretic ”Grigore Moisil”, Timişoara
a Pentru cerinţa 1, se contorizează toate valorile citite care au o singură cifră, ele sunt strict
mai mari decât 0 şi mai mici sau egale cu 9.
a Pentru cerinţa 2, se calculează, pentru fiecare rând R al castelului, numărul cuburilor galbene
aflate pe acesta. Ştim că pe ultimul rând este un singur cub galben, pe penultimul rând sunt 2
cuburi galbene, pe antepenultimul 3 cuburi galbene, şi, procedând ı̂n acest fel, pe primul rând
al castelului (numerotat cu 1) sunt K cuburi galbene. Astfel, castelul construit, are ı̂n total
1+2+3+4+...+K cuburi galbene, aranjate pe cele K rânduri.
Determinăm cea mai mare valoare a lui K pentru care suma 1+2+3+4+...K nu depăşeşte
valoarea lui N . Rândul pe care se află cubul din vârful castelului este K iar numărul scris pe
acesta este cel de pe pozitia p ı̂n şirul de intrare, unde p 1 2 ... k.
Alternativ p poate fi determinat şi cu formula k k 1©2.
a Pentru cerinţa 3, observăm că pe fiecare rând al castelului numărul cuburilor albastre este
cu 1 mai mic decât numărul cuburilor galbene. Păstrând aceleaşi notaţii ca la cerinţa anterioară,
numărul cuburilor albastre din castel este egal cu 1 2 3 ... k 1.
Pentru fiecare cub albastru, calculăm numărul scris pe acesta ca fiind suma a două valori
preluate succesiv din fişierul de intrare. Acestea reprezintă numerele scrise pe cuburile galbene
situate pe acelaşi rând, ı̂n stânga şi dreapta fiecărui cub albastru.
Calculăm suma tuturor valorilor scrise pe cuburile albastre din castel.
Fiecare scie codul cum vrea! Uneori este util şi un ”copy-paste”.
Trebuie să fim atenţi la valorile datelor de intrare! Numerele scrise pe cuburile galbene pot
avea 9 cifre, deci pot avea coduri 999 999 999 care este numai cu 1 mai mic decât 1 miliard.
N poate fi 5 000 iar suma tuturor numerelor poate fi aproape de 5 000 * 1 000 000 000, adică
de 5 mii de miliarde.
Un miliard ”ı̂ncape” ı̂ntr-un int dar o valoare de 5 000 de miliarde nu ”ı̂ncape” decât ı̂ntr-un
long long.
Şi o ultimă observaţie: este util să ”ı̂mpănăm ” programul cu mesaje care să afişeze pe ecran
valorile intermediare obţinute! ı̂n acest fel putem să observăm repede dacă am greşit pe undeva.
Iar când am terminat şi este totul ok, vom comenta aceste mesaje (nu este bine să le ştergem
pentru că, din greşeală, putem să ştergem ce nu trebuie!).
//ifstream fin("castel.in");
CAPITOLUL 1. OJI 2023 1.2. CASTEL 10
//ifstream fin("castel1.in");
//ifstream fin("castel2.in");
//ifstream fin("castel3.in");
//ifstream fin("..//..//teste_castel//input.1_0-castel");
//ifstream fin("..//..//teste_castel//input.1_7-castel");
//ifstream fin("..//..//teste_castel//input.2_0-castel");
//ifstream fin("..//..//teste_castel//input.2_9-castel");
//ifstream fin("..//..//teste_castel//input.3_0-castel");
ifstream fin("..//..//teste_castel//input.3_9-castel");
ofstream fout("castel.out");
int C; // cerinta
int N; // nr de zboruri
nrcg1=0;
for(int i=1; i<=N; i++)
{
fin>>ncg;
//cout<<i<<" : "<<ncg<<endl;
if(ncg <= 9) // are o cifra
{
nrcg1=nrcg1+1;
//cout<<" ncg = "<<ncg<<" nrcg1 = "<<nrcg1<<endl;
}
}
//cout<<"nrcg1 = "<<nrcg1<<endl;
fout<<nrcg1;
return 0;
} // sf calcul1()
// ---------------------------------------
rvarf=0;
nrvarf=0;
while(nrvarf < N)
{
rvarf++; // trbuie sa adiun
nrvarf=nrvarf+rvarf;
}
//cout<<"rvarf = "<<rvarf<<" nrvarf = "<<nrvarf<<endl;
if(nrvarf > N)
{
nrvarf=nrvarf-rvarf;
rvarf=rvarf-1;
}
//cout<<"rvarf = "<<rvarf<<" nrvarf = "<<nrvarf<<endl;
// ---------------------------------------
CAPITOLUL 1. OJI 2023 1.2. CASTEL 11
scr=0;
for(i=rvarf; i>=1; i--)
{
fin>>ncg;
}
//cout<<rvarf<<" "<<ncg<<endl;
fout<<rvarf<<" "<<ncg<<endl;
return 0;
} // sf calcul2()
scr=0LL;
nrca=0;
for(i=rvarf-1; i>=1; i--)
{
fin>>ncg;
ncgs=ncg;
for(j=1; j<=i; j++)
{
fin>>ncg;
ncgd=ncg;
ncr=ncgs+ncgd;
//cout<<"i: "<<i<<" j: "<<j
// <<" ncgs = "<<ncgs<<" ncgd = "<<ncgd
// <<" ncr = "<<ncr<<endl;
scr=scr+ncr;
nrca++;
ncgs=ncgd;
}
//cout<<endl;
}
// cout<<"nrca= "<<nrca<<" scr = "<<scr<<endl;
fout<<nrca<<" "<<scr<<endl;
return 0;
} // sf calcul3()
int main()
{
fin>>C; //cout<<"C = "<<C<<endl;
fin>>N; //cout<<"N = "<<N<<endl<<endl;
fin.close();
fout.close();
return 0;
}
CAPITOLUL 1. OJI 2023 1.2. CASTEL 12
int main()
{
int argc=4;
char* argv[] =
{
(char*)"checker",
//(char*)"../../teste_castel/input.1_7-castel", // input
//(char*)"../../teste_castel/output.1_7-castel", // rezultat corect
//(char*)"../../teste_castel/input.2_9-castel", // input
//(char*)"../../teste_castel/output.2_9-castel", // rezultat corect
(char*)"../../teste_castel/input.3_9-castel", // input
(char*)"../../teste_castel/output.3_9-castel", // rezultat corect
cout<<"argc = "<<argc<<"\n";
for(int kk=0;kk<argc;kk++)
cout<<argv[kk]<<"\n";
cout<<"----------------------\n";
compareRemainingLines();
}
Capitolul 2
OJI 2022
2.1 ceas
Problema 1 - ceas 100 de puncte
Un atelier de fabricat ceasuri cu cuc are nevoie de plăcuţe cu numerele pentru orele pe care
trebuie să le aşeze pe discul ceasurilor. Aceste numere sunt realizate la o imprimantă.
Din cauza unei erori imprimanta tipăreşte plăcuţe cu numere naturale, unele mai mari ca 12.
Atelierul poate utiliza doar plăcuţe cu numere cuprinse ı̂ntre 0 şi 12. Pentru a utiliza aceste numere
este nevoie ca ele să fie tăiate ı̂ncepând din partea dreaptă ı̂n grupuri de maxim 2 cifre, fiecare
grup reprezentând valoarea de pe o plăcuţă, care să fie o cifră la 0 la 9 sau unul dintre numerele 10,
11, 12. Dacă pe o plăcuţă se găseşte un număr mai mare ca 12 atunci plăcuţa trebuie tăiată, astfel
ı̂ncât ı̂n urma tăierii să se obţină numere de cel mult 2 cifre. Dacă ı̂n numărul de pe o plăcuţă
cifra zecilor este 0, atunci la prima tăiere se ia doar cifra unităţilor, altfel dacă numărul format cu
cifra zecilor şi unităţilor este mai mare ca 12, atunci se taie prima dată cifra unităţilor, iar dacă
numărul format cu cifra zecilor şi unităţilor este 10, 11 sau 12 se taie prima dată numărul format
din ultimele 2 cifre, apoi procedeul se repetă până la tăierea completă a plăcuţei. Imprimanta a
realizat N plăcuţe. De exemplu dacă plăcuţa este 12030, după tăiere se obţin 0, 3, 0, 12.
Cerinţe
Cerinţa 1
Determinaţi numărul total de apariţii ale cifrei X pe plăcuţe ı̂nainte de tăiere.
Cerinţa 2
Determinaţi numărul de tăieturi realizate conform enunţului.
Date de intrare
Pe prima linie a fişierului ceas.in se află valorile C, X şi N separate prin câte un singur spaţiu.
Pe linia a doua se află N numere naturale separate prin câte un singur spaţiu, având semnificaţia
din enunţ. Pentru C = 1 se rezolvă doar cerinţa 1, iar pentru C = 2 se rezolvă doar cerinţa 2.
Date de ieşire
Fişierul ceas.out conţine pe prima linie un singur număr natural care reprezintă valoarea
calculată conform cerinţei.
13
CAPITOLUL 2. OJI 2022 2.1. CEAS 14
Exemple:
Propusa de: Pintea Adrian Doru, profesor la Colegiul Naţional Andrei Mureşanu Dej
Pentru cerinţa 1, se citesc pe rând cele N numere şi pentru fiecare număr se calculează de câte
ori conţine cifra X.
Pentru cerinţa 2, se citesc pe rând cele N numere şi pentru fiecare număr se fac tăieturile a
uneia (cifra unităţilor) sau a două cifre (cifra zecilor şi cifra unităţilor) conform cerinţei, numărând
fiecare taietură realizată.
//ifstream fin("ceas1.in");
//ifstream fin("ceas2.in");
//ifstream fin("ceas3.in");
//cerinta 1
//ifstream fin("../teste_ceas/00-ceas.in"); // 734
//ifstream fin("../teste_ceas/01-ceas.in"); // 14469
//ifstream fin("../teste_ceas/02-ceas.in"); // 11868
//ifstream fin("../teste_ceas/03-ceas.in"); // 13697
//ifstream fin("../teste_ceas/04-ceas.in"); // 19773
//ifstream fin("../teste_ceas/05-ceas.in"); // 20627
//ifstream fin("../teste_ceas/06-ceas.in"); // 50999
//ifstream fin("../teste_ceas/07-ceas.in"); // 31844
//ifstream fin("../teste_ceas/08-ceas.in"); // 30866
//ifstream fin("../teste_ceas/09-ceas.in"); // 39615
//cerinta 1
//ifstream fin("../teste_ceas/10-ceas.in"); // 3496
//ifstream fin("../teste_ceas/11-ceas.in"); // 34949
//ifstream fin("../teste_ceas/12-ceas.in"); // 104795
//ifstream fin("../teste_ceas/13-ceas.in"); // 139697
//ifstream fin("../teste_ceas/14-ceas.in"); // 174574
//ifstream fin("../teste_ceas/15-ceas.in"); // 209481
ifstream fin("../teste_ceas/16-ceas.in"); // 244393
//ifstream fin("../teste_ceas/17-ceas.in"); // 279229
//ifstream fin("../teste_ceas/18-ceas.in"); // 314061
//ifstream fin("../teste_ceas/19-ceas.in"); // 348865
//ifstream fin("../teste_ceas/20-ceas.in"); // 3
//ifstream fin("../teste_ceas/21-ceas.in"); // 4
//ifstream fin("../teste_ceas/22-ceas.in"); // 8
//ifstream fin("../teste_ceas/23-ceas.in"); // 0
//ifstream fin("../teste_ceas/24-ceas.in"); // 16
CAPITOLUL 2. OJI 2022 2.1. CEAS 15
ofstream fout("ceas.out");
int C; // cerinta
int X; // cifra
int N; // nr numere
void cerinta1()
{
int i;
rez1=0;
for(i=1; i<=N; i++)
{
fin>>nr;
if((nr==0)&&(X==0)) // Atentie: si zero este numar natural !!!
{
rez1++;
continue; // i++
}
while(nr != 0)
{
if(nr%10 == X) rez1++; // testez ultima cifra
nr=nr/10; // elimin ultima cifra
}
}
cout<<"rez1 = "<<rez1;
fout<<rez1;
return;
}
rez2=0;
for(i=1; i<=N; i++)
{
fin>>nr;
//getchar();
if((nr%10) >= 3) // daca ultima cifra este 3, 4, ..., 9
{
//cout<<(nr%10)<<", ";
nr=nr/10;
if(nr>0) // daca a mai ramas ceva in nr --> s-a taiat o cifra
{
rez2++; // daca a fost ultimul --> nu am ce sa tai
//cout<<" | ";
}
}
else // ultima cifra este 0, 1 sau 2
if(nr/10==0) // este o singura cifra --> se plaseaza, nu se taie
{
//cout<<nr<<"*, ";
nr=nr/10;
}
else // aici sunt cel putin 2 cifre si ultima cifra este 1 sau 2
{
nr2=nr%100; // nr2 = ultimele 2 cifre
CAPITOLUL 2. OJI 2022 2.1. CEAS 16
cout<<"rez2 = "<<rez2;
fout<<rez2;
return;
}
int main()
{
fin>>C;
fin>>X;
fin>>N;
cout<<"C = "<<C<<" X = "<<X<<" N = "<<N<<’\n’;
if(C==1) cerinta1();
if(C==2) cerinta2();
fin.close();
fout.close();
return 0;
}
int main()
{
int argc=4;
char* argv[] =
{
(char*)"checker",
(char*)"../teste_ceas/16-ceas.in", // input
(char*)"../teste_ceas/16-ceas.out", // rezultat corect
(char*)"ceas.out", // rezultat de verificat si acordat punctaj
};
cout<<"argc = "<<argc<<"\n";
for(int kk=0;kk<argc;kk++)
cout<<argv[kk]<<"\n";
cout<<"----------------------\n";
compareRemainingLines();
}
CAPITOLUL 2. OJI 2022 2.2. SSS 17
2.2 sss
Problema 2 - sss 100 de puncte
Se dă un număr N, şi un şir de N numere naturale nenule.
Cerinţe
Cerinţa 1
Determinaţi suma valorilor aflate pe ultimele K poziţii ı̂n şir (unde K reprezintă valoarea celei
mai din dreapta cifre nenule a primei valori din şir).
Cerinţa 2
Ne imaginăm ı̂mpărţirea şirului ı̂n secvenţe ı̂n următorul mod: prima secvenţă este formată
din primele L elemente, a doua este formată din următoarele L - 1 elemente, a treia este formată
din următoarele L - 2 elemente şi aşa mai departe, ultima secvenţă este formată dintr-un singur
element şi acesta coincide cu ultimul element din şir. Considerând suma valorilor fiecărei secvenţe,
să se determine cea mai mare dintre aceste sume.
Date de intrare
Pe prima linie a fişierului sss.in se află două valori C şi N separate printr-un spaţiu. Pe linia a
doua se află N numere naturale separate prin câte un spaţiu. Pentru C = 1 se rezolvă doar cerinţa
1 iar pentru C = 2 se rezolvă doar cerinţa 2.
Date de ieşire
Fişierul sss.out conţine un singur număr care reprezintă valoarea calculată conform cerinţei.
Se garantează că pentru testele ı̂n care C = 1 şirul are cel puţin K elemente;
Se garantează că valoarea lui N permite descompunerea conform descrierii, pentru testele
care au C = 2;
Pentru teste ı̂n valoare de 51 de puncte avem C=1;
Pentru 27 de puncte dintre testele ı̂n care C=1 primul număr din şir are o cifră;
Pentru teste ı̂n valoare de 22 de puncte dintre cele care au C=2, valoarea lui N este mai
mică sau egală cu 10.
Denumirea problemei este o prescurtare de la ”sume şi secvenţe”.
Exemple:
Propusa de: Marius Nicoli, profesor la Colegiul Naţional Fraţii Buzeşti Craiova, Programator
la Syncro Soft Craiova
Pentru cerinţa 1, aflăm mai ı̂ntâi valoarea lui k imediat după citirea primului termen al şirului.
Pentru acest lucru folosim algoritmul clasic de parcurgere a cifrelor unui număr (ı̂mpărţiri
repetate la 10). Ulterior citim şi celelalte numere şi acumulăm la suma cerută valorile celor aflate
pe poziţii mai mari sau egale cu n-k+1 (considerăm numerotarea de la poziţia 1).
Pentru cerinţa 2, imediat după citirea lui n şi ı̂nainte să citim elementele şirului, determinăm
valoarea L. Vom folosi o repetiţie ı̂n care construim suma 1 + 2 + 3 + . . . până când aceasta
devine egală cu n (lucru garantat de restricţiile din enunţ). Numărul de termeni ai acestei sume
este chiar L. Acum putem ı̂ncepe citirea valorilor şirului, de exemplu putem folosi o variabilă
sumaCurentă ı̂n care acumulăm iniţial valorile primelor L elemente, apoi resetăm sumaCurentă şi
acumulăm la ea valorile următoarelor L-1 şi aşa mai departe până terminăm de citit valorile din
şir.
//ifstream fin("sss1.in");
//ifstream fin("sss2.in");
//cerinta 1
//ifstream fin("../teste_sss/00-sss.in"); // 14
//ifstream fin("../teste_sss/01-sss.in"); // 98
//ifstream fin("../teste_sss/02-sss.in"); // 3355
//ifstream fin("../teste_sss/03-sss.in"); // 11
//ifstream fin("../teste_sss/04-sss.in"); // 17442
//ifstream fin("../teste_sss/05-sss.in"); // 6
//ifstream fin("../teste_sss/06-sss.in"); // 1413
//ifstream fin("../teste_sss/07-sss.in"); // 35222
//ifstream fin("../teste_sss/08-sss.in"); // 154
//ifstream fin("../teste_sss/09-sss.in"); // 383221
//cerinta 2
//ifstream fin("../teste_sss/10-sss.in"); // 18
//ifstream fin("../teste_sss/11-sss.in"); // 25
//ifstream fin("../teste_sss/12-sss.in"); // 25
//ifstream fin("../teste_sss/13-sss.in"); // 67
//ifstream fin("../teste_sss/14-sss.in"); // 108
//ifstream fin("../teste_sss/15-sss.in"); // 29671
//ifstream fin("../teste_sss/16-sss.in"); // 30147
//ifstream fin("../teste_sss/17-sss.in"); // 30147
//ifstream fin("../teste_sss/18-sss.in"); // 30151
ifstream fin("../teste_sss/19-sss.in"); // 30356
ofstream fout("sss.out");
int C; // cerinta
int N; // nr numere
int L;
int s;
int smax;
void cerinta1()
{
int i;
int cifra;
rez1=0;
fin>>nr;
cout<<"nr = "<<nr<<endl;
cifra=nr%10;
//cout<<"cifra = "<<cifra<<endl;
//getchar();
cout<<"rez1 = "<<rez1;
fout<<rez1;
return;
}
// 1+2+3+...+L=N;
if(N==1)
{
fin>>nr;
cout<<"rez2 = "<<nr<<endl;
fout<<rez2;
return;
}
if(N==3) // 3 = 2 + 1
{
fin>>nr; // citesc primele 2 nr
s=nr;
fin>>nr;
s=s+nr;
smax=s; // este prima valoare pentru sume
if(s>smax) smax=s;
cout<<"rez2 = "<<smax<<endl;
fout<<smax;
return;
}
s1L=0; // cu s determin L
L=0;
// s = 1 + 2 + 3 + ... + (L-1) + L = N
while(s<N)
{
L=L+1;
s=s+L;
//cout<<"L = "<<L<<" s = "<<s<<endl; // s trebuie sa ajunga la N
}
//cout<<"L = "<<L<<endl;
//getchar();
return;
}
int main()
{
fin>>C;
fin>>N;
cout<<"C = "<<C<<" N = "<<N<<’\n’;
if(C==1) cerinta1();
if(C==2) cerinta2();
fin.close();
fout.close();
return 0;
}
int main()
{
int argc=4;
char* argv[] =
{
(char*)"checker",
(char*)"../teste_sss/19-sss.in", // input
(char*)"../teste_sss/19-sss.out", // rezultat corect
(char*)"sss.out", // rezultat de verificat si acordat punctaj
};
cout<<"argc = "<<argc<<"\n";
for(int kk=0;kk<argc;kk++)
cout<<argv[kk]<<"\n";
cout<<"----------------------\n";
3.1 concurs
Problema 1 - concurs 100 de puncte
În oraşul X va avea loc o nouă ediţie a concursului Y , la care participă 3 echipe având numerele
de concurs 1, 2 şi 3. Echipele pot avea număr diferit de concurenţi.
Ordinea ı̂n care participanţii intră ı̂n concurs este una oarecare. Fiecare concurent are de
susţinut 9 probe. La fiecare probă, un concurent obţine un punctaj exprimat printr-un număr
natural, cuprins ı̂ntre 0 şi 10, inclusiv.
La scurt timp după ce un concurent a susţinut toate cele 9 probe, se afişează performanţa
concurentului sub forma a două numere naturale, astfel:
primul număr poate fi 1, 2 sau 3 şi reprezintă echipa din care face parte concurentul;
al doilea număr este obţinut prin concatenarea (alipirea) numerelor ce reprezintă punctajele
nenule obţinute de concurent la cele 9 probe. Dacă un concurent are punctaj 0 la toate
probele atunci al doilea număr este 0.
Punctajul total al unui concurent se obţine adunând punctajele obţinute de acesta la cele 9
probe. Punctajul unei echipe se obţine adunând punctajele totale obţinute de membrii acesteia.
De exemplu, afişajul 2 14102172, semnifică faptul că acest concurent face parte din echipa 2
şi are punctajele nenule 1, 4, 10, 2, 1, 7 şi 2, la 7 dintre cele 9 probe susţinute. La celelalte două
probe a avut punctajul 0. Punctajul său total este 27, contribuţia sa la punctajul echipei 2 fiind
de 27 de puncte.
Este declarată campioană echipa cu punctajul cel mai mare. Dacă mai multe echipe au obţinut
cel mai mare punctaj, atunci toate aceste echipe sunt declarate campioane. Totuşi, dacă toate
echipele au totalizat 0 puncte, atunci nicio echipă nu este declarată campioană.
Cerinţe
Cunoscând numărul N de concurenţi, echipele din care fac parte precum şi punctajele obţinute
de fiecare dintre ei, să se determine:
1. punctajul maxim obţinut de un concurent şi numărul de concurenţi care au obţinut acest
punctaj;
2. numărul sau numerele de concurs ale echipelor declarate campioane, n̂ ordine crescătoare,
şi punctajul obţinut de acestea. Dacă toate echipele au punctajul final 0, se va afişa textul
FARA CAMPION
Date de intrare
Fişierul de intrare concurs.in conţine pe prima linie un număr C (care poate fi 1 sau 2),
indicând cerinţa de rezolvat. Pe a doua linie se găseşte un număr natural N reprezentând numărul
de concurenţi, iar pe fiecare dintre următoarele N linii se găsesc câte două numere naturale,
separate printr-un spaţiu, reprezentând echipa şi punctajele fiecăruia dintre cei N concurenţi, ı̂n
ordinea intrării ı̂n concurs.
21
CAPITOLUL 3. OJI 2021 - OSEPI 3.1. CONCURS 22
Date de ieşire
Exemple:
valoarea afişată după susţinerea celor 9 probe este nenulă, stabilirea punctajul total al concuren-
tului se reduce la a calcula suma cifrelor numărului ce reprezintă performanţa sa, cu observaţia
că, dacă cifra prelucrată la un moment dat este 0, se va asocia cu valoarea 1 din faţa sa, şi la
punctajul total se adună 10 puncte.
Cerinţa 1 presupune calculul maximului dintr-un şir şi de câte ori apare acesta.
Cerinţa 2 presupune calculul maximului dintre trei valori, valori asociate puntajelor totale ale
celor 3 echipe, şi afişarea etichetei echipelor care au punctajul egal cu cel maxim.
Obs: https://ebooks.infobits.ro/culegere_OJI_2021.pdf
ifstream f("concurs.in");
ofstream g("concurs.out");
int main()
{
f>>x>>n;
if(x==2)
{
for(int i=1; i<=n; i++)
{
f>>C>>P;
pct=0;
while(P)
{
if(P%10==0)
{
pct+=10;
P/=100;
}
else
{
pct+=P%10;
P/=10;
}
}
if(C==1) pa+=pct;
else
if(C==2) pb+=pct;
else pc+=pct;
}
pmax=max(pa,max(pb,pc));
if(pmax)
{
if(pa==pmax) g<<1<<’ ’;
if(pb==pmax) g<<2<<’ ’;
if(pc==pmax) g<<3<<’ ’;
g<<pmax<<endl;
}
else
g<<"FARA CAMPION"<<endl;
}
else
{
for(int i=1; i<=n; i++)
{
f>>C>>P;
CAPITOLUL 3. OJI 2021 - OSEPI 3.1. CONCURS 24
pct=0;
long long aux=P;
while(P)
{
if(P%10==0)
{
pct+=10;
P/=100;
}
else
{
pct+=P%10;
P/=10;
}
}
if(pct>pmax)
{
nrc=1;
pmax=pct;
}
else
if(pct==pmax) nrc++;
}
g<<pmax<<" "<<nrc<<endl;
}
f.close();
g.close();
return 0;
}
long long smax, nr, p,x,n,i,c, max1, c1, s, aux, s1, s2, s3;
int main()
{
f>>c;
if (c==1)
{
f>>n;
max1=0;
for (i=1;i<=n;i++)
{
f>>p;
f>>x;
aux=x;
s=0;
while (aux>0)
{
if (aux%10==0)
{
s=s+10;
aux=aux/100;
}
else
{
s=s+aux%10;
aux=aux/10;
}
}
if (s>max1)
{
CAPITOLUL 3. OJI 2021 - OSEPI 3.1. CONCURS 25
max1=s;
nr=1;
}
else
if (s==max1) nr++;
}
g<<max1<<" "<<nr<<"\n";
}
else
{
f>>n;
max1=0;
s1=0;
s2=0;
s3=0;
for (i=1;i<=n;i++)
{
f>>p;
f>>x;
if (x==0) s=0;
else
{
aux=x;
s=0;
while (aux>0)
{
if (aux%10==0)
{
s=s+10;
aux=aux/100;
}
else
{
s=s+aux%10;
aux=aux/10;
}
}
if (p==1) s1=s1+s;
if (p==2) s2=s2+s;
if (p==3) s3=s3+s;
}
}
if (s1==0&&s2==0&&s3==0)
g<<"FARA CAMPION"<<"\n";
else
{
max1=0;
if (s1>max1) max1=s1;
if (s2>max1) max1=s2;
if (s3>max1) max1=s3;
if (s1==max1) g<<"1 "<<max1<<"\n";
if (s2==max1) g<<"2 "<<max1<<"\n";
if (s3==max1) g<<"3 "<<max1<<"\n";
}
}
return 0;
}
ifstream in("concurs.in");
ofstream out("concurs.out");
int E,c, n;
long long x, p1, p2, p3, p, pmax, k;
CAPITOLUL 3. OJI 2021 - OSEPI 3.2. SIR 26
int main()
{
in>>c>>n;
p1=p2=p3=p=pmax=k=0;
for(int i=1; i<=n; i++)
{
in>>E>>x;
p=0;
while(x)
{
if(x%10) p=p+x%10;
else
{
p+=10;
x/= 10;
}
x/= 10;
}
if(c==1)
if(p>pmax)
{
pmax=p;
k=1;
}
else
if(p==pmax) k++;
else;
else
E==1?p1+=p:(E==2?p2+=p:p3+=p);
}
return 0;
}
3.2 sir
Problema 2 - sir 100 de puncte
Se dă un şir format din n numere naturale nenule. Elementele şirului sunt numerotate de la
stânga la dreapta ı̂ncepând cu poziţia 1.
Cerinţe
Scrieţi un program care să determine răspunsul pentru ı̂ntrebări de următoarele tipuri:
1. Care este cea mai din stânga poziţie care conţine o valoare strict mai mare decât toate cele
din dreapta sa? - ı̂ntrebare de tipul 1
2. Care sunt poziţiile care conţin valori strict mai mari decât toate cele din stânga lor? -
ı̂ntrebare de tipul 2
3. Dacă fiecărui element aflat ı̂ntre prima şi ultima apariţie a maximului i-am mări valoarea
pentru a ajunge egal cu maximul, care este suma totală a valorilor adăugate? - ı̂ntrebare de
tipul 3
CAPITOLUL 3. OJI 2021 - OSEPI 3.2. SIR 27
Date de intrare
Fişierul de intrare sir.in conţine pe prima linie un număr C (care poate fi 1, 2 sau 3), indicând
tipul ı̂ntrebării. Pe linia a doua se află un număr natural N , reprezentând numărul de elemente
din şir. Pe a treia linie a fişierului de intrare se află N numere naturale, reprezentând elementele
şirului, date de la stânga la dreapta (cel mai din stânga are poziţia 1 şi cel mai din dreapta are
poziţia N ). Numerele de pe această linie sunt separate prin câte un spaţiu.
Date de ieşire
Dacă C 1, fişierul de ieşire sir.out trebuie să conţină un număr natural ce reprezintă
răspunsul la o ı̂ntrebare de tipul 1.
Dacă C 2, fişierul de ieşire trebuie să conţină, separaţi prin câte un spaţiu şi ı̂n ordine
crescătoare, indicii determinaţi ca răspuns la o ı̂ntrebare de tipul 2.
Dacă C 3, fişierul de ieşire trebuie să conţină un număr ce reprezintă răspunsul la o ı̂ntrebare
de tipul 3.
1&C & 3.
1 & N &100 000.
Numerele din şirul dat sunt cuprinse ı̂ntre 1 şi 10 000, inclusiv.
Pentru teste ı̂n valoare de 24 de puncte avem C 1.
Pentru teste ı̂n valoare de 32 de puncte avem C 2.
Pentru teste ı̂n valoare de 44 de puncte avem C 3.
Exemple:
Mai sus am descris o strategie de a procesa informaţiile dintr-o secvenţă cuprinsă ı̂ntre primul
şi ultimul element cu valoarea maximă, realizând calculele ı̂n timpul citirii datelor.
Obs: https://ebooks.infobits.ro/culegere_OJI_2021.pdf
int C,N,x,maxi,pmax,i,j,s,S;
ifstream f("sir.in");
ofstream g("sir.out");
int main()
{
f>>C>>N;
if(C==1)
{
for(i=1; i<=N; i++)
{
f>>x;
if(x>=maxi)
{
maxi=x;
pmax=i;
}
}
g<<pmax<<endl;
}
else if(C==2)
{
for(i=1; i<=N; i++)
{
f>>x;
if(x>maxi)
{
maxi=x;
g<<i<<" ";
}
}
g<<endl;
}
else
{
for(i=1; i<=N; i++)
{
f>>x;
if(x>maxi)
{
maxi=x;
s=0;
}
else
{
CAPITOLUL 3. OJI 2021 - OSEPI 3.2. SIR 29
s+=maxi-x;
if(x==maxi) S=s;
}
}
g<<S<<endl;
}
f.close();
g.close();
return 0;
}
ifstream f("sir.in");
ofstream g("sir.out");
int c,n,i,x,max1,p1,p2,sf,p,s;
int main()
{
f>>c;
if (c==1)
{
f>>n;
max1=0;
for (i=1;i<=n;i++)
{
f>>x;
if (x>=max1)
{
max1=x;
p=i;
}
}
g<<p<<"\n";
}
else
if (c==2)
{
f>>n;
max1=0;
for (i=1;i<=n;i++)
{
f>>x;
if (x>max1)
{
max1=x;
g<<i<<" ";
}
}
g<<"\n";
}
else
{
f>>n;
max1=0;
p1=0;
p2=0;
s=0;
sf=0;
for (i=1;i<=n;i++)
{
f>>x;
s=s+x;
CAPITOLUL 3. OJI 2021 - OSEPI 3.2. SIR 30
if (x>max1)
{
max1=x;
p1=i;
p2=p1;
s=0;
}
else
if (x==max1)
{
p2=i;
sf=s;
}
}
g<<(p2-p1-1)*max1-(sf-max1);
}
return 0;
}
ifstream in ("sir.in");
ofstream out("sir.out");
int main ()
{
in>>c>>n;
switch (c)
{
case 1:
{
maxi=poz= 0;
for (i=1; i<=n; i++)
{
in>>x;
if (x >= maxi)
{
maxi = x;
poz = i;
}
}
out<<poz<<’\n’;
return 0;
}
case 2:
{
maxi=0;
for (i=1; i<=n; i++)
{
in>>x;
if (x > maxi)
{
maxi = x;
out<<i<<’ ’;
}
}
out<<’\n’;
return 0;
}
case 3:
CAPITOLUL 3. OJI 2021 - OSEPI 3.2. SIR 31
{
for (i=1; i<=n; i++)
{
in>>x;
if (x > maxi)
{
maxi = x;
g = 0;
}
else g += maxi-x;
if (x == maxi)rez = g;
}
out<<rez<<’\n’;
}
}
return 0;
}
OJI 2020
4.1 cartonase
Problema 1 - cartonase 100 de puncte
Ionel are N cartonaşe. Fiecare cartonaş are ı̂nscrise două numere (un număr, s, ı̂n partea
stângă, şi celălalt număr, d, ı̂n partea dreaptă).
El a aşezat cartonaşele ı̂ntr-un şir, lipite unul de celălalt, astfel ı̂ncât numărul din partea
dreaptă a primului cartonaş este lipit de numărul din partea stângă a celui de-al doilea cartonaş,
numărul din partea dreaptă a celui de al doilea cartonaş este lipit de numărul din partea stângă
a celui de-al treilea cartonaş etc.
Spunem că două cartonaşe alăturate ”se potrivesc” dacă numărul din dreapta al primului
cartonaş este egal cu numărul din stânga al celui de al doilea cartonaş.
Ionel observă că sunt perechi de cartonaşe alăturate care ”se potrivesc” şi chiar secvenţe de
mai multe cartonaşe alăturate, ı̂n care primul ”se potriveşte” cu al doilea, al doilea ”se potriveşte”
cu al treilea etc.
Cerinţe
Scrieţi un program care să citească numărul N de cartonaşe, numerele ı̂nscrise pe fiecare
cartonaş şi determină:
1) Numărul de perechi de cartonaşe care ”se potrivesc”.
2) Numărul de cartonaşe din cea mai lungă secvenţă ı̂n care fiecare două cartonaşe alăturate
”se potrivesc”.
3) Numărul de secvenţe cu număr maxim de cartonaşe care ”se potrivesc”.
Date de intrare
Date de ieşire
32
CAPITOLUL 4. OJI 2020 4.1. CARTONASE 33
Exemple:
Cerinţa 1
Cerinţa 2
Cerinţa 3
int main()
{
ifstream in ("cartonase.in");
CAPITOLUL 4. OJI 2020 4.1. CARTONASE 35
int n,L=1,P=0,C,s1,d1,s2,d2,i,nr=0,i1,i2,cate;
in>>C>>n;
if(C==1)
{
in>>s1>>d1;
for(i=2;i<=n;++i)
{
in>>s2>>d2;
if(d1==s2)
P++;
s1=s2;
d1=d2;
}
out<<P<<endl;
}
if(C==2)
{
in>>s1>>d1;
nr=1;
i1=1;
i2=1;
for(i=2;i<=n;++i)
{
in>>s2>>d2;
if(d1==s2)
{
nr++;
if(nr>L){L=nr;}
}
else {nr=1;}
s1=s2;
d1=d2;
}
out<<L<<endl;
}
if(C==3)
{
in>>s1>>d1;
nr=1;
cate=1;
for(i=2;i<=n;++i)
{
in>>s2>>d2;
if(d1==s2)
{
nr++;
if(nr>L){L=nr; cate=1;}
else if(nr==L) cate++;
}
else {nr=1;}
s1=s2;
d1=d2;
}
out<<cate<<endl;
}
return 0;
}
#include <fstream>
int main()
{
int i, n;
int task; /// cerinta
int a1, b1; /// a1,b1= valorile de pe cartonasul precedent
int a2, b2; /// a2, b2 = valorile de pe cartonasul curent
int nrPerechi; /// pentru cerinta 1
int maxLen, L, cnt;
ifstream fin("cartonase.in");
ofstream fout("cartonase.out");
if (maxLen < L)
{
maxLen = L;
cnt = 1;
}
else if (maxLen == L) cnt++;
a1 = a2;
b1 = b2;
}
fin.close();
fout.close();
return 0;
}
int n,s,d,nr,c,S,D,lc,lmax;
CAPITOLUL 4. OJI 2020 4.2. TAI 37
ifstream f("cartonase.in");
ofstream g("cartonase.out");
int main()
{
f>>c>>n;
///cerinta 1
if(c==1)
{ f>>s>>d;
for(int i=2;i<=n;i++)
{
f>>S>>D;
if(d==S) nr++;
s=S;d=D;
}
g<<nr<<endl;
}
else
{ ///cerintele 2 si 3
f>>s>>d;lmax=1;nr=1;lc=1;
for(int i=2;i<=n;i++)
{
f>>S>>D;
if(d==S) lc++;
else
lc=1;
if(lc>lmax)
{lmax=lc;nr=1;}
else
if(lc==lmax) nr++;
s=S;d=D;
}
///afisare cerinta 2
if(c==2)
g<<lmax<<endl;
else g<<nr<<endl; ///afisare cerinta 3
}
f.close();
g.close();
return 0;
}
4.2 tai
Problema 2 - tai 100 de puncte
Un număr este prim dacă are exact doi divizori naturali. Prin tăierea unui număr ı̂n p părţi
ı̂nţelegem ı̂mpărţirea acestuia ı̂n p numere, fiecare de cel puţin o cifră, astfel ı̂ncât prin alipirea
numerelor obţinute de la stânga la dreapta obţinem numărul iniţial.
De exemplu, dacă ı̂mpărţim numărul 12045 ı̂n două părţi avem patru variante de tăiere
obţinându-se numerele: 1 şi 2045; 12 şi 045; 120 şi 45; 1204 şi 5. Dacă ı̂l ı̂mpărţim ı̂n trei
părţi avem şase variante de tăiere obţinându-se numerele 1, 2 şi 045; 1, 20 şi 45; 1, 204 şi 5; 12, 0
şi 45; 12, 04 şi 5; 120, 4 şi 5.
Cerinţe
Date de intrare
Pe prima linie a fişierului tai.in se găseşte numărul C care poate avea doar valorile 1, 2 sau 3
şi reprezintă cerinţa care urmează a fi rezolvată. Pe a doua linie se găseşte N , cu semnificaţia din
enunţ, iar pe a treia linie se găseşte şirul celor N numere naturale despărţite prin câte un spaţiu.
Date de ieşire
În fişierul de ieşire tai.out pe prima linie se va afişa un număr natural reprezentând răspunsul
la cerinţa specificată.
Exemple:
- Vom ı̂mpărţi numerele date ı̂n exact două numere şi vom calcula maximul celor prime
Cerinţa 3
- Vom ı̂mpărţi numerele date ı̂n exact 3 numere ca ı̂n enunţ şi vom calcula maximul celor
prime. Se pot ı̂mpărţi direct ı̂n 3 părţi numerele cu două strucuturi repetitive şi folosind puterile
lui 10 sau se poate ı̂mpărţi o dată ı̂n 2 părţi şi o parte iar ı̂n 2 părţi.
62 ok = 0;
63
64 if(a>1 && ok && a > Max)
65 Max = a;
66
67 ok = 1;
68 for(d = 2; d * d <= b && ok; d++)
69 if(b % d == 0)
70 ok = 0;
71
72 if(b>1 && ok && b > Max)
73 Max = b;
74 p/=10;
75 }
76 }
77 printf("%d\n", Max);
78 }
79
80 if(P==3)
81 {
82 Max = 0;
83 for( k = 1; k <= N ; k++)
84 {
85 scanf("%d", &X);
86 assert(X>=0 && X<=inf);
87 nc = 0;
88 pz = 1;
89 while (X/pz > 0)
90 {
91 pz*=10;
92 nc++;
93 }
94 pz = pz/10;
95 p1 = p = pz;
96 for(i = 1; i< nc -1; i++)
97 {
98 c = X / p1;
99 x = X % p1;
100 p = p1 / 10;
101
102 ok = 1;
103 for(d = 2; d * d <= c && ok; d++)
104 if(c % d == 0)
105 ok = 0;
106
107 if(c>1 && ok && c > Max)
108 Max = c;
109 while (p>9)
110 {
111 a = x % p;
112 b = x / p;
113
114 ok = 1;
115 for(d = 2; d * d <= a && ok; d++)
116 if(a % d == 0)
117 ok = 0;
118
119 if(a>1 && ok && a > Max)
120 Max = a;
121
122 ok = 1;
123 for(d = 2; d * d <= b && ok; d++)
124 if(b % d == 0)
125 ok = 0;
126
127 if(b>1 && ok && b > Max)
128 Max = b;
129 p/=10;
130 }
131 p1 /=10;
132 }
133 }
134
135 printf("%d\n", Max);
136 }
137
CAPITOLUL 4. OJI 2020 4.2. TAI 41
138 return 0;
139 }
ifstream f("tai.in");
ofstream g("tai.out");
int N,i,x,nd,d,C,aux,y1,y2,y3,z,t,w,p,max1,x1,x2,q;
int main()
{
f>>C;
if (C==1)
{
f>>N;
max1=0;
for (i=1;i<=N;i++)
{
f>>x;
for (d=2;d*d<=x;d++)
if (x%d==0) break;
if (x>1&&d*d>x&& x>max1)
max1=x;
}
g<<max1<<"\n";
}
else
if (C==2)
{
max1=0;
f>>N;
for (i=1;i<=N;i++)
{
f>>x;
aux=x;
p=10;
while (aux>=p)
{
x1=aux%p;
x2=aux/p;
//g<<x<<"="<<x2<<" "<<x1<<endl;
p=p*10;
for (d=2;d*d<=x1;d++)
if (x1%d==0) break;
if (x1>1&&d*d>x1&& x1>max1)
max1=x1;
for (d=2;d*d<=x2;d++)
if (x2%d==0) break;
if (x2>1&&d*d>x2&& x2>max1)
max1=x2;
}
}
g<<max1<<"\n";
}
else
{
f>>N;
max1=0;
for (i=1;i<=N;i++)
{
f>>x;
aux=x;
p=10;
while (aux>p*10)
p=p*10;
for (t=10;t*10<=p;t=t*10)
for (q=10;q*t<=p;q=q*10)
{
y1=x%t;
z=x/t;
CAPITOLUL 4. OJI 2020 4.2. TAI 42
y2=z%q;
y3=z/q;
for (d=2;d*d<=y1;d++)
if (y1%d==0) break;
if (y1>1&&d*d>y1&& y1>max1)
max1=y1;
for (d=2;d*d<=y2;d++)
if (y2%d==0) break;
if (y2>1&&d*d>y2&& y2>max1)
max1=y2;
for (d=2;d*d<=y3;d++)
if (y3%d==0) break;
if (y3>1&&d*d>y3&& y3>max1)
max1=y3;
}
}
g<<max1<<"\n";
}
return 0;
}
ifstream in("tai.in");
ofstream out("tai.out");
int prim(int x)
{
int ok,d;
ok=1;
if(x<=1)ok=0;
for(d=2;d*d<=x&&ok;++d)
if(x%d==0) ok=0;
return ok;
}
int main()
{
int N,i,x,ok,xmax=0,C,d,y,x1,x2,p,p2,x21,x22;
in>>C>>N;
if(C==1)
{
for(i=1;i<=N;++i)
{
in>>x;
if(prim(x))if(x>xmax)xmax=x;
}
out<<xmax;
}
if(C==2)
{
for(i=1;i<=N;++i)
{
in>>y;
p=10;
while(p<y)
{
x1=y/p;
x2=y%p;
if(prim(x1))
if(x1>xmax) xmax=x1;
if(prim(x2))if(x2>xmax)xmax=x2;
p=p*10;
}
CAPITOLUL 4. OJI 2020 4.2. TAI 43
}
out<<xmax;
}
if(C==3)
{
for(i=1;i<=N;++i)
{
in>>y;
p=100;
while(p<y)
{
x1=y/p;
x2=y%p;
if(prim(x1))
if(x1>xmax) xmax=x1;
p2=10;
while(p2<x2)
{
x21=x2/p2;
x22=x2%p2;
if(prim(x21))
if(x21>xmax) xmax=x21;
if(prim(x22))
if(x22>xmax) xmax=x22;
p2=p2*10;
}
p=p*10;
}
}
out<<xmax;
}
return 0;
}
int Prim(int n)
{
if (n <= 1) return 0;
if (n == 2) return 1;
if (n % 2 == 0) return 0;
for (int i = 3; i * i <= n; i += 2)
if (n % i == 0) return 0;
return 1;
}
int main()
{
int x, n, task, p, q, M = 0;
ifstream fin("tai.in");
ofstream fout("tai.out");
if (task == 1)
{
while (n--)
{
fin >> x;
if (Prim(x) && x > M) M = x;
}
}
else if (task == 2)
{
while (n--)
{
CAPITOLUL 4. OJI 2020 4.2. TAI 44
fin >> x;
p = 10;
while (x / p > 0)
{
if (Prim(x / p) && M < x / p) M = x / p;
if (Prim(x % p) && M < x % p) M = x % p;
p *= 10;
}
}
}
else /// task = 3
{
while (n--)
{
fin >> x;
for (p = 100; x / p > 0; p *= 10)
for (q = 10; q < p; q *= 10)
{
if (Prim(x / p) && M < x / p) M = x / p;
if (Prim(x % p / q) && M < x % p / q) M = x % p / q;
if (Prim(x % q) && M < x % q) M = x % q;
}
}
}
ifstream f("tai.in");
ofstream g("tai.out");
int c,n,a;
bool eprim(int);
int nr_cifre(int);
int putere(int);
int main()
{
f>>c>>n;
if(c==1)
{
int sol=0;
for(int i=1; i<=n; i++)
{
f>>a;
if(eprim(a))
sol=max(sol,a);
}
g<<sol;
}
if(c==2)
{
int sol=0;
for(int i=1; i<=n; i++)
{
f>>a;
int cnt=nr_cifre(a)-1;
for(int j=1; j<=cnt; j++)
{
int aux=putere(j);
int b=a%aux,c=a/aux;
if(eprim(b))
sol=max(sol,b);
if(eprim(c))
sol=max(sol,c);
CAPITOLUL 4. OJI 2020 4.2. TAI 45
}
}
g<<sol;
}
if(c==3)
{
int sol=0;
for(int i=1; i<=n; i++)
{
f>>a;
int cnt=nr_cifre(a)-1;
for(int j=1; j<=cnt; j++)
{
int aux=putere(j);
int b=a%aux;
int c=a/aux;
if(b>=10)
{
int cntt=nr_cifre(b)-1;
for(int jj=1; jj<=cntt; jj++)
{
int auxx=putere(jj);
int bb=b%auxx;
int cc=b/auxx;
if(eprim(bb))
sol=max(sol,bb);
if(eprim(cc))
sol=max(sol,cc);
}
if(eprim(c)) sol=max(sol,c);
}
else
{
int cntt=nr_cifre(c)-1;
for(int jj=1; jj<=cntt; jj++)
{
int auxx=putere(jj);
int bb=c%auxx;
int cc=c/auxx;
if(eprim(bb))
sol=max(sol,bb);
if(eprim(cc))
sol=max(sol,cc);
}
if(eprim(b)) sol=max(sol,b);
}
}
}
g<<sol;
}
return 0;
}
bool eprim(int x)
{
if(x==1||x==0)
return false;
if(x==2)
return true;
if(x%2==0)
return false;
for(int i=3; i*i<=x; i+=2)
if(x%i==0)
return false;
return true;
}
int nr_cifre(int x)
{
int cnt=0;
while(x)
{
x/=10;
CAPITOLUL 4. OJI 2020 4.2. TAI 46
cnt++;
}
return cnt;
}
int putere(int x)
{
int p=1;
while(x)
{
p*=10;
x--;
}
return p;
}
ifstream f("tai.in");
ofstream g("tai.out");
return 1;
}
int main()
{
f>>c;
if(c==1)
{
f>>n;
for(i=1;i<=n;i++)
{
f>>x;
if(prim(x))
max_p=max(x,max_p);
}
if(max_p==1) max_p=0;
g<<max_p<<endl;
}
else
if(c==2)
{
f>>n;
for(i=1;i<=n;i++)
{
f>>x;
Nc=nrc(x);
CAPITOLUL 4. OJI 2020 4.2. TAI 47
for(int j=1;j<Nc;j++)
{
n1=x/pz[j];
n2=x%pz[j];
if(prim(n1)) max_p=max(max_p,n1);
if(prim(n2)) max_p=max(max_p,n2);
}
}
g<<max_p<<endl;
}
else
{
f>>n;
for(i=1;i<=n;i++)
{
f>>x;
Nc=nrc(x);
long long X=x;
for(int j=1;j<Nc-1;j++)
{
n3=x%pz[j];
x=x/pz[j];
int Nrc=Nc-j;
for(int k=1;k<Nrc;k++)
{
n2=x%pz[k];
n1=x/pz[k];
// g<<n1<<" "<<n2<<" "<<n3<<endl;
if(prim(n1)) max_p=max(max_p,n1);
if(prim(n2)) max_p=max(max_p,n2);
if(prim(n3)) max_p=max(max_p,n3);
}
x=X;
}
}
g<<max_p<<endl;
}
f.close();
g.close();
return 0;
}
OJI 2019
5.1 Aur
Problema 1 - Aur 90 de
puncte
După ce au mers ı̂mpreună prin lume, Păcală şi Tândală au strâns o căruţă plină de bănuţi
de aur, iar acum ı̂i răstoarnă pe toţi ı̂n curtea casei şi ı̂i ı̂mpart ı̂n N grămezi. Păcală numără
bănuţii din fiecare grămadă şi ı̂i dictează lui Tândală N numere naturale pe care acesta trebuie
să le scrie ı̂n ordine pe o tăbliţă. După ore bune de muncă, Păcală constată că Tândală a scris pe
un singur rând, ı̂n ordine, de la stânga la dreapta, toate numerele dictate de el, dar lipite unul de
altul. Acum pe tăbliţă e doar un şir lung de cifre. Ce să facă Păcală acum?
Cerinţe
Cunoscând cele N numere naturale dictate de Păcală, scrieţi un program care să determine:
1. numărul cifrelor scrise pe tăbliţă de Tândală;
2. ce-a de-a K-a cifră de pe tăbliţă, ı̂n ordine de la stânga la dreapta;
3. cel mai mare număr ce se poate forma cu exact P cifre alăturate de pe tăbliţă, considerate
ı̂n ordine de la stânga la dreapta.
Date de intrare
Date de ieşire
Fişierul aur.out va conţine pe prima linie un singur număr natural ce reprezintă rezultatul de-
terminat conform fiecărei cerinţe.
a 1 & N & 100000 şi 1 & K & 900000; Se garantează că există cel puţin K cifre scrise pe tăbliţă.
a 1 & P & 18; Se garantează ca există cel puţin P cifre scrise pe tăbliţă.
a toate numere dictate de Păcală sunt nenule şi au cel mult 9 cifre fiecare;
a Pentru rezolvarea corectă a primei cerinţe se acordă 20 de puncte, pentru rezolvarea corectă
a celei de-a doua cerinţe se acordă 30 de puncte, iar pentru rezolvarea corectă a celei de-a treia
cerinţe se acordă 40 de puncte.
48
CAPITOLUL 5. OJI 2019 5.1. AUR 49
Exemple
aur.in aur.out Explicaţii
1 12 Se rezolvă cerinţa 1.
7 Tândală a scris pe tăbliţă: 259134592799.
25 9 13 459 2 79 9 Numărul cifrelor scrise de Tândală este 12.
2 7 Se rezolvă cerinţa 2. N are valoarea 7 şi K are
7 10 valoarea 10. Pe tăbliţă este scris: 259134592799
25 9 13 459 2 79 9 Cea de-a zecea cifră este 7.
3 9279 Se rezolvă cerinţa 3. N are valoarea 7 şi P are valoarea 4.
74 Tândală a scris pe tăbliţă: 259134592799.
25 9 13 459 2 79 9 Cel mai mare număr format din patru cifre este 9279.
Cerinţa1 :
- pentru fiecare număr citit din fişier identificăm cifrele sale;
- utilizăm o variabilă de tip contor pentru numărarea cifrelor tuturor numerelor.
Cerinţa 2:
- pentru fiecare număr citit din fişier determinăm cifrele sale ı̂n ordine, de la stânga la dreapta;
- numărăm cifrele până ı̂n momentul ı̂n care variabila care le contorizează ajunge la valoare K.
Cerinţa 3
- considerăm toate secvenţele posibile formate din P cifre alăturate;
- cu cifrele fiecărei secvenţe construim un număr natural;
- calculăm cea mai mare valoare a unui număr natural construit anterior.
Gradul de dificultate
Cerinţa 1 - 2
Cerinta 2 - 3
Cerinta 3 - 4
ifstream fin("aur.in");
ofstream fout("aur.out");
int main()
{
int p;
fin>>p;
if(p==1)
{
int n,nr=0;
char c;
fin>>n;
while(fin>>c)
if(c!=’ ’) nr++;
CAPITOLUL 5. OJI 2019 5.1. AUR 50
fout<<nr;
}
if(p==2)
{
int n,k,nr=0;
char c,a;
fin>>n>>k;
while(fin>>c)
{
if(c!=’ ’) nr++;
if(nr==k) a=c;
}
fout<<a;
}
if(p==3)
{
unsigned long long n, k, maxx=0, v, y=0, nr=0;
char c;
fin>>n>>k;
while(fin>>c)
{
if(c!=’ ’)
{
v=(int)c-48;
y=y*10+v;
}
nr++;
if(nr==k)
{
if(y>maxx) maxx=y;
y=y%f1;
nr--;
}
}
fout<<maxx;
}
return 0;
}
ifstream f("aur.in");
ofstream g("aur.out");
int main()
{
char c,cifraK;
int nr_cif=0,cerinta,K,N,i,P;
f>>cerinta>>N;
if (cerinta==2) f>>K;
else
if (cerinta==3) f>>P;
if (cerinta==1)
CAPITOLUL 5. OJI 2019 5.1. AUR 51
{
while(f>>c)
nr_cif++;
g<<nr_cif<<’\n’;
}
else
if (cerinta==2)
while(f>>c)
{
nr_cif++;
if (nr_cif==K)
{
g<<c<<’\n’;
break;
}
}
else
{
for(i=1; i<P; i++)
{
f>>c;
nr=nr*10+(c-’0’);
p=p*10;
}
nr_max=nr;
while(f>>c)
{
nou=(nr%p)*10+(c-’0’);
if(nou>nr_max) nr_max=nou;
nr=nou;
}
g<<nr_max<<’\n’;
}
return 0;
}
ifstream f("aur.in");
ofstream g("aur.out");
int main()
{
f>>c;
if(c==1)
{
f>>N;
cate=0;
for(i=1; i<=N; i++)
{
f>>x;
while(x)
{
cate++;
x /= 10;
}
}
g<<cate<<" \n";
}
else
if(c==2)
{
f>>N>>K;
nr=0;
for (i=1; i<=N; i++)
CAPITOLUL 5. OJI 2019 5.1. AUR 52
{
f>>x;
y=x;
p=1;
while (p<=y)
p *= 10;
p /= 10;
y=x;
while(p>=1)
{
nr++;
cif = y / p %10;
p /= 10;
if(nr == K)
{
g<<cif<<"\n";
return 0;
}
}
}
}
else
{
f>>N>>P;
q=1;
nr=0;
t=0;
maxf=0;
while(p<=y)
p *= 10;
p /= 10;
y=x;
while(p>=1)
{
nr++;
cif = y / p %10;
t = t % q;
t= t*10 + cif;
p /= 10;
if(nr == K)
{
maxf=t;
}
else
if(nr>K)
{
if(t > maxf) maxf=t;
}
}
}
g<<maxf;
}
return 0;
}
Etapa nr. 0:
CAPITOLUL 5. OJI 2019 5.1. AUR 53
ifstream fin("aur.in");
ofstream fout("aur.out");
int C, N, K, P;
int nr; // cate un numar pe randul 3 (din cele N numere)
int nc; // numarul cifrelor scrise pe tablita
int ck; // cifra K scrisa pe tablita
int nrmaxp; // nr max format cu P cifre
void rezolva1()
{
void rezolva2()
{
void rezolva3()
{
int main()
{
fin>>C;
cout<<"C = "<<C<<"\n";
return 0;
}
Etapa nr. 1:
Listing 5.1.5: Aur - Etapa nr. 1
#include<iostream>
#include<fstream>
ifstream fin("aur.in");
ofstream fout("aur.out");
int C, N, K, P;
int nr; // cate un numar pe randul 3 (din cele N numere)
int nc; // numarul cifrelor scrise pe tablita
int ck; // cifra K scrisa pe tablita
int nrmaxp; // nr max format cu P cifre
void rezolva1()
{
fin>>N;
cout<<"N = "<<N<<"\n";
nc=0;
fout.close();
}
void rezolva2()
{
void rezolva3()
{
int main()
{
fin>>C;
cout<<"C = "<<C<<"\n";
return 0;
}
Etapa nr. 2:
Listing 5.1.6: Aur - Etapa nr. 2
#include<iostream>
#include<fstream>
ifstream fin("aur.in");
ofstream fout("aur.out");
int C, N, K, P;
int nr; // cate un numar pe randul 3 (din cele N numere)
int nc; // numarul cifrelor scrise pe tablita
int ck; // cifra K scrisa pe tablita
int nrmaxp; // nr max format cu P cifre
void rezolva1()
{
fin>>N;
cout<<"N = "<<N<<"\n";
nc=0;
void rezolva2()
{
fin>>N;
cout<<"N = "<<N<<"\n";
fin>>K;
cout<<"K = "<<K<<"\n";
nc=0;
}
cout<<"ch = "<<ch<<"\n";
fout<<ch<<’\n’;
fout.close();
}
void rezolva3()
{
int main()
{
fin>>C;
cout<<"C = "<<C<<"\n";
return 0;
}
Etapa nr. 3:
Listing 5.1.7: Aur - Etapa nr. 3
#include<iostream>
#include<fstream>
ifstream fin("aur.in");
ofstream fout("aur.out");
int C, N, K, P;
int nr; // cate un numar pe randul 3 (din cele N numere)
int nc; // numarul cifrelor scrise pe tablita
int ck; // cifra K scrisa pe tablita
long long nrmaxp; // nr max format cu P cifre
void rezolva1()
{
fin>>N;
cout<<"N = "<<N<<"\n";
nc=0;
void rezolva2()
{
fin>>N;
cout<<"N = "<<N<<"\n";
fin>>K;
cout<<"K = "<<K<<"\n";
nc=0;
fout<<ch<<’\n’;
fout.close();
}
void rezolva3()
{
fin>>N;
cout<<"N = "<<N<<"\n";
fin>>P;
cout<<"P = "<<P<<"\n";
// nr1 = c_1 c_2 ... c_p ---> nrnou = c_2 c_3 ...c_p c_{p+1}
// c_2 c_3 ... c_p = restul impartirii lui nr1 la prod10p_1
// = 10*10*...*10 de p-1 ori
nrmaxp=nr1;
while(fin>>ch)
{
if(ch>=’0’ && ch<=’9’)
{
nr1=(nr1 % prod10p_1)*10 + (ch-’0’);
if(nr1 > nrmaxp) nrmaxp=nr1;
}
}
cout<<"nrmaxp = "<<nrmaxp<<"\n";
fout<<nrmaxp<<’\n’;
fout.close();
}
int main()
{
fin>>C;
cout<<"C = "<<C<<"\n";
return 0;
}
ifstream fin("aur.in");
ofstream fout("aur.out");
int C, N, K, P;
int nr; // cate un numar pe randul 3 (din cele N numere)
int nc; // numarul cifrelor scrise pe tablita
int ck; // cifra K scrisa pe tablita
long long nrmaxp; // nr max format cu P cifre
void rezolva1()
{
CAPITOLUL 5. OJI 2019 5.1. AUR 57
fin>>N;
//cout<<"N = "<<N<<"\n";
nc=0;
void rezolva2()
{
fin>>N;
//cout<<"N = "<<N<<"\n";
fin>>K;
//cout<<"K = "<<K<<"\n";
nc=0;
void rezolva3()
{
fin>>N;
//cout<<"N = "<<N<<"\n";
fin>>P;
//cout<<"P = "<<P<<"\n";
// nr1 = c_1 c_2 ... c_p ---> nrnou = c_2 c_3 ...c_p c_{p+1}
// c_2 c_3 ... c_p = restul impartirii lui nr1 la prod10p_1
// = 10*10*...*10 de p-1 ori
nrmaxp=nr1;
while(fin>>ch)
{
if(ch>=’0’ && ch<=’9’)
{
nr1=(nr1 % prod10p_1)*10 + (ch-’0’);
if(nr1 > nrmaxp) nrmaxp=nr1;
}
}
//cout<<"nrmaxp = "<<nrmaxp<<"\n";
fout<<nrmaxp<<’\n’;
fout.close();
}
int main()
CAPITOLUL 5. OJI 2019 5.1. AUR 58
{
fin>>C;
//cout<<"C = "<<C<<"\n";
return 0;
}
ifstream fin("aur.in");
ofstream fout("aur.out");
int C, N, K, P;
int nr; // cate un numar pe randul 3 (din cele N numere)
int nc; // numarul cifrelor scrise pe tablita
int ck; // cifra K scrisa pe tablita
long long nrmaxp; // nr max format cu P cifre
void rezolva1()
{
fin>>N;
nc=0;
void rezolva2()
{
fin>>N;
fin>>K;
nc=0;
void rezolva3()
{
fin>>N;
fin>>P;
// nr1 = c_1 c_2 ... c_p ---> nrnou = c_2 c_3 ...c_p c_{p+1}
// c_2 c_3 ... c_p = restul impartirii lui nr1
// la prod10p_1 = 10*10*...*10 de p-1 ori
fin>>ch;
nr1=nr1*10+(ch-’0’);
}
nrmaxp=nr1;
while(fin>>ch)
{
if(ch>=’0’ && ch<=’9’)
{
nr1=(nr1 % prod10p_1)*10 + (ch-’0’);
if(nr1 > nrmaxp) nrmaxp=nr1;
}
}
fout<<nrmaxp<<’\n’;
fout.close();
}
int main()
{
fin>>C;
if(C==1) {rezolva1(); return 0;}
if(C==2) {rezolva2(); return 0;}
if(C==3) {rezolva3(); return 0;}
return 0;
}
5.2 Cartele
Problema 2 - cartele 90 de
puncte
Într-o şcoală există un sistem de acces cu ajutorul cartelelor, conectat la un calculator şi
o imprimantă. Fiecare elev al şcolii are câte o cartelă. Într-o zi, la utilizarea fiecărei cartele,
sistemul imprimă următoarele informaţii pe hârtie, pe câte o linie, după regula următoare:
- Caracterul b dacă elevul este băiat sau caracterul f dacă este fată. Caracterul va fi urmat de
un spaţiu;
- Caracterul i dacă elevul a intrat ı̂n şcoală sau caracterul e dacă a ieşit din şcoală. De
asemenea, acest caracter va fi urmat de un spaţiu;
- Momentul utilizării cartelei, exprimat prin oră, minute şi secunde. Acestea vor fi reprezentate
ı̂n cadrul liniei, exact ı̂n această ordine, prin trei numere naturale, separate ı̂ntre ele prin câte un
spaţiu.
Cerinţe
Date de intrare
Fişierul de intrare cartele.in conţine pe prima linie un număr natural C reprezentând numărul
cerinţei care poate avea valorile 1, 2 sau 3, pe a doua linie numărul natural N, iar pe următoarele
N linii informaţiile imprimate de sistem sub forma descrisă ı̂n enunţ, ı̂n ordinea strict crescătoare
a momentului folosirii cartelei.
Date de ieşire
Dacă C = 1, atunci fişierul de ieşire cartele.out va conţine, ı̂n această ordine, separate printr-un
spaţiu, numărul de băieţi şi numărul de fete determinat conform cerinţei 1.
Dacă C = 2 sau C = 3, atunci fişierul de ieşire cartele.out va conţine pe prima linie un singur
număr natural ce reprezintă rezultatul determinat conform cerinţei.
CAPITOLUL 5. OJI 2019 5.2. CARTELE 60
Exemple
Descrierea soluţiei
Se vor citi datele ı̂n formatul specificat şi se vor transforma ı̂n secunde momentele fiecărei
acţiuni.
Cerinţa 1:
CAPITOLUL 5. OJI 2019 5.2. CARTELE 61
- se actualizează numărul de băieţi şi fete ı̂n funcţie de acţiune (intrare sau ieşire) şi se afişează
valorile finale, obţinute după a N -a linie citită.
Cerinţa 2 :
- ı̂n timpul parcurgerii se reactualizează numărul de băieţi şi fete ı̂n funcţie de acţiune (intrare
sau ieşire), vom determina durata de timp curentă care are proprietatea cerută (număr egal de
fete şi băieţi prezenţi ı̂n şcoală, număr nenul) şi adunăm perioadele determinate.
Cerinţa 3:
- ı̂n timpul parcurgerii se actualizează numărul de băieţi şi fete prezenţi ı̂n şcoală, ı̂n funcţie
de acţiune (intrare sau ieşire). Vom determina durata neı̂ntreruptă de timp curentă care are
proprietatea cerută şi vom afişa maximul acestora.
Se folosesc tipurile de date caracter şi ı̂ntregi (char/int respectiv char/integer) apoi se simulează
acţiunile descrise ı̂n secvenţe strict crescătoare de timpi.
Gradul de dificultate
Cerinţa 1 - 2
Cerinţa 2 - 3
Cerinţa 3 - 4
int main()
{
ifstream f("cartele.in");
ofstream g("cartele.out");
short int C;
f>>C;
if(C==1)
{
int nr_Fete=0,nr_Baieti=0;
char c,c1;
int nr,h,m,s;
f>>nr;
if(c==’f’)
{
if(c1==’e’)
nr_Fete--;
else
nr_Fete++;
}
else
{
if(c1==’e’)
nr_Baieti--;
else
nr_Baieti++;
}
}
g<<nr_Baieti<<" "<<nr_Fete;
}
if(C==2)
{
int nr_Fete=0,nr_Baieti=0;
CAPITOLUL 5. OJI 2019 5.2. CARTELE 62
char c,c1;
int nr,s1,s2,h,m,s,timp_total=0;
f>>nr;
bool era_egal=false;
if(c==’f’)
{
if(c1==’e’)
nr_Fete--;
else
nr_Fete++;
}
else
{
if(c1==’e’)
nr_Baieti--;
else
nr_Baieti++;
}
if(i==1)
{
s1=0;
s1+=h*3600;
s1+=m*60;
s1+=s;
}
else
{
s2=0;
s2+=h*3600;
s2+=m*60;
s2+=s;
if(era_egal)
timp_total+=s2-s1;
s1=s2;
}
}
g<<timp_total;
}
if(C==3)
{
int nr_Baieti=0,nr,s1=0,s2,timp_maxim=0;
char c,c1;
int h,m,s;
f>>nr;
if(nr_Baieti%2==1)
era_impar=true;
if(c==’b’)
{
if(c1==’e’)
nr_Baieti--;
else
nr_Baieti++;
}
if(nr_Baieti%2==1&&s1==0)
CAPITOLUL 5. OJI 2019 5.2. CARTELE 63
{
s1+=h*3600;
s1+=m*60;
s1+=s;
}
else
{
s2=0;
s2+=h*3600;
s2+=m*60;
s2+=s;
if(era_impar&&nr_Baieti%2==0)
{
if(s2-s1>timp_maxim)
timp_maxim=s2-s1;
s1=0;
}
}
}
g<<timp_maxim;
}
}
ifstream f("cartele.in");
ofstream g("cartele.out");
int maxim,sec1,sec,p,h,m,s,h1,m1,s1,i,N,max1,cb,cf,suma;
char c,a;
int main()
{
f>>p;
f>>N;
if (p==1)
{
cb=0;
cf=0;
for (i = 1; i <= N; i++)
{
f>>c>>a>>h>>m>>s;
if (c==’b’)
if (a==’i’) cb++;
else cb--;
else
if (a==’i’) cf++;
else cf--;
}
g<<cb<<" "<<cf<<"\n";
}
else
if (p==2)
{
f>>c>>a>>h1>>m1>>s1;
sec1=h1*3600+m1*60+s1;
if (c==’b’) cb=1,cf=0;
else cb=0,cf=1;
suma=0;
for (i = 2; i <= N; i++)
{
f>>c>>a>>h>>m>>s;
sec=h*3600+m*60+s;
CAPITOLUL 5. OJI 2019 5.2. CARTELE 64
if (c==’b’)
if (a==’i’) cb++;
else cb--;
else
if (a==’i’) cf++;
else cf--;
sec1=sec;
}
g<<suma<<"\n";
}
else
{
f>>c>>a>>h1>>m1>>s1;
maxim=0;
for (i = 2; i <= N; i++)
{
f>>c>>a>>h>>m>>s;
sec=h*3600+m*60+s;
if (c==’b’)
{
if (cb%2!=0 && sec-sec1 > maxim) maxim=sec-sec1;
if (a==’i’) cb++; else cb--;
sec1=sec;
}
else
if (a==’i’) cf++; else cf--;
}
g<<maxim<<"\n";
}
return 0;
}
Etapa nr. 0:
ifstream fin("cartele.in");
ofstream fout("cartele.out");
int C, N;
char elev; // ’b’ sau ’f’
char inout; // ’i’ sau ’e’
int ora, minut, sec;
void rezolva1()
{
void rezolva2()
{
CAPITOLUL 5. OJI 2019 5.2. CARTELE 65
void rezolva3()
{
int main()
{
fin>>C;
cout<<"C = "<<C<<"\n";
return 0;
}
Etapa nr. 1:
Listing 5.2.4: Cartele - Etapa nr. 1
#include<iostream>
#include<fstream>
ifstream fin("cartele.in");
ofstream fout("cartele.out");
int C, N;
unsigned char elev; // ’b’ sau ’f’
unsigned char inout; // ’i’ sau ’e’
int ora, minut, sec;
void citesteCartela()
{
fin>>elev;
fin>>inout;
fin>>ora;
fin>>minut;
fin>>sec;
cout<<elev<<" "<<inout<<" "<<ora<<" "<<minut<<" "<<sec<<"\n";
}
void rezolva1()
{
fin>>N;
cout<<"N = "<<N<<"\n";
nrb=0;
nrf=0;
if(elev==’b’)
{
if(inout==’i’) nrb=nrb+1; else nrb=nrb-1;
}
else
if(elev==’f’)
{
if(inout==’i’) nrf=nrf+1; else nrf=nrf-1;
}
}
fout<<nrb<<" "<<nrf<<’\n’;
fout.close();
}
void rezolva2()
{
void rezolva3()
{
int main()
{
fin>>C;
cout<<"C = "<<C<<"\n";
return 0;
}
Etapa nr. 2:
Listing 5.2.5: Cartele - Etapa nr. 2
#include<iostream>
#include<fstream>
ifstream fin("cartele.in");
ofstream fout("cartele.out");
int C, N;
unsigned char elev; // ’b’ sau ’f’
unsigned char inout; // ’i’ sau ’e’
int ora, minut, sec;
void citesteCartela()
{
fin>>elev;
fin>>inout;
fin>>ora;
fin>>minut;
fin>>sec;
cout<<elev<<" "<<inout<<" "<<ora<<" "<<minut<<" "<<sec<<"\n";
}
void rezolva1()
{
fin>>N;
cout<<"N = "<<N<<"\n";
nrb=0;
nrf=0;
if(elev==’b’)
{
if(inout==’i’) nrb=nrb+1; else nrb=nrb-1;
}
else
if(elev==’f’)
CAPITOLUL 5. OJI 2019 5.2. CARTELE 67
{
if(inout==’i’) nrf=nrf+1; else nrf=nrf-1;
}
}
void rezolva2()
{
nrtotsec=0;
fin>>N;
cout<<"N = "<<N<<"\n";
nrb=0;
nrf=0;
bool adunTimp=false;
int timp1, timp2;
if(elev==’b’)
{
if(inout==’i’) nrb=nrb+1; else nrb=nrb-1;
}
else
if(elev==’f’)
{
if(inout==’i’) nrf=nrf+1; else nrf=nrf-1;
}
if(adunTimp) nrtotsec=nrtotsec+(timp2-timp1);
timp1=timp2;
if(nrb==nrf && nrb>0) adunTimp=true; else adunTimp=false;
}
cout<<"nrtotsec = "<<nrtotsec<<"\n";
fout<<nrtotsec<<’\n’;
fout.close();
}
void rezolva3()
{
int main()
{
fin>>C;
cout<<"C = "<<C<<"\n";
return 0;
}
Etapa nr. 3:
Listing 5.2.6: Cartele - Etapa nr. 3
#include<iostream>
#include<fstream>
CAPITOLUL 5. OJI 2019 5.2. CARTELE 68
ifstream fin("cartele.in");
ofstream fout("cartele.out");
int C, N;
unsigned char elev; // ’b’ sau ’f’
unsigned char inout; // ’i’ sau ’e’
int ora, minut, sec;
void citesteCartela()
{
fin>>elev;
fin>>inout;
fin>>ora;
fin>>minut;
fin>>sec;
cout<<elev<<" "<<inout<<" "<<ora<<" "<<minut<<" "<<sec<<"\n";
}
void rezolva1()
{
fin>>N;
cout<<"N = "<<N<<"\n";
nrb=0;
nrf=0;
if(elev==’b’)
{
if(inout==’i’) nrb=nrb+1; else nrb=nrb-1;
}
else
if(elev==’f’)
{
if(inout==’i’) nrf=nrf+1; else nrf=nrf-1;
}
}
void rezolva2()
{
nrtotsec=0;
fin>>N;
cout<<"N = "<<N<<"\n";
nrb=0;
nrf=0;
bool adunTimp=false;
int timp1, timp2;
if(elev==’b’)
{
if(inout==’i’) nrb=nrb+1; else nrb=nrb-1;
}
else
if(elev==’f’)
CAPITOLUL 5. OJI 2019 5.2. CARTELE 69
{
if(inout==’i’) nrf=nrf+1; else nrf=nrf-1;
}
if(adunTimp) nrtotsec=nrtotsec+(timp2-timp1);
timp1=timp2;
if(nrb==nrf && nrb>0) adunTimp=true; else adunTimp=false;
}
cout<<"nrtotsec = "<<nrtotsec<<"\n";
fout<<nrtotsec<<’\n’;
fout.close();
}
void rezolva3()
{
nrmaxsec=0;
fin>>N;
cout<<"N = "<<N<<"\n";
nrb=0;
cout<<"nrmaxsec = "<<nrmaxsec<<"\n";
fout<<nrmaxsec<<’\n’;
fout.close();
}
int main()
{
fin>>C;
cout<<"C = "<<C<<"\n";
return 0;
}
OJI 2018
6.1 Patrate
Problema 1 - Patrate 90 de puncte
Un elev a desenat un set format din mai multe pătrate care conţin numere naturale nenule,
distincte, consecutive, dispuse ı̂n număr egal pe laturi. Pe latura fiecărui pătrat sunt scrise un
număr impar de valori. În fiecare pătrat, numerele sunt scrise ı̂n ordine crescătoare parcurgând
laturile sale, ı̂ncepând din colţul stânga-jos, ı̂n sensul invers al acelor de ceasornic. Elevul a
numerotat pătratele cu 1, 2, 3 etc., ı̂n ordinea strict crescătoare a numărului de valori conţinute
de fiecare. Diferenţa dintre cel mai mic număr din pătratul P 1 $ P şi cel mai mare număr din
pătratul P 1 este egală cu 1. Primele patru pătrate sunt:
Cerinţe
Date de intrare
Fişierul de intrare patrate.in conţine pe prima linie un număr natural C reprezentând cerinţa
din problemă care trebuie rezolvată (1 sau 2). Dacă C 1, atunci fişierul conţine pe a doua linie
numărul natural M . Dacă C 2, atunci fişierul conţine pe a doua linie numărul natural N .
Date de ieşire
71
CAPITOLUL 6. OJI 2018 6.1. PATRATE 72
Exemple
patrate.in patrate.out Explicaţii
1 24 Cerinţa este 1. Pătratul numerotat cu M 3 conţine
3 K 24 de numere naturale (vezi figura din enunţ).
2 4 Cerinţa este 2. Numărul N 73 este conţinut de pătratul
73 K 24 numerotat cu T 4 (vezi figura din enunţ).
Descrierea soluţiei
int N,C,K,M,T;
int main()
{
CAPITOLUL 6. OJI 2018 6.1. PATRATE 73
ifstream in("patrate.in");
ofstream out("patrate.out");
in>>C;
if(C==1)
{
in>>M;
out<<8*M<<endl;
}
else
{
in>>N;
T=sqrt(N);
if(T%2)T++;
out<<T/2<<endl;
}
return 0;
}
ifstream f("patrate.in");
ofstream g("patrate.out");
int main()
{
int N,C,M,T,K,nr=0;
f>>C;
if(C==1)
{
f>>M;
K=8*M;
g<<K<<endl;
}
else
{
f>>N;
T=0;
nr=0;
while(8*(T+1)<=N-nr)
{
++T;
K=8*T;
nr=nr+K;
}
if(N>nr){ ++T; }
g<<T<<endl;
}
return 0;
}
ifstream f("patrate.in");
ofstream g("patrate.out");
int main()
{
f>>c;
if(c==1)
CAPITOLUL 6. OJI 2018 6.2. FORUS 74
{
f>>M;
g<<8*M;
}
else
{
f>>N;
k=8;
T=1;
while(N-k>0)
{
N=N-k;
k=k+8;
T++;
}
g<<T;
}
return 0;
}
int main()
{ int m, cer, n;
long long t,x;
ifstream f("patrate.in");
ofstream g("patrate.out");
f>>cer>>n;
if(cer==1)
g<<8*n<<endl;
else
{
if(n<8) g<<1<<endl;
else
{
m=1; t=0; x=0;
while(t<n)
{
t=8*(m+x);
x+=m;
m++;
}
g<<m-1<<endl;
}
}
return 0;
}
6.2 forus
Problema 2 - forus 90 de puncte
La ora de educaţie tehnologică a clasei a V-a profesorul Forus, pasionat de matematică, a adus
pentru fiecare dintre cei N elevi câte un carton pe care este scris câte un număr natural nenul.
Fiecare elev poate folosi cartonul aşa cum l-a primit sau poate să taie o singură dată cartonul
ı̂ntre două cifre şi să lipească partea stângă la finalul părţii drepte. Elevul NU are voie să facă
o tăietură ı̂n faţa cifrei 0, deci niciunul dintre numerele obţinute NU poate să ı̂nceap cu cifra
0. Dintre toate numerele pe care le poate obţine, elevul ı̂l alege pe cel care are număr minim de
CAPITOLUL 6. OJI 2018 6.2. FORUS 75
divizori, iar dacă poate obţine mai multe astfel de numere, l alege pe cel mai mic dintre ele. La
sfârşitul orei, profesorul strânge cartoanele cu numerele alese, ı̂n ordinea distribuirii lor.
De exemplu, dacă iniţial elevul primeşte cartonul cu numărul 25082 atunci el are doar
următoarele trei variante de tăiere şi lipire:
Cerinţe
Scrieţi un program care citeşte numărul natural N şi cele N numere scrise pe cartoanele aduse
de profesorul Forus, apoi rezolvă următoarele două cerinţe:
1. determină numărul de cartoane pe care elevii au voie să le taie de oriunde (NU conţin cifre
ı̂n faţa cărora NU au voie să taie);
2. determină, ı̂n ordinea strângerii cartoanelor, numerele preluate de către profesorul Forus la
finalul orei.
Date de intrare
Fişierul de intrare forus.in conţine pe prima linie un număr natural C reprezentând cerinţa
din problemă care trebuie rezolvată (1 sau 2). A doua linie din fişier conţine un număr natural N ,
reprezentând numărul de elevi, iar a treia linie din fişier conţine N numere naturale, separate prin
câte un spaţiu, reprezentând numerele scrise pe cartoanele aduse de profesor, ı̂n ordinea distribuirii
lor.
Date de ieşire
Dacă C 1, fişierul de ieşire forus.out conţine pe prima linie un număr natural reprezentând
răspunsul la cerinţa 1.
Dacă C 2, fişierul de ieşire forus.out conţine pe prima linie N numere naturale, separate
prin câte un spaţiu, reprezentând răspunsul la cerinţa 2; numerele sunt scrise ı̂n ordinea ı̂n care
au fost strânse.
a 2 & N & 30
a 1 & numărul natural de pe carton $ 1000000000
a Pentru rezolvarea corectă a cerinţei 1 se acordă 20 de puncte; pentru rezolvarea corectă a
cerinţei 2 se acordă 70 de puncte. Se acordă 10 puncte din oficiu.
Exemple
Descrierea soluţiei
Cerinţa 1. Pentru fiecare număr citit, se verifică dacă conţine cel puţin o cifră de 0 ı̂n scrierea
sa. Se vor contoriza numerele citite care nu conţin cifra 0.
Cerinţa 2. Pentru fiecare număr citit se construiesc prin permutări circulare la dreapta cu
o poziţie toate numerele posibile. Dintre acestea se va alege numărul cu un număr minim de
divizori, cu observaţia că numărul ales trebuie să aibă acelaşi număr de cifre ca şi numărul iniţial
(nu am voie să tai ı̂naintea cifrei 0). Vom genera toate aceste numerele care se pot forma şi vom
calcula numărul de divizori, reţinând de fiecare dată pe cel cu număr minim de divizori, iar ı̂n caz
de egalitate a numărului de divizori ı̂l vom reţine pe cel mai mic.
ifstream f("forus.in");
ofstream g("forus.out");
int nrdiv(int N)
{
int d, nrd=1;
for(d=1;d*d<N;d++)
if(N%d==0)nrd+=2;
if(d*d==N) ++nrd;
return nrd;
}
int main()
{
int C,N,nr;
f>>C>>N;
if(C==1)
{
int r=0,ok;
for(int i=1; i<=N; i++)
{
f>>nr;
//cout<<nr<<" ";
ok=1;
while(nr && ok)
CAPITOLUL 6. OJI 2018 6.2. FORUS 77
{
if (nr%10==0)ok=0;
nr=nr/10;
}
r=r+ok;
}
g<<r<<endl;
}
else
{
int y,p,nrc,x,pr,ult,pu,xmin,nrdm,nrd,z;
for(int i=1; i<=N; i++)
{
f>>nr;
p=1;nrc=1;pu=10;
xmin=nr; nrdm=nrdiv(nr);
x=nr;
while(x>0)
{
x=x/10;
p=p*10;
nrc++;
}
p=p/10;z=p;
for(int i=1; i<nrc; i++)
{
pr=nr/p;
ult=nr%p;
x=ult*pu+pr;
if(x/z>0)
{
nrd=nrdiv(x);
if(nrd<nrdm)
{
xmin=x;
nrdm=nrd;
}
else
if(nrd==nrdm) xmin=min(xmin,x);
}
pu=pu*10;
p=p/10;
}
g<<xmin<<" ";
}
g<<endl;
}
return 0;
}
#include <bits/stdc++.h>
ifstream fin("forus.in");
ofstream fout("forus.out");
int nr_div(int x)
{
int p,d=2,N=1;
while(x>1)
{
p=0;
while(x%d==0)
{
p++;
x/=d;
}
if(p)N*=(p+1);
if(d*d<x) d++;
CAPITOLUL 6. OJI 2018 6.2. FORUS 78
else d=x;
}
return N;
}
int main()
{
int n,x,cer;
fin>>cer>>n;
if(cer==1)
{
int nr=0,nc,n0;
for(; n; n--)
{
fin>>x;
nc=0,n0=0;
if(x==0) nr++;
while(x)
{
if(x%10==0) n0++;
nc++;
x/=10;
}
if(n0==0) nr++;
}
fout<<nr;
}
else
{
int nc;
long long put,nrmax=0,val,nrc;
for(; n; n--)
{
fin>>x;
nc=log10(x);
put=pow10(nc);
nrmax=nr_div(x);
val=x;
int main()
CAPITOLUL 6. OJI 2018 6.2. FORUS 79
{
ifstream f("forus.in");
ofstream g("forus.out");
f>>c;
if(c==1)
{
f>>n;
r=0;
for(i=1;i<=n;i++)
{
f>>x;
ok=1;
while(x>0 && ok)
if(x%10==0) ok=0;
else x/=10;
if(ok) r++;
}
g<<r;
}
else
{
f>>n;
for(i=1;i<=n;i++)
{
f>>x;
if(x<10)
g<<x<<’ ’;
else
{
y=x;
mx=1000000000;
nc=0;
p=1;
while(x)
{
nc++;
x/=10;
p=p*10;
}
p=p/10;
x=y;
do
{
nd=0;
for(d=1;d*d<x;d++)
if(x%d==0) nd+=2;
if(d*d==x) nd++;
if(x/(p/10)%10==0)
{
nz=0;
y=p/10;
while(x/y%10==0 && y>1)
{
y=y/10;
nz++;
}
a=x/p;
x=x*10+a;
x=x%p;
CAPITOLUL 6. OJI 2018 6.2. FORUS 80
for(j=1;j<=nz;j++)
x=x*10;
nc=nc-nz;
}
else
{
a=x/p;
b=x%p;
x=b*10+a;
}
nc--;
} while(nc>0);
g<<r<<’ ’;
}
}
}
return 0;
}
ifstream f("forus.in");
ofstream g("forus.out");
int N,P,i,u,x,ok,k,t,cifre,minim,numar,pf,ps,p,ajt;
int main()
{
f>>P>>N;
if(P==1)
{
for(i=1; i<=N; i++)
{
f>>x;
ok=1;
while(x)
{
u=x%10;
if(u==0)
{
ok=0;
break;
}
x=x/10;
}
if(ok==1) k++;
}
g<<k;
}
if(P==2)
{
for(i=1; i<=N; i++)
{
f>>x;
t=x;
cifre=0;
while(t)
{
t=t/10;
cifre++;
}
t=x;
int prod=1,d,putere=0;
while(t%2==0)
{
t=t/2;
putere++;
CAPITOLUL 6. OJI 2018 6.2. FORUS 81
}
if(putere>0) prod=prod*(putere+1);
d=3;
while(t>1)
{
putere=0;
while(t%d==0)
{
t=t/d;
putere++;
}
if(putere>0)
prod=prod*(putere+1);
d=d+2;
if(d*d>t)
d=t;
}
minim=prod;
t=x;
numar=x;
k=cifre-1;
p=1;
while(k)
{
p*=10;
k--;
}
k=cifre-1;
while(k)
{
if(t%10!=0)
{
pf=t%10;
ps=t/10;
t=pf*p+ps;
prod=1,putere=0;
ajt=t;
while(t%2==0)
{
t=t/2;
putere++;
}
if(putere>0) prod=prod*(putere+1);
d=3;
while(t>1)
{
putere=0;
while(t%d==0)
{
t=t/d;
putere++;
}
if(putere>0) prod=prod*(putere+1);
d=d+2;
if(d*d>t) d=t;
}
if(prod<minim)
{
minim=prod;
numar=ajt;
}
if(prod==minim and ajt<numar)
{
numar=ajt;
}
t=ajt;
}
else
{
pf=t%10;
ps=t/10;
t=pf*p+ps;
}
k--;
}
CAPITOLUL 6. OJI 2018 6.2. FORUS 82
g<<numar<<" ";
}
}
return 0;
}
OJI 2017
7.1 numere
Problema 1 - numere 90 de puncte
Un copil construieşte un triunghi cu numerele naturale nenule astfel:
- ı̂n vârful triunghiului scrie valoarea 1;
- completează liniile triunghiului de sus ı̂n jos, iar căsuţele de pe aceeaşi linie de la stânga la
dreapta cu numere naturale consecutive, ca ı̂n figurile următoare.
În figura 1 este ilustrat un astfel de triunghi având 5 linii, conţinând numerele naturale de la
1 la 15. În acest triunghi copilul ı̂ncepe să construiască drumuri, respectând următoarele reguli:
- orice drum ı̂ncepe din 1;
- din orice căsuţă se poate deplasa fie ı̂n căsuţa situată pe linia următoare ı̂n stânga sa (deplasare
codificată cu 1), fie ı̂n căsuţa situată pe linia următoare ı̂n dreapta sa (deplasare codificată cu 2);
- orice drum va fi descris prin succesiunea deplasărilor efectuate.
De exemplu, drumul ilustrat ı̂n figura 2 poate fi descris astfel: 1222.
Cerinţe
Date de intrare
Fişierul de intrare numere.in conţine pe prima linie un număr natural C reprezentând cerinţa
din problemă care trebuie rezolvată (1 sau 2).
Dacă C este egal cu 1, a doua linie din fişier conţine un număr natural N , reprezentând
lungimea drumului, iar a treia linie din fişier conţine descrierea drumului sub forma a N valori, 1
sau 2, separate ı̂ntre ele prin câte un spaţiu.
Dacă C este egal cu 2, a doua linie din fişier conţine numărul natural K.
Date de ieşire
83
CAPITOLUL 7. OJI 2017 7.1. NUMERE 84
Fişierul de ieşire numere.out va conţine o singură linie pe care va fi scris un singur număr
natural. Dacă C 1, va fi scris numărul cu care se termină drumul descris ı̂n fişierul de intrare.
Dacă C 2, va fi scrisă suma maximă a numerelor aflate pe un drum care se termină cu numărul
K.
Exemple
numere.in numere.out Explicaţii
1 13 Cerinţa este 1. Drumul descris are lungimea 4 şi trece
4 prin numerele 1, 2, 5, 8, 13 .
1212
2 19 Cerinţa este 2. Suma maximă se obţine pe drumul
9 care trece prin numerele 1, 3, 6, 9 1 3 6 9 19.
Fie ultim - valoarea ultimului element de pe fiecare linie si l valoarea liniei cur
Initial ultim=1, l=0.
Cat timp ultim < K,incrementam linia, actualizam ultim cu ultim<-ultim+l, calculam
numerelor de linie.
Cand ultim>=K, elemc<-K
Repetat
-eliminam din suma s ultimul element de pe linia l si adunam elementul de pe poziti
-elemc<-elemc-l+1
-decrementam linia l
pana cand l=c
ifstream fin("numere.in");
ofstream fout("numere.out");
unsigned C,N,K,pas,curent,linie,rest,s,ultim;
int main()
{
fin>>C;
if(C==1)
{ fin>>N;curent=1;
for(linie=1;linie<=N;linie++)
{
fin>>pas;
curent+=linie;
if(pas==2)
curent++;
}
fout<<curent<<’\n’;
return 0;
}
///C=2
fin>>K;
while(ultim<K)
{
ultim+=++linie;
s+=ultim;
}
rest=ultim-K;
s-=rest*(rest+1)/2;
fout<<s<<’\n’;
return 0;
}
ifstream fin("numere.in");
ofstream fout("numere.out");
int c, n, K, nr, sum;
int main()
{
int lin, col, i, j, d, ultim;
fin>>c;
if (c==1)
{
fin>>n;
col=1;
for (i=0; i<n; i++)
{
fin>>d;
col+=d-1;
}
lin=n+1;
nr=lin*(lin-1)/2;//1+2+...lin-1
nr+=col;
fout<<nr<<’\n’;
}
else
{
fin>>K;
for (lin=1; K>lin*(lin+1)/2; lin++);
col=K-lin*(lin-1)/2;
sum=ultim=0;
for (i=1; i<=col; i++)
{
ultim+=i;
sum+=ultim;
}
for (i=col+1; i<=lin; i++)
{
CAPITOLUL 7. OJI 2017 7.1. NUMERE 86
ultim+=i;
sum+=(ultim-(i-col));
}
fout<<sum<<’\n’;
}
fout.close();
return 0;
}
int main()
{
ifstream in("numere.in");
ofstream out("numere.out");
int p,a,b,n,i,nr=1,lin,col;
in>>p;
if(p==1)
{
in>>n;
for(i=2;i<=n+1;i++)
{
in>>a;
if(a==1)
nr=nr+i-1;
else
nr=nr+i;
}
out<<nr<<endl;
}
if(p==2)
{
in>>nr;
a=1;lin=1;
while(a<nr)
{
lin++;
a=a+lin;
}
col=(a+nr)%lin;
a=1;
b=1;
for(i=2;i<=col;i++)
{
b=b+i;
a=a+b;
}
for(i=col;i<lin;i++)
{
b=b+i;
a=a+b;
}
out<<a;
}
in.close();
out.close();
return 0;
}
ifstream fin("numere.in");
ofstream fout("numere.out");
int main()
{
int C,N,nr,i,x;
fin>>C;
if(C==1)
{
fin>>N;nr=1;
for(i=1;i<=N;i++)
{
fin>>x;
if(x==1)
nr=nr+i;
else
nr=nr+i+1;
}
fout<<nr;
}
else
{
int n,S;
fin>>N;
n=1;
while(n*(n+1)/2<N)
n++;
S=N;
while(n*(n+1)/2!=N)
{
n--;
N=N-n;
S=S+N;
}
n--;
while(n>=1)
{
S=S+n*(n+1)/2;
n--;
}
fout<<S;
}
return 0;
}
ifstream fin("numere.in");
ofstream fout("numere.out");
int n,c,nr,i,k,x,s,a,b,j;
int main()
{
fin>>c;
if (c==1)
{
fin>>n;
nr=1;
for (i=1;i<=n;i++)
{
fin>>x;
if (x==1)
nr=nr+i;
else
nr=nr+i+1;
}
fout<<nr;
}
else
CAPITOLUL 7. OJI 2017 7.2. ROBOT 88
{
fin>>k;
i=1; a=1;
while (a<k)
{
a=i*(i+1)/2;
if (k>a)
i=i+1;
}
b=0;
a=(i-1)*i/2;
while (a<k)
{
a=a+1;
b=b+1;
}
for (j=1;j<=b;j++)
s=s+j*(j+1)/2;
for (j=b+1;j<=i-1;j++)
s=s+j*(j-1)/2+b;
s=s+k;
fout<<s;
}
return 0;
}
7.2 robot
Problema 2 - robot 90 de puncte
Paul doreşte să ı̂nveţe cum să programeze un robot. Pentru ı̂nceput s-a gândit să construiască
un robot format dintr-un mâner, 10 butoane aranjate circular şi un ecran. Pe butoane sunt scrise,
ı̂n ordine crescătoare, cifrele de la 0 la 9, ca ı̂n figură.
Instrucţiune Explicaţii
Dp Mânerul robotului se deplasează spre dreapta cu p poziţii (p este o cifră).
Sp Mânerul robotului se deplasează spre stânga cu p poziţii (p este o cifră).
A Este apăsat butonul ı̂n dreptul căruia se află mânerul robotului şi pe ecran
apare cifra scrisă pe buton.
T Terminarea programului (se utilizează o singură dată la final şi este precedată
de cel puţin o instrucţiune A).
Iniţial mânerul robotului este plasat ı̂n dreptul butonului 0, iar ecranul este gol.
De exemplu, ı̂n urma executării roboprogramului D4AS1AAD6AT robotul apasă butoanele pe
care sunt scrise cifrele 4, 3, 3, 9, iar pe ecran va apărea 4339.
Cerinţe
2. citeşte un roboprogram şi determină cifrele afişate pe ecran după executarea roboprogra-
mului;
3. citeşte un număr natural N şi construieşte un roboprogram de lungime minimă prin ex-
ecutarea căruia pe ecran se va obţine numărul N ; deoarece robotului ı̂i place să se deplaseze ı̂n
special spre dreapta, dacă există mai multe roboprograme de lungime minimă, se va afişa robo-
programul cu număr maxim de instrucţiuni D.
Date de intrare
Fişierul de intrare robot.in conţine pe prima linie un număr natural C, reprezentând cerinţa
care urmează să fie rezolvată (1, 2 sau 3). Dacă C 1 sau C 2, pe a doua linie a fişierului se
află un roboprogram. Dacă C 3, pe a doua linie a fişierului de intrare se află numărul natural
N.
Date de ieşire
Fişierul de ieşire robot.out va conţine o singură linie. Dacă C 1, pe prima linie se va scrie
un număr natural reprezentând numărul de cifre afişate pe ecran după executarea roboprogra-
mului din fişierul de intrare. Dacă C 2, pe prima linie vor fi scrise cifrele afişate pe ecran ı̂n
urma executării roboprogramului din fişierul de intrare. Dacă C 3, pe prima linie va fi scris
roboprogramul solicitat de cerinţa 3.
Exemple
Punctul 1
Punctul 2
Daca directia indicata este dreapta si deoarece manerul robotului se deplaseaza cir
numarul de pozitii efectuate va fi suma dintre pozitia (cifra curenta) si cifra ind
in program modulo 10 (avand in total 10 cifre). Daca directia indicata este dreapta
din cauza deplasarii circulare din pozitia curenta se scade cifra din roboprogram,
rezultatul este negativ, se aduna 10.
Punctul 3
Pentru numarul citit, instructiunile trebuie asociate incepand de la cifra cea mai
semnificativa spre cifra unitatilor si trebuie acordat atentie cifrelor 0 de la sfa
numarului dat (se determina oglinditul numarului si se retine numarul de zerouri de
sfarsitul numarului citit).
Daca numarul citit avea zerouri la sfarsitul numarului, se determina numarul de dep
necesare afisarii acestora si se introduc in roboprogram un numar de instructiuni A
numarul de zerouri calculate.
ifstream fin("robot.in");
ofstream fout("robot.out");
CAPITOLUL 7. OJI 2017 7.2. ROBOT 91
int cerinta, n;
int main()
{
char c;
int nr, st, dr, poz, zero, cat, cifra;
fin>>cerinta;
if(cerinta==1)
{
c=’*’; nr=0;
while (c!=’T’)
{
fin>>c;
if (c==’A’) nr++;
}
fout<<nr<<’\n’;
fout.close();
return 0;
}
if(cerinta==2)
{
c=’*’; nr=0; poz=0;
while (c!=’T’)
{
fin>>c;
if (c==’A’) fout<<poz;
else
if (c==’D’)
{
fin>>c;
cat=c-’0’;
poz=(poz+cat)%10;
}
else
if (c==’S’)
{
fin>>c;
cat=c-’0’;
poz-=cat;
if(poz<0) poz+=10;
}
}
fout<<’\n’;
fout.close();
return 0;
}
fin>>n;
//obtin nr
poz=0;
while (nr)
{
cifra=nr%10; nr/=10;
if (cifra!=poz)
{
if (cifra<poz)
{
st=poz-cifra;
dr=10+cifra-poz;
}
else
{
dr=cifra-poz;
st=10+poz-cifra;
}
CAPITOLUL 7. OJI 2017 7.2. ROBOT 92
if (st<dr)
fout<<"S"<<st;
else
fout<<"D"<<dr;
}
poz=cifra;
fout<<"A";
}
if (zero)
{
if (poz)
{
dr=10-poz; st=poz;
if (st<dr)
fout<<"S"<<st;
else
fout<<"D"<<dr;
}
while (zero) {fout<<"A"; zero--;}
}
fout<<"T\n";
fout.close();
return 0;
}
ifstream fin("robot.in");
ofstream fout("robot.out");
int cerinta, n;
int main()
{
char c;
int nr, st, dr, poz, zero, cat, cifra;
fin>>cerinta;
if (cerinta==1)
{
c=’*’; nr=0;
while (c!=’T’)
{
fin>>c;
if (c==’A’) nr++;
}
fout<<nr<<’\n’;
fout.close();
return 0;
}
if (cerinta==2)
{
c=’*’; nr=0; poz=0;
while (c!=’T’)
{
fin>>c;
if (c==’A’) fout<<poz;
else
if (c==’D’)
{
fin>>c;
cat=c-’0’;
poz=(poz+cat)%10;
}
else
if (c==’S’)
{
fin>>c;
cat=c-’0’;
CAPITOLUL 7. OJI 2017 7.2. ROBOT 93
poz-=cat;
if(poz<0) poz+=10;
}
}
fout<<’\n’;
fout.close();
return 0;
}
fin>>n;
if (n==0){fout<<"AT\n"; fout.close(); return 0; }
zero=0;
while (n%10==0) {zero++;n/=10;}
nr=0;
while (n) {nr=nr*10+n%10; n/=10;}
//obtin nr
poz=0;
while (nr)
{
cifra=nr%10; nr/=10;
if (cifra!=poz)
{
if (cifra<poz)
{
st=poz-cifra;
dr=10+cifra-poz;
}
else
{
dr=cifra-poz;
st=10+poz-cifra;
}
fout<<"D"<<dr;
}
poz=cifra;
fout<<"A";
}
if (zero)
{
if (poz)
{
dr=10-poz; st=poz;
fout<<"D"<<dr;
}
while (zero) {fout<<"A"; zero--;}
}
fout<<"T\n";
fout.close();
return 0;
}
int main()
{
ifstream in("robot.in");
ofstream out("robot.out");
char c;
int a=0,b=0,n=0,m=0,z=0,e,d,p;
in>>p;
if(p==1)
{
while(!in.eof())
{
in>>c;
CAPITOLUL 7. OJI 2017 7.2. ROBOT 94
if (c==’A’)a++;
}
out<<a<<endl;
}
if(p==2)
{
in>>c;
b=0;
while(c!=’T’)
{
if (c==’D’)
{
in>>c;
a=c-48;
b=(b+a)%10;
}
else
if (c==’S’)
{
in>>c;
a=c-48;
b=(b+10-a)%10;
}
if(c==’A’) out<<b;
in>>c;
}
}
if(p==3)
{
in>>a;
if(a==0)out<<"A";
else
if(a<10)
{
if(10-a<a)
out<<’S’<<10-a<<’A’;
else
out<<’D’<<a<<’A’;
}
else
{
z=0;
while(a%10==0)
{
z++;
a=a/10;
}
while(a!=0)
{
b=b*10+a%10;
a=a/10;
}
a=b;
b=a%10;
if(10-b<b)
out<<’S’<<10-b<<’A’;
else
out<<’D’<<b<<’A’;
a=a/10;
while(a!=0)
{
if(b==a%10)
out<<’A’;
else
if(b>a%10)
if(10-b+a%10<=b-a%10)
out<<’D’<<10-b+a%10<<’A’;
else
out<<’S’<<b-a%10<<’A’;
else
if(10-a%10+b<a%10-b)
out<<’S’<<10-a%10+b<<’A’;
else
CAPITOLUL 7. OJI 2017 7.2. ROBOT 95
out<<’D’<<a%10-b<<’A’;
b=a%10;
a=a/10;
}
if(z!=0)
{
if(10-b<b)
out<<’D’<<b;
else
out<<’S’<<b;
while(z!=0)
{
out<<’A’;
z--;
}
}
}
out<<’T’;
}
in.close();
out.close();
return 0;
}
OJI 2016
8.1 colier
Problema 1 - colier 90 de
puncte
Maria are ı̂n camera sa N mărgele aşezate una lângă alta. Pe fiecare dintre ele este scris un
număr natural format din cifre nenule distincte. Pentru fiecare mărgea, Maria şterge numărul şi
ı̂n locul său scrie altul, având doar două cifre, respectiv cifra minimă şi cifra maximă din numărul
scris iniţial, ı̂n ordinea ı̂n care aceste cifre apăreau ı̂nainte de ştergere. Acum Maria consideră că
mărgelele sunt de două tipuri, ı̂n funcţie de numărul de două cifre scris pe ele: tipul 1 (cele care
au cifra zecilor mai mică decât cifra unităţilor) şi tipul 2 (celelalte). Folosind mărgelele, fetiţa
doreşte ca prin eliminarea unora dintre ele (dar fără să le schimbe ordinea celorlalte) să obţină
un colier circular cât mai lung care să respecte proprietatea că oricare două mărgele vecine ale
sale sunt de tipuri diferite. În colierul format cu mărgelele rămase după eliminare se consideră că
prima mărgea este vecină cu ultima.
Cerinţe
Date de intrare
Fişierul colier.in conţine pe prima linie un număr natural T . Pe linia a doua se găseşte un
număr natural N . Pe linia a treia sunt N numere naturale ce reprezintă, ı̂n ordine, valorile scrise
iniţial pe mărgele. Aceste numere sunt separate prin câte un spaţiu.
Date de ieşire
Dacă valoarea lui T este 1, se va rezolva numai punctul 1) din cerinţe. În acest caz, fişierul de
ieşire colier.out va conţine pe prima linie un număr natural reprezentând răspunsul la cerinţa 1).
Dacă valoarea lui T este 2, se va rezolva numai punctul 2) din cerinţe. În acest caz, fişierul de
ieşire colier.out va conţine pe prima linie un număr natural reprezentând răspunsul la cerinţa 2).
96
CAPITOLUL 8. OJI 2016 8.1. COLIER 97
Exemple
colier.in colier.out Explicaţii
1 3 Numerele scrise de Maria pe mărgele vor fi, ı̂n ordine: 12 68 31
5 24 93. Trei dintre ele (12, 68 şi 24) sunt de tipul 1. (T fiind 1
12 678 312 24 938 se rezolvă doar cerinţa 1).
2 4 Numerele scrise de Maria pe mărgele vor fi, ı̂n ordine: 12 68 31
5 24 93. Eliminând mărgeaua de pe poziţia 1 sau pe cea de pe
12 678 312 24 938 poziţia 2 şi aşezându-le pe celelalte circular obţinem un colier cu
4 mărgele ı̂n care oricare două vecine sunt de tipuri diferite. (T
fiind 2 se rezolvă doar cerinţa 2). Maria este obligată să elimine
una din cele două mărgele, altfel ar exista mărgele vecine de
acelaşi tip.
Prima cerinţă se rezolvă prin aplicarea pentru fiecare număr a algoritmului de parcurgere a
cifrelor sale, identificând cifra maximă si cea minimă a sa, precum şi poziţiile lor.
Pentru cerinţa a doua, determinăm câte secvenţe maximale formate din valori de acelaşi tip
există. Dacă prima şi ultima secvenţă sunt formate din acelaşi tip de mărgele, scădem 1 din
valoarea dererminată anterior.
Ambele cerinţe se rezolvă procesând numerele ı̂n momentul citirii, deci fără a fi necesare
tablouri de memorie.
ifstream f("colier.in");
ofstream g("colier.out");
int main()
{
int x,P,M,p,m,poz=0,n,t,s=0,a,b,k=1;
f>>t>>n;
f>>x;
poz=0;
m=10;
M=-1;
while(x)
{
poz++;
if(x%10>M)
{
M=x%10;
P=poz;
}
if(x%10<m)
{
m=x%10;
p=poz;
}
CAPITOLUL 8. OJI 2016 8.1. COLIER 98
x=x/10;
}
s+=(1+(p<P))==1;
a=1+(p<P);
for(int i=2;i<=n;i++)
{
f>>x;
poz=0;
m=10;
M=-1;
while(x)
{
poz++;
if(x%10>M)
{
M=x%10;
P=poz;
}
if(x%10<m)
{
m=x%10;
p=poz;
}
x=x/10;
}
s+=(1+(p<P))==1;
b=1+(p<P);
if(a!=b)
{
k++;
a=b;
}
}
if(k%2)k--;
if(t==1)
g<<s<<’\n’;
else
g<<k<<’\n’;
f.close();
g.close();
return 0;
}
int n, i, x, c, maxim, minim, nr, pmaxim, pminim, tip, tipa, sol1, sol2, first, t;
int main ()
{
ifstream fin ("colier.in");
ofstream fout("colier.out");
fin>>t>>n;
sol2 = 1;
for(i=1;i<=n;i++)
{
fin>>x;
maxim = 0;
minim = 9;
nr = 0;
while(x != 0)
{
c = x % 10;
nr++;
if(c > maxim)
{
maxim = c;
pmaxim = nr;
CAPITOLUL 8. OJI 2016 8.1. COLIER 99
}
if(c < minim)
{
minim = c;
pminim = nr;
}
x /= 10;
}
if (tip == first)
sol2--;
if (t == 1)
fout<<sol1<<"\n";
else
{
if (sol1 == n || sol1 == 0)
fout<<"1\n";
else
fout<<sol2<<"\n";
}
return 0;
}
ifstream f("colier.in");
ofstream g("colier.out");
int main()
{
int n, nr=1, tip1=0, tip2=0,x,c,u,k=0,cmin=10,cmax=0,pcmin,pcmax,p,i,t;
f>>t>>n>>x;
while (x)
{
c=x%10;
k++;
if (c<cmin) { cmin=c; pcmin=k; }
if (c>cmax) { cmax=c; pcmax=k; }
x/=10;
}
while (x)
{
c=x%10;
k++;
if (c<cmin) { cmin=c; pcmin=k; }
if (c>cmax) { cmax=c; pcmax=k; }
x/=10;
}
if (pcmin>pcmax)
{
tip1++;
if (u!=1) {nr++; u=1;}
}
else
{
tip2++;
if (u!=2) {nr++; u=2;}
}
}
if (u==p) nr--;
if (t==1)
g<<tip1<<’\n’;
else
g<<nr<<’\n’;
return 0;
}
ifstream f("colier.in");
ofstream out("colier.out");
int main()
{
int n,m,x,y,a,b,c,T,maxim,minim,maxi,mini,tipa,tipb,tipul,tip1=0,i,k;
ifstream in("colier.in");
in>>T;
in>>n;m=n;
in>>a;
y=a; maxim=0; maxi=0; minim=999999999; mini=0, k=0;
while(y)
{
c=y%10;k++;
if(c>maxim)
maxim=c,maxi=k;
if(c<minim)
minim=c,mini=k;
y/=10;
}
if(mini>maxi)
tip1++,tipa=1;
else
tipa=2;
tipul=tipa;
// cout<<"a="<<a<<endl;
// cout<<"*"<<n<<" "<<tip1<<" "<<tipa<<endl;
for(i=2;i<=m;i++)
{
in>>b; // cout<<"b="<<b<<endl;
y=b;maxim=0;maxi=0;minim=999999999; mini=0;k=0;
while(y)
CAPITOLUL 8. OJI 2016 8.2. PALINDROM 101
{
c=y%10;k++;
if(c>maxim) maxim=c, maxi=k;
if(c<minim) minim=c, mini=k;
y/=10;
}
if(mini>maxi)
tip1++,tipb=1;
else
tipb=2;
if(tipa==tipb) n--;
//cout<<"!"<<n<<" "<<tip1<<" "<<tipb<<endl;
a=b,tipa=tipb;
}
if(tipb==tipul) n--;
// cout<<"*"<<n<<" "<<tip1<<" "<<tipb<<" "<<tipul<<endl;
if(T==1)
out<<tip1;
else
out<<n;
return 0;
}
8.2 Palindrom
Problema 2 - Palindrom 90 de
puncte
Un număr se numeşte palindrom dacă prima lui cifră este egală cu ultima, a doua cu penultima
şi aşa mai departe. De exemplu numerele 1221, 505 şi 7 sunt palindromuri, ı̂n vreme ce 500, 1410
şi 2424 nu sunt palindromuri.
Similar, un număr se numeşte aproape palindrom dacă are aceleaşi perechi de cifre identice
ca un palindrom, mai puţin o pereche ı̂n care cifrele diferă. De exemplu numerele 500, 1411,
2444, 1220, 53625, 14 şi 4014 sunt numere aproape palindromuri (cu perechea de cifre neidentice
ı̂ngroşată), ı̂n vreme ce 1221, 1410, 6, 505, 22 şi 512125 nu sunt numere aproape palindromuri
deoarece fie sunt palindromuri, fie au prea multe perechi de cifre diferite.
Mai definim palindromul asociat al unui număr x ca fiind cel mai mic număr palindrom p
strict mai mare decât x (p % x). De exemplu palindromul asociat al lui 5442 este 5445, palindromul
asociat al lui 2445 este 2552, al lui 545 este 555, al lui 39995 este 40004, al lui 500 este 505, iar al
lui 512125 este 512215.
Cerinţe
Scrieţi un program care citind un număr natural nenul n şi apoi un şir de n numere naturale
determină:
1. câte dintre cele n numere sunt palindrom
2. câte dintre cele n numere sunt aproape palindrom
3. palindromurile asociate pentru cele n numere citite.
Date de intrare
Fişierul de intrare palindrom.in conţine pe prima linie un număr C. Pentru toate testele, C
poate lua numai valorile 1, 2 sau 3. Pe a doua linie se află numărul n, iar pe a treia linie cele n
numere naturale despărţite prin câte un spaţiu.
Date de ieşire
a dacă C 2, va conţine numărul de numere din şir care sunt aproape palindrom
a dacă C 3, va conţine numerele palindrom asociate celor n numere din şir, separate prin
câte un spaţiu
Exemple
palindrom.in palindrom.out
1 5
7
1221 500 53635 505 7 4004 1410
Explicaţie: Cele 5 numere palindrom sunt 1221, 53635, 505, 7 şi 4004
(C fiind 1, se rezolvă doar prima cerinţă).
2 3
4
5442 2445 545 39995
Explicaţie: Cele 3 numere aproape palindrom sunt 5442, 2445 şi 39995
(C fiind 2, se rezolvă doar a doua cerinţă).
3 7 1441 2552 1331 515 1221 53635 22 4114 1441 33
11
6 1411 2444 1221 505 1220 53625 14 4014 1410 22
Explicaţie: Palindromul asociat lui 6 este 7, al lui 1411 este 1441, al lui 2444 este 2552 etc.
(C fiind 3, se rezolvă doar a treia cerinţă).
Cerinta 1
Punctul 1 al problemei este relativ banal, cerand sa spunem cate numere palindrom exista
intr-un sir de numere. Cu toate acestea trebuie avut grija deoarece algoritmul standard calculeaza
rasturnatul numarului, care poate sa depaseasca valoarea maxima a unui intreg, de circa doua
miliarde (de exemplu numarul 1234554327). Pentru a nu depasi intregul putem proceda in mai
multe moduri:
1. Putem sa extragem cifrele din capetele opuse ale numarului, spre a le compara, iar apoi le
eliminam. Pentru aceasta vom calcula p10, puterea maxima a lui 10 care este mai mica sau egala
cu numarul nostru, x. Apoi avem:
prima_cifra = x / p10;
ultima_cifra = x % 10;
x = x % p10 / 10;
p10 = p10 / 100;
2. Putem sa rasturnam numarul doar pana la jumatatea sa. Facem acest lucru la fel ca in
algoritmul clasic, adaugand cifrele de la coada lui x la coada lui y, cu diferenta ca ne vom opri
atunci cand x ¡= y.
CAPITOLUL 8. OJI 2016 8.2. PALINDROM 103
Cerinta 2
Cerinta 2 se rezolva similar cu punctul 1, numai ca de data aceasta vom numara cate diferente
avem intre perechile de cifre. Cu algoritmul clasic rasturnam numarul x in y si apoi extragem pe
rand cifre din coada ambelor numere calculand cate perechi diferite avem.
Daca numarul de perechi diferite este 0, numarul este palindrom, iar daca este 2 atunci numarul
este aproape palindrom.
Avem aceeasi problema insa, ca si la punctul 1, anume pe anumite numere vom depasi intregul.
Pentru a nu depasi putem iar aplica metodele descrise la punctul 1.
Cerinta 3
Punctul 3 al problemei se reduce la a calcula pentru un numar x cel mai mic palindrom strict
mai mare ca x. Putem rezolva direct, incrementand x si testand daca este palindrom, avand grija
la depasire. Aceasta metoda este destul de lenta si va depasi timpul la cateva teste. O metoda
mai rapida este urmatoarea:
Vom porni cu numarul x x 1 si vom calcula cel mai mic palindrom mai mare sau egal cu
x.
Pentru aceasta calculam y, simetrizarea lui x, ca fiind copierea primei jumatati in cea de-a
doua, rasturnata. De exemplu pentru 123456 vom calcula 123321, iar pentru 4066345 vom calcula
4066604. Daca palindromul calculat, y, este mai mare sau egal cu x, atunci el este chiar raspunsul.
Altfel, daca este mai mic, va trebui sa calculam numarul z caruia i se aduna unu la ultima cifra
dinainte de jumatatea a doua a numarului. Daca simetrizam z vom obtine raspunsul.
char s[12];
int t, n, i, j, k, t1, t2, nr;
int main ()
{
ifstream fin("palindrom.in");
ofstream fout("palindrom.out");
fin>>t>>n;
for (i=1;i<=n;i++)
{
fin>>s;
int nr = 0;
for (j=0, k=strlen(s)-1; j<k; j++, k--)
{
if (s[j] != s[k]) nr++;
}
if (nr == 0) t1++;
if (nr == 1) t2++;
if (t == 3)
{
int number = 0;
int noua = 1;
for (j=0;s[j]!=0;j++)
{
if (s[j] != ’9’) { noua = 0; }
number = number*10 + s[j] - ’0’;
}
if (noua)
{
fout<<1;
for (j=0;s[j+1]!=0;j++) fout<<0;
fout<<"1 ";
CAPITOLUL 8. OJI 2016 8.2. PALINDROM 104
continue;
}
if (strlen(s) % 2 == 0)
{
int left = 0;
for (j=0;j<strlen(s)/2;j++)
left = left * 10 + s[j] - ’0’;
int auxleft = left;
int rez = left;
while (left != 0)
{
rez = rez * 10 + left % 10;
left /= 10;
}
if (rez > number)
{
fout<<rez<<" ";
continue;
}
else
{
left = auxleft + 1;
rez = left;
while (left != 0)
{
rez = rez * 10 + left % 10;
left /= 10;
}
fout<<rez<<" ";
continue;
}
}
else
{
int left = 0;
for (j=0;j<=strlen(s)/2;j++)
left = left * 10 + s[j] - ’0’;
int auxleft = left;
int rez = left;
left /= 10;
while (left != 0)
{
rez = rez * 10 + left % 10;
left /= 10;
}
if (rez > number)
{
fout<<rez<<" ";
continue;
}
else
{
left = auxleft + 1;
rez = left;
left /= 10;
while (left != 0)
{
rez = rez * 10 + left % 10;
left /= 10;
}
fout<<rez<<" ";
continue;
}
}
}
}
if (t == 1) fout<<t1<<"\n";
if (t == 2) fout<<t2<<"\n";
return 0;
}
#include <iostream>
#include <fstream>
ifstream in("palindrom.in");
ofstream out("palindrom.out");
int main()
{
int c,n,i,j,k,d=1, nrap=0,nrpal=0;
long long x,y,z=0,a,b;
in>>c;
in>>n;
for(i=1;i<=n;i++)
{
in>>x;
y=x;
z=k=0;
while(y)
{
z=z*10+y%10;
k++;
y/=10;
}
if(c==1)
{
if(x==z) nrpal++;
}
else
if(c==2)
{
a=x,b=z,d=0;
while(a && d<=2){
if(a%10!=b%10) d++;
a/=10,b/=10;
}
if(d==2)
nrap++;
}
else
{
int m=1,prim,ultim;
for(j=1;j<=k/2;j++) m*=10;
y=x/m*m+z%m;
if(y<=x)
{
if(k%2==0)
a=b=(x/m+1);
else
a=b=(x/m+1)/10;
z=0;
while(b)
{
z=z*10+b%10;
b=b/10;
}
y=(x/m+1)*m+z;
}
out<<y<<’ ’;
}
}
if(c==1) out<<nrpal;
else
if(c==2) out<<nrap;
return 0;
}
OJI 2015
9.1 Cuart
Problema 1 - Cuart 100 de puncte
Gina şi Mihai joacă ı̂mpreună jocul Cuart. Ei au la dispoziţie un şir de 2 N cartonaşe ce conţin
numere naturale. Primele N cartonaşe, de la stânga la dreapta, sunt ale Ginei, iar următoarele
N ale lui Mihai. Gina traveresează şirul, de la stânga la dreapta şi scrie pe o foaie de hârtie, pe
primul rând, un şir de numere obţinut din numerele de pe cartonaşele sale, din care a şters toate
cifrele pare. La fel procedează Mihai care scrie pe foaia sa de hârtie, pe primul rând, şirul de
numere obţinut din numerele de pe cartonaşele sale, din care a şters toate cifrele impare. Dacă
dintr-un număr s-au şters toate cifrele, sau au rămas doar cifre egale cu 0, atunci numărul este
ignorat, deci pe hârtie nu se scrie nimic.
Fiecare copil, notează pe hârtia sa, pe al doilea rând, un alt şir de numere obţinut astfel:
pentru fiecare număr X scris pe primul rând, copilul va scrie cel mai mare număr natural K cu
proprietatea că 1 5 9 13 ... K & X. În jocul copiilor, numărul X se numeşte cuarţ dacă
1 5 9 13 ... K X .
În exemplul de mai sus, Gina nu a scris niciun număr cuarţ pe primul rând, iar Mihai a scris
unul singur (6=1+5). Regulile de câştig ale jocului sunt următoarele:
a Câştigă acel copil care are scrise pe primul rând cele mai multe numere cuarţ. În acest caz,
valoarea de câştig a jocului este egală cu numărul de numere cuarţ scrise de copilul câştigător.
a Dacă cei doi copii au scris acelaşi număr de numere cuarţ, atunci va câştiga cel care are primul
număr scris pe primul rând, mai mare decât al celuilalt. Acest prim număr scris de câştigător va
reprezenta valoarea de câştig.
a Dacă nici Gina şi nici Mihai nu au scris niciun număr pe hârtie, se consideră egalitate şi nu
câştigă niciunul.
Cerinţe
Scrieţi un program care să citească numărul N reprezentând numărul de cartonaşe ale unui
copil şi cele 2 N numere de pe cartonaşe, ı̂n ordine de la stânga la dreapta şi care să determine:
1) Cel mai mare număr de pe cele 2 N catonaşe, pentru care nu s-a scris niciun număr pe
primul rând (a fost omis), nici pe hârtia Ginei, nici pe hârtia lui Mihai; dacă nu a fost omis niciun
număr, se va scrie 0;
2) Câştigătorul jocului şi afişează numărul 1 dacă a câştigat Gina, 2 pentru Mihai sau 0 ı̂n caz
de egalitate.
3) Valoarea de câştig a jocului, sau 0, ı̂n caz de egalitate.
Date de intrare
106
CAPITOLUL 9. OJI 2015 9.1. CUART 107
Fişierul de intrare cuart.in conţine pe prima linie un număr natural P . Pentru toate testele
de intrare, numărul P poate avea doar valoarea 1, valoarea 2 sau valoarea 3. Pe a doua linie a
fişierului de intrare cuart.in se găseşte numărul natural N reprezentând numărul de cartonaşe
ale fiecărui copil şi pe a treia linie, ı̂n ordine de la stânga la dreapta, numerele de pe cele 2 N
cartonaşe, separate prin câte un spaţiu.
Date de ieşire
Dacă valoarea lui P este 1, se va rezolva numai punctul 1) din cerinţe. În acest caz, fişierul de
ieşire cuart.out va conţine pe prima linie un număr natural reprezentând răspunsul la cerinţa 1).
Dacă valoarea lui P este 2, se va rezolva numai punctul 2) din cerinţe. În acest caz, fişierul de
ieşire cuart.out va conţine pe prima linie un număr natural reprezentând răspunsul la cerinţa 2).
Dacă valoarea lui P este 3, se va rezolva numai punctul 3) din cerinţe. În acest caz, fişierul de
ieşire cuart.out va conţine pe prima linie un număr natural reprezentând răspunsul la cerinţa 3).
Exemple
cuart.in cuart.out Explicaţii
1 284260 P = 1, pentru acest test, se rezolvă cerinţa 1).
4 Gina a scris pe hârtia sa, pe două rânduri nu-
1234 48 284260 75 756 1232515 153 98 merele:
13 75
5 21
Mihai a scris pe hârtie numerele:
6 22 8
595
Cel mai mare număr omis este 284260
2 2 P = 2, pentru acest test, se rezolvă cerinţa 2). A
4 câştigat Mihai deoarece are un număr cuarţ, iar
1234 48 284260 75 756 1232515 153 98 Gina niciunul.
3 28 P = 3, pentru acest test, se rezolvă cerinţa 3).
1 Gina a scris pe hârtia sa, pe două rânduri nu-
154 2181 merele:
15
9
Mihai a scris pe hârtie numerele:
28
13
Ambii copii au scris câte un număr cuarţ, ı̂nsă
a câştigat Mihai care are primul număr scris pe
primul rând mai mare decât al Ginei. Valoarea
de câştig a jocului este 28.
int main()
{
freopen("cuart.in", "r",stdin);
freopen("cuart.out","w",stdout);
scanf("%d\n%d",&P, &N);
assert(N<=1000 && N>=1 && P>0 && P<4);
first1=cuart1=0;
if(x)
{
if(!first1) first1=x;
Sum=0; t=1;
while (Sum + t <= x)
{
Sum+=t;
t+=4;
}
if(Sum==x) cuart1++;
}
else Max=max(X, Max);
}
first2=cuart2=0;
for(int i=1; i<=N; i++)
{
scanf("%d",&X);
assert(X<100000000 && X>0);
if(x)
{
if(!first2) first2=x;
Sum=0; t=1;
while (Sum + t <= x)
{
Sum+=t;
t+=4;
}
if(Sum==x) cuart2++;
}
else Max=max(X, Max);
}
if(P==1)
printf("%d\n", Max);
else
{
if(cuart1>cuart2)
{
if (P==2) printf("1\n"); else printf("%d\n",cuart1);
}
else
if(cuart1<cuart2)
{
if (P==2) printf("2\n"); else printf("%d\n", cuart2);
}
else
if(first1==0 && first2 ==0)
{
if (P==2) printf("0\n"); else printf("%d\n", 0);
}
else
if (first1>first2)
{
if (P==2) printf("1\n"); else printf("%d\n",first1);
}
else
{
if (P==2) printf("2\n"); else printf("%d\n",first2);
}
}
return 0;
}
ifstream f("cuart.in");
ofstream g("cuart.out");
int n,x;
int main()
{
int i,max1=0,p=1,nr=0,y,q1=0,q2=0,k,s,
prim1=0, prim2=0,max2=0,nr1=0,nr2=0,P;
f>>P>>n;
p=p*10;
}
x=x/10;
}
if(nr==0&&max1<y) max1=y;
if(nr)
{
nr1++;
if(prim1==0) prim1=nr;
k=1;
s=0;
while (s<nr)
{
s=s+k;
k=k+4;
}
if(s==nr) q1++;
}
nr=0;
p=1;
}
for(i=1; i<=n; i++)
{
f>>x;
y=x;
while(x!=0)
{
if(x%10%2==0)
{
nr=nr+x%10*p;
p=p*10;
}
x=x/10;
}
if(nr==0&&max2<y) max2=y;
if(nr)
{
nr2++;
if(prim2==0) prim2=nr;
k=1;
s=0;
while (s<nr)
{
s=s+k;
k=k+4;
}
if(s==nr) q2++;
}
nr=0;
p=1;
}
if(P==1)
if(max1>max2) g<<max1<<’\n’;
else g<<max2<<’\n’;
else
{
if(nr1==0&&nr2==0) g<<0<<’\n’;
else
{
if(q1>q2) if(P==2) g<<1<<’\n’; else g<<q1<<’\n’;
if(q1<q2) if(P==2) g<<2<<’\n’; else g<<q2<<’\n’;
if(q1==q2)
{
if(prim1>prim2) if(P==2) g<<1<<’\n’; else g<<prim1<<’\n’;
else if(P==2) g<<2<<’\n’; else g<<prim2<<’\n’;
}
}
}
f.close();
g.close();
return 0;
}
CAPITOLUL 9. OJI 2015 9.1. CUART 111
int main()
{
int pp,n,nr1=0,nr2=0,p1=0,p2=0,max1=0,
nrcuart1=0,nrcuart2=0,c,y,x,p,i,k,s;
ifstream f("cuart.in");
ofstream g("cuart.out");
f>>pp>>n;
if (y!=0)
{
nr1++;
if (nr1==1) p1=y;
s=1;
k=5;
while (s+k<=y)
{
s=s+k;
k=k+4;
}
if (s==y) nrcuart1++;
}
else if (c>max1) max1=c;
}
if (y!=0)
{
nr2++;
if (nr2==1) p2=y;
s=1;
k=5;
while (s+k<=y)
{
s=s+k;
k=k+4;
}
CAPITOLUL 9. OJI 2015 9.1. CUART 112
if (s==y) nrcuart2++;
}
else if (c>max1) max1=c;
}
if (pp==1)
g<<max1<<’\n’;
else
if (pp==2)
{
if (nrcuart1>nrcuart2)
g<<"1\n";
else
if (nrcuart2>nrcuart1)
g<<"2\n";
else
{
if (p1>p2)
g<<"1\n";
else
if(p2>p1)
g<<"2\n";
else
g<<"0\n";
}
}
else
{
if (nrcuart1>nrcuart2)
g<<nrcuart1;
else
if (nrcuart2>nrcuart1)
g<<nrcuart2;
else
{
if (p1>p2)
g<<p1<<"\n";
else
if (p2>p1)
g<<p2<<"\n";
else
g<<"0\n";
}
}
return 0;
}
ifstream f("cuart.in");
ofstream g("cuart.out");
int N,P,B,C,m1,m2,maxo,K,M,q1,q2,
primul1,primul2,k,i,x,p,q,nr1,nr2;
int main()
{
//citire-prelucrare
f>>P>>N;
//Gina
for(i=1;i<=N;i++)
{
f>>K;x=K;p=1;q=0;
while(x>0)
{
if(x%2==1){q+=p*(x%10);p*=10;}
x/=10;
}
if(q==0){if(K>maxo)maxo=K;}
CAPITOLUL 9. OJI 2015 9.1. CUART 113
else
{
nr1++;
if(primul1==0)primul1=q;
//1+5+9+...+(4M+1)=(M+1)(2M+1)
//k=M*4+1;
M=0;
while(2*M*M+3*M+1<q) M++;
if(q==(M+1)*(2*M+1)) q1++;
}
}
//Mihai
for(i=1;i<=N;i++)
{
f>>K;x=K;p=1;q=0;
while(x>0)
{
if(x%2==0){q+=p*(x%10);p*=10;}x/=10;
}
if(q==0){if(K>maxo)maxo=K;}
else
{
nr2++;
if(primul2==0)primul2=q;
//k=M*4+1;
M=0;
while(2*M*M+3*M+1<q )M++;
if(q==(M+1)*(2*M+1))q2++;
}
}
//afisare a)
if(P==1)g<<maxo<<’\n’;
//afisare b) si c)
if(q1<q2)
B=2,C=q2;
else
if(q1>q2)
B=1,C=q1;
else
if(primul1>primul2)
B=1,C=primul1;
else
if(primul1<primul2)
B=2,C=primul2;
else
B=C=0;
if(P==2)g<<B<<’\n’;
if(P==3)g<<C<<’\n’;
f.close();
g.close();
return 0;
}
ifstream f("cuart.in");
ofstream g("cuart.out");
int P,N,m1,m2,maxo,A,B,C,M,q1,q2,
primul1,primul2,k,i,x,q,p,nr1,nr2;
CAPITOLUL 9. OJI 2015 9.1. CUART 114
int main()
{
//citire-prelucrare
f>>P>>N;
//Gina
for(i=1;i<=N;i++)
{
f>>A;x=A;p=1;q=0;
while(x>0)
{
if(x%2==1)
{
q+=p*(x%10);
p*=10;
}
x/=10;
}
if(q==0)
{
if(A>maxo) maxo=A;
}
else
{
nr1++;
if(primul1==0)primul1=q;
//1+5+9+...+(4M+1)=(M+1)(2M+1)
M=(-3+sqrt(1+8*q))/4;
//k=M*4+1;
if(q==(M+1)*(2*M+1))q1++;
}
}
//Mihai
for(i=1;i<=N;i++)
{
f>>A; x=A; p=1; q=0;
while(x>0)
{
if(x%2==0)
{
q+=p*(x%10);
p*=10;
}
x/=10;
}
if(q==0){if(A>maxo)maxo=A;}
else
{
nr2++;
if(primul2==0)primul2=q;
M=(-3+sqrt(1+8*q))/4;
//k=M*4+1;
if(q==(M+1)*(2*M+1))q2++;
}
}
//afisare a)
if(P==1)g<<maxo<<’\n’;
//afisare b) si c)
if(q1<q2) B=2,C=q2;
else if(q1>q2) B=1,C=q1;
else if(primul1>primul2)B=1,C=primul1;
else if(primul1<primul2)B=2,C=primul2;
else B=C=0;
if(P==2)g<<B<<’\n’;
if(P==3)g<<C<<’\n’;
f.close();
g.close();
return 0;
}
CAPITOLUL 9. OJI 2015 9.2. SPECIALE 115
9.2 speciale
Problema 2 - speciale 100 de puncte
Maria a aflat că numerele naturale care ı̂ncep cu cifra 1 şi au toate cifrele ordonate strict
crescător şi consecutive sau ı̂ncep cu cifra 9 şi au toate cifrele ordonate strict descrescător şi
consecutive se numesc numere speciale. Interesată să descopere legătura dintre numerele speciale
cu acelaşi număr de cifre, a observat că poate construi tabelul alăturat.
Cerinţe
Date de intrare
Fişierul de intrare speciale.in conţine pe prima linie un număr natural P . Pentru toate testele
de intrare, numărul P poate avea doar valoarea 1, valoarea 2 sau valoarea 3. Pe a doua linie a
fişierului speciale.in se găsesc, ı̂n această ordine, numerele naturale K, N , A şi B, separate prin
câte un spaţiu.
Date de ieşire
Dacă valoarea lui P este 1, se va rezolva numai punctul 1) din cerinţe. În acest caz, fişierul de
ieşire speciale.out va conţine pe prima linie un număr natural reprezentând cel mai mare număr
special situat ı̂n tabel pe linia K.
Dacă valoarea lui P este 2, se va rezolva numai punctul 2) din cerinţe. În acest caz, fişierul
de ieşire speciale.out va conţine pe prima linie un număr natural reprezentând numărul special
obţinut din numărul N prin ştergerea unei cifre sau 0 dacă un astfel de număr nu se poate obţine;
Dacă valoarea lui P este 3, se va rezolva numai punctul 3) din cerinţe. În acest caz, fişierul de
ieşire speciale.out va conţine pe prima linie un număr natural reprezentând numărul de numere
speciale din mulţimea {A, A 1, A 2, A 3, ..., B 1, B}.
a 1&K&9
a 1 & N & 999999999
a 1 & A & B & 999999999
a Pentru rezolvarea corectă a primei cerinţe se acordă 20 de puncte, pentru rezolvarea corectă
a celei de a doua cerinţe se acordă 40 de puncte, pentru rezolvarea corectă a celei de a treia cerinţe
se acordă 40 de puncte.
CAPITOLUL 9. OJI 2015 9.2. SPECIALE 116
Exemple
Cerinta 1
Se formeaza numarul special care incepe cu cifra 9 si contine k cifre cu ajutorul unei structuri
repetitive.
Cerinta 2
O solutie posibila: numaram cifrele numarului N (nr); construim numarul special cu un numar
de cifre egal cu nr 1; comparam cifrele numarului N cu cifrele numarului special construit (cifra
cu cifra de la dreapta la stanga); daca toate sunt egale (pe aceeasi pozitie) si numai una difera,
atunci afisam numarul special construit, altfel afisam valoarea 0.
Cerinta 3
O solutie posibila: Calculam cate cifre are numrul A. Construim numerele speciale care
sa contina tot atatea cifre cate contine numarul A. Comparam valoarea numerelor speciale cu
valoarea numarului A si B iar apoi construim prin adaugare de cifre crescatore/descrescatore
urmatoarele numere speciale pana cand ajungem la valoarea numarului B.
ifstream fin("speciale.in");
ofstream fout("speciale.out");
int main()
{
unsigned P,N,K,A,B,x,special,i,p,NN,Ncif;
x=special=Ncif=0;
fin>>P>>K>>N>>A>>B; NN=N;
if(P==1)
{
for(i=9;i>=10-K;i--) fout<<i;
fout<<’\n’;
return 0;
}
if(P==2)
{
CAPITOLUL 9. OJI 2015 9.2. SPECIALE 117
///cerinta 2
while(NN)
{
NN/=10;
special=special*10+Ncif;
Ncif++;
}
if(P==3)
{
///cerinta 3
for(x=special=0,i=1;special<=B;i++)
{
special=special*10+i;
if(special>=A&&special<=B) x++;
if(special*8+i>=A&&special*8+i<=B) x++;
}
fout<<x<<’\n’;
return 0;
}
return 0;
}
ifstream f("speciale.in");
ofstream g("speciale.out");
int main()
{
int k,n,a,b,x=0,i,pr,nr=0,nr1=0,p1,fin_nr,ok=0,nr2,p;
f>>p>>k>>n>>a>>b;
if(p==1)
{
CAPITOLUL 9. OJI 2015 9.2. SPECIALE 118
x=0;
for(i=9;i>9-k;i--)
x=i+x*10;
g<<x<<’\n’;
}
//cerinta 2
if(p==2)
{
pr=n;
while(pr)
{
pr=pr/10;
nr++;
}
nr--;
for(i=1;i<=nr;i++)
nr1=i+nr1*10;
p1=0;
pr=n;
fin_nr=nr1;
while(pr)
{
if(pr%10==nr1%10) {pr=pr/10;nr1=nr1/10;}
else {p1++;pr=pr/10;}
}
if(p1==1) {g<<fin_nr<<’\n’;ok=1;}
else
{
nr1=0;
for(i=9;i>9-nr;i--)
nr1=i+nr1*10;
p1=0;
pr=n;
fin_nr=nr1;
while(pr)
{
if(pr%10==nr1%10) {pr=pr/10;nr1=nr1/10;}
else {p1++;pr=pr/10;}
}
if(p1==1) {g<<fin_nr<<’\n’;ok=1;}
}
if(ok==0) g<<0<<’\n’;
}
//cerinta 3
if(p==3)
{
nr=0;
pr=a;
nr1=0;
while(pr){pr=pr/10;nr++;}
for(i=1;i<=nr;i++)
nr1=i+nr1*10;
nr2=0;
for(i=9;i>9-nr;i--)
nr2=i+nr2*10;
x=0;
if(nr1>=a) x++;
if(nr2>=a&&nr2<=b) x++;
nr++;
pr=nr2%10-1;
while(nr2<b && nr1<b)
{
nr2=nr2*10+pr;
nr1=nr1*10+nr;
CAPITOLUL 9. OJI 2015 9.2. SPECIALE 119
nr++;pr--;
if(nr1<=b) x++;
if(nr2<=b) x++;
}
g<<x<<’\n’;
}
f.close();
g.close();
return 0;
}
ifstream in("speciale.in");
ofstream out("speciale.out");
int main()
{
int P,k,n,A,B,m,nr=0,nrm=0,mr=0,i,l,sw1,sw2;
in>>P;
in>>k>>n>>A>>B;
if(P==1)
{
//a
for(i=1;i<=k;i++)
nrm=nrm*10+10-i;
out<<nrm<<’\n’;
}
else
if(P==2)
{
//b
nr=0;
m=n,l=0;
while(m)
l++,m/=10;
for(i=1;i<l;i++)
nr=nr*10+i;
mr=nr,sw1=0,m=n;
while(n)
{
if(n%10!=nr%10)
n/=10, sw1++;
else
n/=10,nr/=10;
}
n=m;
if(sw1==1&&nr==0)
out<<mr<<’\n’;
else
if(sw1==0 && n/10==0)
out<<mr<<’\n’;
else
{
nr=0;
for(i=9;i>10-l;i--)
nr=nr*10+i;
mr=nr,sw2=0,m=n;
while(n)
{
if(n%10!=nr%10)
n/=10, sw2++;
else
CAPITOLUL 9. OJI 2015 9.2. SPECIALE 120
n/=10,nr/=10;
}
if(sw2==1&&n==0)
out<<mr<<’\n’;
else
if(sw2==0 && n/10==0)
out<<mr<<’\n’;
while(m)
l++,m/=10;
for(i=1;i<=l;i++)
nr=nr*10+i;
if(nr<A)
{
m=nr*8+l;
if(m>=A && m<=B)
k++;
l++, nr=nr*10+l;
}
i=l;
while(nr>=A && nr<=B)
{
k++;
if(nr*8+i>=A && nr*8+i<=B)
k++;
i++;
nr=nr*10+i;
}
out<<k;
}
return 0;
}
int main()
{
freopen("speciale.in", "r",stdin);
freopen("speciale.out","w",stdout);
scanf("%d\n",&P);
scanf("%d%d%d%d",&K, &N, &A, &B);
assert(P>0 && P<=3 && K<10 && K>0 && N<=MRD && A<=MRD &&
B<=MRD && N>0 && A>0 && B>0 && A<=B);
if(P==1)
{
for(int i=1; i<=K; i++)
CAPITOLUL 9. OJI 2015 9.2. SPECIALE 121
N2=N2*10 + 10 - i;
printf("%d\n", N2);
}
else
if(P==2)
{
p = 1;
Special=0;
while(N/p>0 && !Special)
{
Nr=N/(p*10)*p + N%p;
int cn=Nr;
while(cn>9) cn/=10;
if(Nr==1 ||Nr == 9)
Special = Nr;
else
{
d=(cn==9? 1: -1);
u=Nr%10;
ok=true;
while (Nr>0)
{
if ( u != Nr % 10 ) ok=false;
Nr/=10; u += d;
}
p*=10;
}
printf("%d\n", Special);
}
else
{
Na1=Na2=nr=0;
for(int i=1; i<=9 ; i++ )
{
Na1=Na1*10 + i;
if(Na1>=A&&Na1<=B ) nr++;
Na2=Na2*10 + 10 - i;
if(Na2>=A&&Na2<=B) nr++;
}
printf("%d\n", nr);
}
return 0;
}
OJI 2014
10.1 martisoare
Problema 1 - martisoare 100 de puncte
Gică şi Lică lucrează la o fabrică de jucării, ı̂n schimburi diferite. Anul acesta patronul fabricii
a hotărât să confecţioneze şi mărţişoare. Mărţişoarele gata confecţionate sunt puse ı̂n cutii nu-
merotate consecutiv.
Cutiile sunt aranjate ı̂n ordinea strict crescătoare şi consecutivă a numerelor de pe acestea.
Gică trebuie să ia, ı̂n ordine, fiecare cutie, să lege la fiecare mărţişor câte un şnur alb-roşu şi
apoi să le pună la loc ı̂n cutie.
În fiecare schimb, Gică scrie pe o tablă magnetică, utilizând cifre magnetice, ı̂n ordine strict
crescătoare, numerele cutiilor pentru care a legat şnururi la mărţişoare.
Când se termină schimbul lui Gică, Lică, care lucrează ı̂n schimbul următor, vine şi ambalează
cutiile cu numerele de pe tablă şi le trimite la magazine. Totul merge ca pe roate, până ı̂ntr-o zi,
când, două cifre de pe tablă se demagnetizează şi cad, rămânând două locuri goale. Lică observă
acest lucru, le ia de jos şi le pune la ı̂ntâmplare pe tablă, ı̂n cele două locuri goale. Singurul lucru
de care ţine cont este acela că cifra 0 nu poate fi prima cifră a unui număr.
Cerinţe
Scrieţi un program care să citească numerele naturale N (reprezentând numărul de numere
scrise pe tablă) şi c1 , c2 , ..., cN (reprezentând numerele scrise, ı̂n ordine, pe tablă, după ce Lică a
completat cele două locuri goale cu cifrele căzute) şi care să determine:
a) cele două cifre care au fost schimbate ı̂ntre ele, dacă, după ce au completat locurile goale,
acestea au schimbat şirul numerelor scrise de Gică;
b) numărul maxim scris pe tablă de Gică.
Date de intrare
Fişierul de intrare martisoare.in conţine pe prima linie numărul natural N reprezentând
numărul de numere de pe tablă. A doua linie a fişierului conţine, ı̂n ordine, cele N numere
c1 , c2 , ..., cN , separate prin câte un spaţiu, reprezentând, ı̂n ordine, numerele existente pe tablă,
după ce Lică a completat cele două locuri libere cu cifrele căzute.
Date de ieşire
Fişierul de ieşire martisoare.out va conţine pe prima linie două cifre, ı̂n ordine crescătoare,
separate printr-un spaţiu, reprezentând cele două cifre care au fost schimbate ı̂ntre ele sau 0 0
ı̂n cazul ı̂n care cele două cifre magnetice căzute, după ce au fost puse ı̂napoi pe tablă, nu au
schimbat şirul numerelor scrise de Gică. A doua linie va conţine un număr reprezentând numărul
maxim din secvenţa de numere consecutive scrisă de Gică pe tablă.
122
CAPITOLUL 10. OJI 2014 10.1. MARTISOARE 123
Exemple
martisoare.in martisoare.out Explicaţii
5 2 629 Gică a scris pe tablă, ı̂n ordine, numerele: 25 26 27 28 29.
65 22 27 28 29 Au fost schimbate ı̂ntre ele cifra 2 din primul număr şi cifra
6 din al doilea număr. Cel mai mare număr scris de Gică pe
tablă este 29. .
4 8 998 Gică a scris pe tablă, ı̂n ordine, numerele: 95 96 97 98 Au
95 96 97 89 fost schimbate ı̂ntre ele cifrele ultimului număr. Cel mai mare
număr scris de Gică pe tablă este 98.
5 0 039 Gică a scris pe tablă, ı̂n ordine, numerele: 35 36 37 38 39
35 36 37 38 39 şirul numerelor nu a fost schimbat, cel mai mare număr fiind
39.
ifstream f("martisoare.in");
ofstream g("martisoare.out");
int N,i,c1,c2,c3,c4,x,y,maxi,gasit;
int main()
{
f>>N;
f>>c1>>c2;
if(c3-c2!=1)
{
x=c2+1;y=c3;gasit=1;
while(x!=0 && y!=0)
{
if(x%10!=y%10)
{
if(x%10<y%10)
g<<x%10<<’ ’<<y%10<<endl;
else
g<<y%10<<’ ’<<x%10<<endl;
break;
}
else
x/=10,y/=10;
}
}
else
c2=c3;
}
}
else
{
f>>c3>>c4;
//c1 modificat
if(c3-c2==1)
{
x=c2-1;
y=c1;
gasit=1;
maxi=c2+N-2;
}
else
if(c4-c2==2)
{
x=c2-1;
y=c1;
gasit=1;
maxi=c4+N-4;
}
//c2 este modificat
else
if(c4-c3==1)
{
x=c2;
y=c3-1;
gasit=1;
maxi=c3+N-3;
}
else
if(c3-c1==2)
{
x=c2;
y=c3-1;
gasit=1;
maxi=c3+N-3;
}//c2 modificat si c3 este bun
else
{
x=c2;
y=c4-2;
gasit=1;
maxi=c4+N-4;
}//c2 modificat si c4 este bun
x/=10,y/=10;
}
}
if(!gasit)
g<<"0 0\n";
g<<maxi<<endl;
f.close();
g.close();
return 0;
}
ifstream f("martisoare.in");
ofstream g("martisoare.out");
int v[100001];
int main()
{
int i,x,k=1,y,n, a=0,b=0;
f>>n>>x;
v[1]=x; y=x;
for(i=2;i<=n;i++)
{
f>>v[i];
x=max(x,v[i]);
y=min(y,v[i]);
}
if(y+n-1==x)
{
for(i=1; i<=n;i++,y++)
if(v[i]!=y)
{
a=v[i];
b=y;
break;
}
}
else
{ int i=1;
if(v[1]!=y && v[2]==y)
{
if(v[3]==y+1)
{
a=v[1];
b=y-1;
x=b+n-1;
}
else
{
x=v[3]+n-3;
a=v[3]-1;
b=y;
}
}
else
{
i=2;
while(y+1==v[i] && i<=n)
{
i++;
y++;
}
CAPITOLUL 10. OJI 2014 10.1. MARTISOARE 126
a=v[i];
b=y+1;
x=y+(n-i+1);
}
}
if(a*b)
{
while(a%10==b%10)
{
a=a/10; b=b/10;
}
a=a%10;
b=b%10;
if(a>b) swap(a,b);
}
g<<a<<" "<<b<<endl<<x<<endl;
return 0;
}
ifstream f("martisoare.in");
ofstream g("martisoare.out");
int n,a,b,c,d,u;
int main()
{
f>>n>>a>>b>>c;
if(a+1==b && b+1==c)
{
u=a+n-1; n-=3;
while(n && b+1==c)
f>>c,++b,--n;
if(b+1!=c)
cifre(b+1,c), g<<u<<’\n’;
else
g<<"0 0\n"<<u<<’\n’;
}
else // cifre schimbate in primele 3 numere
if(a+1==b)
cifre(b+1,c), g<<a+n-1<<’\n’;
else
if(b+1==c)
cifre(a,b-1), g<<b+n-2<<’\n’;
else
if(a+2==c)
cifre(a+1,b), g<<a+n-1<<’\n’;
else
{
f>>d;
if(a+3==d)
cifre(a+1,b), g<<a+n-1<<’\n’;
else
if(b+2==d)
cifre(a,b-1), g<<b+n-2<<’\n’;
else
cifre(b,c-1), g<<c+n-3<<’\n’;
}
CAPITOLUL 10. OJI 2014 10.1. MARTISOARE 127
f.close();
g.close();
return 0;
}
ifstream f("martisoare.in");
ifstream g("martisoare.in");
ofstream h("martisoare.out");
int n,vmin,vmax,t,x,x1,y,y1,a,b,c,d,i,poz;
int main()
{
f>>n>>a>>b>>c>>d;
if(b-a==1){vmin=a; vmax=a+n-1;}
else
if(c-b==1){vmin=b-1; vmax=b+n-2;}
else
if(d-c==1){vmin=c-2; vmax=c+n-3;}
else
if(c-a==2){vmin=a; vmax=a+n-1;}
else
if(d-b==2){vmin=b-1; vmax=b+n-2;}
else
if(d-a==3){vmin=a; vmax=a+n-1;}
f.close();
x=x/10;y=y/10;
}
}
if (t==2) i=n;
x1++;
}
g.close();
CAPITOLUL 10. OJI 2014 10.1. MARTISOARE 128
h.close();
return 0;
}
ifstream f("martisoare.in");
ofstream g("martisoare.out");
int main()
{
int v[4], n, i, max=0, r, c, x, j, nr1=0,
p1, nr2=0, p2, nr, c1=0, c2=0, cc;
f>>n;
for(i=0;i<4;i++)
f>>v[i];
for(i=0;i<4;i++)
if(v[i]-i!=r)
if(nr1==0) nr1=v[i], p1=i;
else
if(nr2==0) nr2=v[i],p2=i;
if(nr1)
{
x=r+p1;
while(nr1)
{
c=nr1%10;
cc=x%10;
if(c!=cc)
if(c<cc) c1=c, c2=cc;
else c1=cc, c2=c;
nr1/=10;
x/=10;
}
}
g<<c1<<’ ’<<c2<<’\n’<<r+n-1<<’\n’;
f.close();
g.close();
return 0;
}
10.2 piramide
Problema 2 - piramide 100 de puncte
Fascinat de Egiptul Antic, Rareş vrea să construiască cât mai multe piramide din cartonaşe
pătratice identice. El are la dispoziţie N cartonaşe numerotate de la 1 la N , albe sau gri, aşezate
ı̂n ordinea strict crescătoare a numerelor.
a Prima piramidă o va construi folosind primele trei cartonaşe. Baza piramidei va fi formată
din cartonaşele 1 şi 2 aşezate alăturat, peste care va aşeza cartonaşul 3 (vârful piramidei).
a A doua piramidă va avea baza formată din cartonaşele 4, 5 şi 6 aşezate alăturat, deasupra
cărora se vor aşeza cartonaşele 7 şi 8, alăturate, peste care se va aşeza cartonaşul 9 (vârful
piramidei).
a Mai departe, va construi ı̂n ordine piramidele complete cu bazele formate din 4 cartonaşe
(cu numerele de la 10 la 13), respectiv 5 cartonaşe (cu numerele de la 20 la 24), 6 cartonaşe (cu
numerele de la 35 la 40) etc., cât timp va putea construi o piramidă completă. De exemplu, dacă
Rareş are N 75 cartonaşe atunci el va construi piramidele complete 1, 2, 3, 4 şi 5 din imaginile
următoare. Din cele 75 de cartonaşe el va folosi doar primele 55 de cartonaşe, deoarece ultimele
20 cartonaşe nu sunt suficiente pentru a construi piramida 6, cu baza formată din 7 cartonaşe.
Cerinţe
Scrieţi un program care să citească numerele naturale N (reprezentând numărul de cartonaşe),
X (reprezentând numărul unui cartonaş), K (reprezentând numărul de cartonaşe albe), numerele
celor K cartonaşe albe c1 , c2 , ..., cK şi care să determine: a) numărul P al piramidei complete
ce conţine cartonaşul numerotat cu X; b) numărul M maxim de piramide complete construite
de Rareş; c) numărul C de cartonaşe nefolosite; d) numărul A al primei piramide complete care
conţine cele mai multe cartonaşe albe.
Date de intrare
Fişierul de intrare piramide.in conţine pe prima linie cele trei numere N , X şi K, separate
prin câte un spaţiu, cu semnificaţia din enunţ. A doua linie a fişierului conţine, ı̂n ordine, cele K
numere c1 , c2 , ..., cK , separate prin câte un spaţiu, reprezentând numerele celor K cartonaşe albe
din cele N .
Date de ieşire
Fişierul de ieşire piramide.out va conţine pe prima linie numărul P sau valoarea 0 (zero)
dacă niciuna dintre piramidele complete construite nu conţine cartonaşul cu numărul X. A doua
linie a fişierului va conţine numărul M . Cea de-a treia linie va conţine numărul C. Cea de-a
patra linie va conţine numărul A sau valoarea 0 (zero) dacă nicio piramidă completă nu conţine
cel puţin un cartonaş alb.
Exemple
piramide.in piramide.out
75 15 23 3
5 9 11 18 20 21 25 27 28 30 35 37 45 46 51 55 60 65 68 69 70 71 72 5
20
4
Explicaţie: Piramida 3 (P=3) construită conţine cartonaşul cu numărul X 15. Rareş poate
construi doar M 5 piramide complete, rămânând nefolosite 20 cartonaşe (C 20) insuficiente
pentru construirea piramidei 6. Numărul maxim de cartonaşe albe dintr-o piramidă completă
este egal cu 6. Piramidele 4 şi 5 conţin fiecare un număr maxim de cartonaşe albe (6), prima
dintre acestea fiind piramida 4 (A 4). Ultimele 7 cartonaşe albe (cu numerele: 60, 65, 68, 69,
70, 71, 72) nu sunt folosite ı̂n construirea piramidelor complete.
Descriere soluţie
autor prof. Carmen Mincă,
Colegiul Naţional de Informatică ”Tudor Vianu”, Bucureşti
O soluţie posibilă se poate obţine fără a utiliza tablouri unidimensionale, prin citirea succesivă
a datelor din fişier combinată cu prelucrarea acestora.
Se observă că pentru construirea piramidei complete care are baza formata din b cartonaşe
sunt necesare: CB b b 1 b 2 ... 3 2 1 b b 1©2
Simulăm construirea numărului maxim M de piramide complete folosind cele N cartonaşe.
Se citeşte numărul CA al primului cartonaş alb din fişier.
Pornind de la prima piramidă (cea cu baza b 2), construim celelalte piramide cât timp avem
cartonaşe nefolosite suficiente şi numărul cartonaşelor folosite ı̂n construirea acestora este mai mic
ca CA.
Numărăm piramida completă curentă şi verificăm apartenenţa cartonaşului X la piramida
curentă folosindu-ne de numărul primului, respectiv ultimului, cartonaş din piramidă.
La găsirea primei piramide ce conţine cartonaşul alb CA, citim din fişierul de intrare numerele
următoarelor cartonaşe albe cţt timp numerele acestora sunt mai mici sau egale cu numărul
cartonaşului vţrf din piramida curentă. La finalul acestei operaţii vom dispune de numărul car-
tonaşelor albe din piramida curentă. Se compară acest număr cu cel maxim obţinut pţnă ı̂n acest
moment. Se actualizează acest maxim dacă s-a obţinut o valoare mai mare memorţndu-se şi
numărul piramidei curente.
Se trece la ”construirea” următoarei piramide, cu baza b 1 dacă avem suficiente cartonaşe
nefolosite, altfel se ı̂ncheie procesul de construire a piramidei.
#include <fstream>
int n, x, k;
ifstream f("piramide.in");
CAPITOLUL 10. OJI 2014 10.2. PIRAMIDE 131
ofstream g("piramide.out");
int main()
{
int p=0, a=0, m=0, c=0,i,ca,b=1,cfol=0,cp,nra, maxnra=0;
f>>n>>x>>k;
i=1;
f>>ca;
do //caut piramida ce contine cartonasul alb cu numarul ca
{ b++;//nr cartonase din baza piramida curenta
nra=0;//caut in piramida curenta cartonasele albe
cp=b*(b+1)/2; //nr cartonase din care e formata piramida curenta
if(nra>maxnra)
{ a=m; maxnra=nra; }
}
else break;
} while (cfol<n);
c=n-cfol;
g<<p<<endl<<m<<endl<<c<<endl<<a<<endl;
return 0;
}
#include <fstream>
int n, x, k, cart[100];
ifstream f("piramide.in");
ofstream g("piramide.out");
int main()
{
int p=0, a=0, m=0, c,i,ca,b,nra, maxnra=0,j;
f>>n>>x>>k;
b=1;
cart[1]=3;
m=0; b++;
while(cart[m]+b*(b+1)/2<=n)
{
m++;
cart[m]=b*(b+1)/2+cart[m-1];
b++;
if(x>cart[m-1] && x<=cart[m])p=m;
}
c=n-cart[m]; j=1;
i=1; f>>ca;
g<<p<<endl<<m<<endl<<c<<endl<<a;
return 0;
}
ifstream f("piramide.in");
ofstream g("piramide.out");
int N,X,K,i,ls,ld,P,nrpc,nrc,nrca,maxca,nrpmax,c,S,nr;
int main()
{
//citire
f>>N>>X>>K;
//a)
ls=1;ld=3;nrpc=1;
while(X>ld){nrpc++;ls=ld+1;ld+=(nrpc+1)*(nrpc+2)/2;}
if(N>=ld)g<<nrpc<<endl;
else g<<0<<endl;
//b)
S=0;nrpc=0;nr=1;
while(N>S){nrpc++;nr++;S+=nr*(nr+1)/2;}
if(N<S){S-=nr*(nr+1)/2;nrpc--;}
g<<nrpc<<endl;
//c)
g<<N-S<<endl;
//d)
ls=1;ld=3;nrpc=1;nrc=3;
f>>c;K--;//cartonasul alb curent
do
{
while(c>ld)
{
nrpc++;ls=ld+1;ld+=(nrpc+1)*(nrpc+2)/2;nrca=0;
}
nrca++;f>>c;K--;if(K==0)nrca++;
if(nrca>maxca && ld<=N){maxca=nrca;nrpmax=nrpc;}
}
while(K>0);
//afisare
g<<nrpmax<<endl;
f.close();
g.close();
return 0;
}
#include <fstream>
using namespace std;
ifstream f("piramide.in");
CAPITOLUL 10. OJI 2014 10.2. PIRAMIDE 133
ofstream g("piramide.out");
int n,x,k,p=1,l=2,amax,a,y,pmax=1,prim=1,ultim=3,px;
int main()
{ f>>n>>x>>k>>y;
while(ultim<=n)
{ if(x>=prim && x<=ultim)px=p;
if(a>amax) amax=a,pmax=p;
++p;++l;a=0;
prim=ultim+1; ultim+=l*(l+1)/2;
}
if(n<ultim)p--,ultim=prim-1;
g<<px<<’\n’<<p<<’\n’<<n-ultim<<’\n’;
f.close();
g.close();
return 0;
}
ifstream f("piramide.in");
ofstream g("piramide.out");
long N,X,K,c,k,S,i,A,maxa,P,M,piramida,nca,C;
int main()
{ f>>N>>X>>K;k=1;
while(S<=N)
{ if(P==0 && X<S) P=k-1;
S+=(k+1)*(k+2)/2; k++;
}
g<<P<<endl;
k--;
S=S-(k+1)*(k+2)/2;
k=k-1; C=N-S;
g<<k<<endl<<C<<endl;
// g<<S<<" k="<<k<<" "<<M<<endl;
maxa=0;A=0;nca=0;piramida=0;long cf=N-C;S=0;k=1;
for(i=1;i<=N;i++)
{
f>>c;
if(S>=c) nca++;
else
{ if(maxa<nca){maxa=nca;A=k-1;}
g<<A<<endl;
return 0;
CAPITOLUL 10. OJI 2014 10.2. PIRAMIDE 134
int N,K,S,S1,c,nr,ok,pmax,ppmax,vmin,vmax,np,nrc,i,ok1,x;
ifstream f("piramide.in");
ofstream g("piramide.out");
int main()
{
f>>N>>x>>K>>c;
for(i=2;i<=N;i++)
{
S1=i*(i+1)/2;
g<<ok<<endl<<np<<endl<<nrc <<endl<<ppmax;
f.close();
g.close();
return 0;
}
ifstream f("piramide.in");
ofstream g("piramide.out");
int n, x, k, c;
int main()
{
f>>n>>x>>k;
while(cn>=cc)
{
cn-=cc;
cp++;
if(x>=pc and x<=uc) px=cp;
cc+=pas;
pas++;
pc=uc+1;
uc=pc+cc-1;
}
CAPITOLUL 10. OJI 2014 10.2. PIRAMIDE 135
g<<px<<’\n’<<cp<<’\n’<<cn<<’\n’;
f>>c1;
pc=1;uc=3;cc=3;pas=3;
int cpp=1;
while(c1>uc)
{
cpp++;
cc+=pas;
pas++;
pc=uc+1;
uc=pc+cc-1;
}
g<<pir<<’\n’;
f.close();
g.close();
return 0;
}
OJI 2013
11.1 bete
Problema 1 - bete 100 de puncte
Ana şi Bogdan au găsit la bunicul lor o cutie cu N beţe de aceeaşi lungime. După câteva
minute de joacă urmează cearta. Bunicul le-a propus să rupă cele N beţe şi apoi Ana să primească
fragmentele din mâna stângă, iar Bogdan fragmentele din mâna dreaptă. Zis şi făcut. Copiii au
luat fragmentele, le-au numerotat fiecare cu numere de la 1 la N , le-au măsurat şi acum ı̂şi doresc
să lipească fragmentele primite, dar mai au nevoie de câteva informaţii.
Cerinţe
Date de intrare
Fişierul de intrare bete.in conţine pe prima linie numărul natural N reprezentţnd numărul de
beţe. Pe a doua linie sunt N numere naturale a1 , a2 , ..., aN reprezentţnd lungimile fragmentelor
primite de Ana şi pe a treia linie sunt N numere naturale b1 , b2 , ..., bN reprezentţnd lungimile
fragmentelor primite de Bogdan.
Date de ieşire
Fişierul de ieşire bete.out va conţine trei linii. Pe prima linie se va scrie numărul natu-
ral L reprezentând lungimea iniţială a beţelor, pe a doua linie se va scrie numărul natural K
reprezentând lungimea celui mai lung băţ care se poate obţine prin lipirea unui fragment aparţinţnd
Anei cu un fragment care aparţine lui Bogdan, iar pe a treia linie se va scrie numărul natural P
reprezentând numărul beţelor de lungime maximă care se pot obţine prin lipirea unui fragment
aparţinând Anei cu un fragment care aparţine lui Bogdan.
136
CAPITOLUL 11. OJI 2013 11.1. BETE 137
Exemple
bete.in bete.out Explicaţii
6 10 Lungimea iniţială este 10,
267135 16 lungimea maximă este 16
547893 1 şi se poate forma un singur băţ de lungime 16.
Pentru a determina lungimea initiala a betelor $L$ vom determina in $S$ suma
numerelor citite. Apoi evident
\hspace{7mm} L = S div N
#include<fstream>
ifstream fin("bete.in");
ofstream fout("bete.out");
int n,l,k,a,b,i,j,s,ma,mb,na,nb;
int main()
{
fin>>n;
fin>>a;
ma=a;na=1;s=a;
for(i=2;i<=n;i++)
{
fin>>a;
if(ma<a){ma=a;na=1;}
else if(ma==a)na++;
s+=a;
}
fin>>b;
mb=b;nb=1;s+=b;
for(i=2;i<=n;i++)
{
fin>>b;
CAPITOLUL 11. OJI 2013 11.2. CHIBRITURI 138
if(mb<b){mb=b;nb=1;}
else
if(mb==b) nb++;
s+=b;
}
l=s/n;
fout<<l<<’\n’<<ma+mb<<’\n’<<min(na,nb)<<’\n’;
fout.close();
return 0;
}
#include<fstream>
ifstream fin("bete.in");
ofstream fout("bete.out");
int n,l,k,a[1001],b[1001],i,j,s,p;
int main()
{
fin>>n;
s=0;
for(i=1;i<=n;i++)
{
fin>>a[i];
s+=a[i];
}
for(i=1;i<=n;i++)
{
fin>>b[i];
s+=b[i];
}
l=s/n;
k=0;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(a[i]+b[j]>k)
k=a[i]+b[j];
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(a[i]+b[j]==k)
{
p++;
a[i]=-1;
b[j]=-1;
};
fout<<l<<’\n’<<k<<’\n’<<p;
fout<<’\n’;
fout.close();
return 0;
}
11.2 chibrituri
Problema 2 - chibrituri 100 de puncte
CAPITOLUL 11. OJI 2013 11.2. CHIBRITURI 139
Lui Gigel, elev ı̂n clasa a V-a, ı̂i place grozav de tare să se joace cu
cifrele, cu numerele şi creează tot felul de probleme pe care apoi ı̂ncearcă
să le rezolve. Acum se joacă cu o cutie de chibrituri şi formează cu ele
cifre. Apoi privirea i-a căzut pe cadranul unui ceas electronic şi a văzut
că cifrele sunt formate din segmente orizontale şi verticale şi a ı̂nceput să Figura 11.1: chibrit-
formeze cu chibriturile cifrele care indică ora (vezi figura). uri1
Şi imediat şi-a pus o ı̂ntrebare: ”oare dacă am n chibrituri puse ver-
tical şi m chibrituri puse orizontal, care este ora minimă pe care o pot forma cu aceste chibrituri”
Cerinţe
Fiind date un număr n de chibrituri verticale şi un număr m de chibrituri orizontale, să se
scrie un program care determină numărul de ore posibile, ora minimă şi ora maximă care se
pot forma cu aceste chibrituri, ı̂n modul indicat mai sus, utilizând toate chibriturile respective şi
nemodificţnd orientarea acestora.
Date de intrare
Fişierul de intrare chibrituri.in conţine pe prima linie două numere naturale n m, separate
printr-un spaţiu, indicând numărul de chibrituri verticale (n), respectiv orizontale (m).
Date de ieşire
Pentru datele de test există ı̂ntotdeauna soluţie. Cifrele sunt formate din chibrituri ı̂n felul
următor:
Pentru determinarea corectă a numărului de variante se va acorda 20% din punctaj, pentru
determinarea corectă a numărului de variante şi a orei minime se va acorda 60% din punctaj, iar
pentru determinarea corectă a numărului de variante, a orei minime şi a orei maxime se va acorda
punctajul maxim.
Exemple
Retinerea valorilor o fac fie intr-un vector, fie in variabile fie ... pe hartie!
\begin{verbatim}
calculez ora
calculez minutele
calculez prima si a doua cifra a orei
calculez prima si a doua cifra a minutului
numar chibriturile verticale (fie din vector, fie din variabile, fie direct
ca si constante in instructiuni if sau switch)
numar chibriturile orizontale (la fel)
Afisez tinand cont ca daca am doar o solutie, aceasta este si ora maxima
#include <fstream>
ifstream fin("chibrituri.in");
ofstream fout("chibrituri.out");
bool OK1;
short int t, h1, h2, m1, m2, v, o, vOK, oOK, Cate;
short int h1min, h2min, m1min, m2min;
short int h1max, h2max, m1max, m2max;
int main()
{
fin >> vOK >> oOK;
t = 0; //plec de la ora 00:00
OK1 = false; //inca nu am gasit nici o ora corecta
Cate = 0;
while (t < 24 * 60) //intr-o zi sunt 24*60 minute
{ //trec pe la fiecare
m1 = t % 60; //ora
h1 = t / 60; //minute
h2 = h1 % 10; //a doua cifra a orei
h1 = h1 / 10; //prima cifra a orei
m2 = m1 % 10; //a doua cifra a minutului
m1 = m1 / 10; //prima cifra a minutului
{
case 1:
case 2:
case 3:
case 5:
case 7: v += 2; break;
case 4:
case 6:
case 9: v += 3; break;
case 0:
case 8: v += 4; break;
}
switch (h2)
{
case 1:
case 2:
case 3:
case 5:
case 7: v += 2; break;
case 4:
case 6:
case 9: v += 3; break;
case 0:
case 8: v += 4; break;
}
switch (m1)
{
case 1:
case 2:
case 3:
case 5:
case 7: v += 2; break;
case 4:
case 6:
case 9: v += 3; break;
case 0:
case 8: v += 4; break;
}
switch (m2)
{
case 1:
case 2:
case 3:
case 5:
case 7: v += 2; break;
case 4:
case 6:
case 9: v += 3; break;
case 0:
case 8: v += 4; break;
}
case 8:
case 9: o += 3; break;
}
switch (m1)
{
case 1: o += 0; break;
case 4:
case 7: o += 1; break;
case 0: o += 2; break;
case 2:
case 3:
case 5:
case 6:
case 8:
case 9: o += 3; break;
}
switch (m2)
{
case 1: o += 0; break;
case 4:
case 7: o += 1; break;
case 0: o += 2; break;
case 2:
case 3:
case 5:
case 6:
case 8:
case 9: o += 3; break;
}
fout.close();
return 0;
}
ifstream fin("chibrituri.in");
ofstream fout("chibrituri.out");
int OK1;
short int t, h1, h2, m1, m2, v, o, vOK, oOK, Cate;
short int h1min, h2min, m1min, m2min;
short int h1max, h2max, m1max, m2max;
int main()
CAPITOLUL 11. OJI 2013 11.2. CHIBRITURI 143
{
fin >> vOK >> oOK;
t = 0; //plec de la ora 00:00
OK1 = 0; //inca nu am gasit nici o ora corecta
Cate = 0;
while (t < 24 * 60) //intr-o zi sunt 24*60 minute
{ //trec pe la fiecare
m1 = t % 60; //ora
h1 = t / 60; //minute
h2 = h1 % 10; //a doua cifra a orei
h1 = h1 / 10; //prima cifra a orei
m2 = m1 % 10; //a doua cifra a minutului
m1 = m1 / 10; //prima cifra a minutului
fout << h1min << h2min << ’:’ << m1min << m2min << ’\n’;
else
fout << h1max << h2max << ’:’ << m1max << m2max << ’\n’;
fout.close();
return 0;
}
OJI 2012
12.1 alice
Problema 1 - alice 100 de puncte
Într-o zi frumoasă de vară, Alice se juca ı̂n parc. Deodată, văzu un
iepure cu ceas, numit Iepurele Alb, sărind grăbit ı̂n scorbura unui copac.
Curioasă, Alice ı̂l urmări şi sări şi ea ı̂n scorbură. Spre mirarea ei, ajunse
ı̂ntr-o sală mare cu N uşi ı̂ncuiate. Pe fiecare uşă era scris câte un număr
natural. Într-o clipă, lângă ea apăru Iepurele Alb şi-i spuse că doar uşile Figura 12.1: alice
cu numere magice pot fi deschise dacă are cheile potrivite. Pentru a o
ajuta, Iepurele Alb i-a explicat că un număr magic este un număr natural
care poate fi redus la o cifră prin complementarea cifrelor acestuia faţă de cifra sa maximă din
scrierea zecimală, apoi prin complementarea cifrelor numărului obţinut faţă de cifra sa maximă
şi aşa mai departe până când se obţine o cifră. Evident, nu toate numerele naturale sunt numere
magice. De exemplu, uşa cu numărul 1234 poate fi deschisă cu cheia inscripţionată cu cifra 1
deoarece 1234 este un număr magic ce poate fi redus la cifra 1 prin complementări repetate
(1234 3210 123 210 12 10 1), iar uşa cu numărul 1204 nu poate fi deschisă
deoarece 1204 nu este un număr magic (indiferent de câte ori s-ar repeta complementarea nu
poate fi redus la o cifră: 1204 3240 1204 3240 1204.).
Înainte să dispară, Iepurele Alb ı̂i dădu o cheie aurie inscripţionată cu cifra K şi o avertiză că
poate deschide cu această cheie doar uşile cu numere magice ce pot fi reduse la cifra K.
Cerinţe
Scrieţi un program care să citească numerele naturale N , K şi cele N numere naturale scrise
pe cele N uşi, şi care să determine:
a) cel mai mare număr par dintre numerele scrise pe cele N uşi;
b) numărul uşilor care pot fi deschise cu cheia aurie inscripţionată cu cifra K.
Date de intrare
Date de ieşire
144
CAPITOLUL 12. OJI 2012 12.1. ALICE 145
- complementarea cifrelor unui număr natural faţă de cifra sa maximă din scrierea zecimală
constă ı̂n ı̂nlocuirea fiecărei cifre c din număr cu diferenţa dintre cifra maximă şi cifra c; de
exemplu, cifra maximă a numărului 1234 este 4 iar prin complementare se ı̂nlocuieşte cifra 1 cu
3( 4 1), cifra 2 cu 2( 4 2), cifra 3 cu 1 ( 4 3) şi cifra 4 cu 0( 4 4) rezultând numărul
3210;
- 7 & N & 10000; 0 & K & 9;
- pe fiecare uşă este scris un singur număr natural;
- există cel puţin o uşă pe care este scris un număr par;
- numărul scris pe oricare uşă (din cele N ) este mai mare sau egal cu 10 şi mai mic sau egal
cu 32800;
- pentru rezolvarea corectă a cerinţei a) se acordă 20% din punctaj, iar pentru rezolvarea
corectă a ambelor cerinţe se acordă 100% din punctaj.
Exemple
alice.in alice.out Explicaţii
71 1234 a) Sunt N=7 uşi pe care sunt scrise numerele 1204, 1234,
1204 1234 13 195 23 10 888 3 13, 195, 23, 10, 888. Cel mai mare număr par dintre cele
scrise pe uşi este 1234, număr care se va scrie pe prima
linie a fişierului alice.out.
b) Cheia primită este inscripţionată cu cifra K=1 şi de-
schide 3 uşi cu numerele 1234, 23 şi 10 deoarece numerele
magice dintre cele scrise pe uşi sunt: 1234 (1234 3210
123 210 12 10 1), 13(13 20 2), 195(195
804 84 4), 23(23 10 1), 10(10 1), 888
(888 0). Numărul 1204 nu este un număr magic. Astfel
numărul 3 se va scrie pe a doua linie a fişierului alice.out.
Timp maxim de executare/test: 1.0 secunde
Memorie: total 2 MB din care pentru stivă 2 MB
Dimensiune maximă a sursei: 10 KB
#include <fstream>
int main()
{
int x,cmax,c,z,nrmax,i,nc=0,a, maxpar=0,n,j,nr=0,k;
ifstream f("alice.in");
ofstream g("alice.out");
f>>n>>k;
for(j=1;j<=n; j++)
{
f>>a;
z=x=a;
if(a%2==0 && maxpar<a)maxpar=a;
do
{
a=z; z=x; cmax=0; nc=0;
while(x)
{
c=x%10; x=x/10;nc++;
if(c>cmax)cmax=c;
}
nrmax=0;
for(i=1;i<=nc;i++)
nrmax=nrmax*10+cmax;
x=nrmax-z;
} while(x>9 && x!=z && x!=a);
if(x==k) nr++;
}
g<<maxpar<<endl<<nr;
return 0;
}
#include <fstream>
ifstream f("alice.in");
ofstream g("alice.out");
int i,n,x,m,k,nr;
int vm(int x)
{
int cmax=0,u=0;
while(x)
{
if(x%10>cmax) cmax=x%10;
x=x/10;
u=u*10+1;
}
return u*cmax;
}
CAPITOLUL 12. OJI 2012 12.1. ALICE 148
int complement(int x)
{
int nr=0,u;
if(x>9)return -1;
return x;
}
int main()
{
f>>n>>k;
while(n--)
{
f>>x;
if(x%2==0 && x>m) m=x;
if(complement(x)==k) nr++;
}
g<<m<<’\n’<<nr<<’\n’;
f.close();
g.close();
return 0;
}
ifstream f("alice.in");
ofstream g("alice.out");
int n,k,nr,maxim,x;
int main(void)
{
f>>n>>k;
g<<maxim<<endl;
g<<nr;
f.close();
g.close();
return 0;
}
int magic(int x)
{
int y=x,m=0,l=x,r=1,zero=0,ok=1,z=x;
if(x<10)
return x;
CAPITOLUL 12. OJI 2012 12.2. PORUMB 149
y=x;
while(y)
{
l=l+r*(m-y%10);
r=r*10;
y=y/10;
}
if(l==z)
ok=0;
else
{
ok=1;
z=x;
x=l;
}
}
if(l<10)
return l;
else
return -1;
}
12.2 porumb
Problema 2 - porumb 90 de puncte
Locuitorii planetei Agria, numiţi agri, au hotărât ca ı̂n celebrul an 2012 să le explice
pământenilor cum trebuie cules ”eficient” un rând cu n porumbi, numerotaţi, ı̂n ordine, cu
1, 2, 3, ..., n.
Cei n porumbi sunt culeşi de mai mulţi agri. Primul agri merge de-a lungul rândului, plecând
de la primul porumb şi culege primul porumb ı̂ntâlnit, al treilea, al cincilea şi aşa mai departe
până la capătul rândului. Atunci când ajunge la capătul rândului, porneşte al doilea agri şi culege
porumbi respectând aceeaşi regulă ca şi primul agri.
Metoda se repetă până când toţi porumbii sunt culeşi.
Pământeanul Ionel ı̂ncearcă să descopere ce ascunde această metodă şi se gândeşte câţi porumbi
culege primul agri, câţi agri culeg un rând cu n porumbi, la a câta trecere este cules porumbul cu
numărul x şi care este numărul ultimului porumb cules.
Exemplu: Dacă pe un rând sunt n=14 porumbi atunci sunt 4 agri care culeg porumbii:
a primul agri culege porumbii
1,3,5,7,9,11,13;
Date de intrare
Fişierul porumb.in conţine pe prima linie, separate printr-un spaţiu, cele două numere nat-
urale n şi x cu semnificaţia din enunţ.
Date de ieşire
Exemple
#include<iostream>
#include<fstream>
int main()
{ofstream out("porumb.out");
ifstream in("porumb.in");
int p=1,n,na=1,x,randx;
in>>n>>x;
out<<(n+1)/2<<endl;
while(p<n)
{p=p*2;
na++;
if((x-p)%(p*2)==0) randx= na;
CAPITOLUL 12. OJI 2012 12.2. PORUMB 152
if(p>n) {p=p/2;na--;}
if(x%2==1) randx=1;
out<<na<<endl<<randx<<endl<<p<<endl;
in.close();
out.close();
return 0;
}
int n,x;
int main()
{
int m=1,k=0,nr=0;
freopen("porumb.in","r",stdin);
freopen("porumb.out","w",stdout);
while(m<=n)
m*=2;
m/=2;
while(x%2==0)
{
x/=2;
k++;
}
while(n!=0)
{
nr++;
n/=2;
}
return 0;
}
#include <fstream>
#include <iostream>
int main()
{
ifstream f("porumb.in");
ofstream g("porumb.out");
int n,x,pas=1,t=0,tx=0,u=0,k=0,m;
f>>n>>x;
g<<(n+1)/2<<endl;
m=n;
CAPITOLUL 12. OJI 2012 12.2. PORUMB 153
while(k!=m)
{ t++; //o noua trecere
k=k+(n+1)/2; //nr.porumbi culesi=nr de nr impare <=n
//sirul: pas(1,2,3,4,5,6,7), pas=2ˆ(t-1)
u=n*pas;
if(n%2==0) u-=pas;
if(x%pas==0)tx=t;
n/=2; pas*=2;
}
if(x%2)tx=1;
g<<t<<endl<<tx<<endl<<u<<endl;
}
#include <fstream>
#include <iostream>
#include <cmath>
int main()
{
ifstream f("porumb.in");
ofstream g("porumb.out");
int n,x,a,t,ult,u;
f>>n>>x;
g<<(n+1)/2<<endl;
u=log10(n*1.0)/log10(2.); //u<--log2(n)
a=u+1; //a<--2ˆ(u+1)
ult=pow(2.0,u); //ult<--2ˆu
t=1;
while(x%2==0){t++; x>>=1;}
g<<a<<endl<<t<<endl<<ult<<endl;
return 0;
}
# include <fstream>
long n,m,x,nr;
int main()
{ifstream f("porumb.in");
ofstream g("porumb.out");
f>>n>>x;
//b) nr trasee
m=n;
while(m>0)nr++,m=m/2;
g<<nr<<’\n’;
g<<m+1<<’\n’;
g<<m<<’\n’;
f.close();
g.close();
return 0;
}
#include<fstream>
#include<math.h>
ifstream f("porumb.in");
ofstream g("porumb.out");
int nr,n,x,nr1=1,aux;
long long q;
int main()
{f>>n>>x;
aux=x;
//numarul de agri
while(n!=0)
{
n=n/2;
nr++;
}
g<<nr<<’\n’;
q=pow(2,nr-1);
g<<q<<’\n’;
f.close();
g.close();
return 0;
}
#include <iostream>
#include <fstream>
#include <conio.h>
#include <math.h>
int main(void)
{unsigned long n,x,p=1,e=0,a,b;
CAPITOLUL 12. OJI 2012 12.2. PORUMB 155
fstream f,g;
f.open("porumb.in", ios::in);
f>>n>>x;
while (p*2<n)
{
p*=2;
e++;
}
if (x%2)b=1;
else
{
a=p;b=0;
while (x%a!=0)
{
a/=2;
b++;
}
}
g.open("porumb.out", ios::out);
g<<(n+1)/2<<endl<<e+1<<endl<<e+1-b<<endl<<p;;
g.close();
}
OJI 2011
13.1 magic
Problema 1 - magic 100 de puncte
Rămaşi singuri ı̂n pădure, Hansel şi Grettel, ştiu că singura lor şansă de supravieţuire este să
găsească şi să intre ı̂n Castelul de Turtă Dulce. Poarta castelului este ı̂nchisă şi pentru a intra
este nevoie de un cuvânt magic şi de un număr fermecat.
Zâna cea Bună ı̂i vede pe copii şi pentru că vrea să-i ajute le spune: ”Mergeţi tot ı̂nainte,
iar ı̂n drumul vostru o să ı̂ntâlniţi copaci pe a căror trunchiuri sunt scrise caractere reprezentând
litere sau cifre. Cuvântul magic este format din toate caracterele literă ı̂n ordinea ı̂n care apar,
dar scrise toate cu majuscule. Numărul fermecat este cel mai mic număr cu cifre distincte care se
poate forma din caracterele cifră.”
Cerinţe
Pentru a-i ajuta pe Hansel şi Grettel să intre ı̂n Castelul de Turtă Dulce, scrieţi un program
care citeşte un număr natural n, apoi n caractere şi determină:
a) cuvântul magic;
b) numărul fermecat;
Date de intrare
Fişierul magic.in conţine pe prima linie un număr natural n, reprezentând numărul de car-
actere scrise pe copaci. Pe cea de a doua linie sunt n caractere separate prin câte un spaţiu,
reprezentând caracterele scrise pe copaci.
Date de ieşire
Fişierul de ieşire magic.out va conţine două linii:
a) pe prima linie se va scrie un şir de litere mari, reprezentând cuvântul magic;
b) pe a doua linie se va scrie un număr natural cu cifre distincte, reprezentând numărul
fermecat.
Restricţii şi precizări
a 1 & n & 1000
a Caracterele sunt doar cifre sau litere mici ale alfabetului englez.
a Printre cele n caractere se află ı̂ntotdeauna cel puin o literă şi cel puţin o cifră.
a Pe fiecare copac este scris un singur caracter.
a Numărul magic ı̂ncepe ı̂ntotdeauna cu o cifră diferită de zero.
Pentru rezolvarea cerinţei a) se acordă 40% din punctaj, pentru cerinţa b) 60% din punctaj
Exemple
magic.in magic.out Explicaţii
6 CB Cel mai mic număr cu cifre distincte
c255b2 25 ce se poate obţine este 25.
8 CABD 205 Cel mai mic număr cu cifre distincte
ca50b25d ce se poate obţine este 205.
Timp maxim de executare/test: 1.0 secunde
156
CAPITOLUL 13. OJI 2011 13.1. MAGIC 157
char s[1001];
int c[10];
int n;
int main()
{
int i,ncifre=0,j;
ifstream f("magic.in");
ofstream g("magic.out");
f>>n;
for(i=1;i<=n;i++)
{
f>>s[i];
s[i]=toupper(s[i]);
if(isdigit(s[i]))
{
ncifre++;
c[s[i]-48]++;
}
}
for(i=1;i<=n;i++)
if(isalpha(s[i]))
g<<s[i];
g<<’\n’;
i=1;
CAPITOLUL 13. OJI 2011 13.1. MAGIC 158
while(c[i]==0) i++;
if(c[0])
g<<i<<0;
else
g<<i;
for(j=i+1;j<=9;j++)
if(c[j])
g<<j;
f.close();
g.close();
return 0;
}
char s;
int n;
int c0,c1,c2,c3,c4,c5,c6,c7,c8,c9;
int main()
{
int i;
int nr;
ifstream f("magic.in");
ofstream g("magic.out");
f>>n;
for (i=1;i<=n;i++)
{
f>>s;
if(isalpha(s))
{
s=toupper(s);
g<<s;
}
else
{
nr=int(s)-48;
switch(nr)
{
case 0: c0++;break;
case 1: c1++;break;
case 2: c2++;break;
case 3: c3++;break;
case 4: c4++;break;
case 5: c5++;break;
case 6: c6++;break;
case 7: c7++;break;
case 8: c8++;break;
case 9: c9++;break;
}
}
}
g<<’\n’;
int t=0;
if(c1)
{
g<<1;
if(c0 && t==0)
{
t=1;
g<<0;
CAPITOLUL 13. OJI 2011 13.1. MAGIC 159
}
}
if(c2)
{
g<<2;
if(c0 && t==0)
{
t=1;
g<<0;
}
}
if(c3)
{
g<<3;
if(c0 && t==0)
{
t=1;
g<<0;
}
}
if(c4)
{
g<<4;
if(c0 && t==0)
{
t=1;
g<<0;
}
}
if(c5)
{
g<<5;
if(c0 && t==0)
{
t=1;
g<<0;
}
}
if(c6)
{
g<<6;
if(c0 && t==0)
{
t=1;
g<<0;
}
}
if(c7)
{
g<<7;
if(c0 && t==0)
{
t=1;
g<<0;
}
}
if(c8)
{
g<<8;
if(c0 && t==0)
{
t=1;
g<<0;
}
}
if(c9)
{
g<<9;
CAPITOLUL 13. OJI 2011 13.1. MAGIC 160
f.close();
g.close();
return 0;
}
int x[10];
int main()
{
ifstream fin("magic.in");
ofstream fout("magic.out");
int n, g = 0, i;
char c;
fin >> n;
fout << c;
}
else
{
x[c-48]++;
g = 1;
}
}
fout<<’\n’;
i = 1;
while(x[i] == 0)i++;
fin.close();
fout.close();
return 0;
}
ifstream f("magic.in");
CAPITOLUL 13. OJI 2011 13.1. MAGIC 161
ofstream g("magic.out");
int n,i;
char c;
int x[10];
int main()
{
f>>n;
for(i=1;i<=n;i++)
{
f>>c;
if(c>=’a’ && c<=’z’) g<<(char)(c-32);
else x[c-48]=1;
}
g<<’\n’;
if(x[0]!=0)
{
i=1;
while(x[i]==0 && i<=9)i++;
}
if(i<=9){g<<i;x[i]=0;}
for(i=0;i<=9;i++)
if(x[i]) g<<i;
f.close();
g.close();
return 0;
}
ifstream f("magic.in");
ofstream g("magic.out");
int main()
{
int n,i; char x;
f>>n;
for(i=1;i<=n;i++)
{
f>>x;
if (!(x>=’0’ && x<=’9’)) g<<(char)(x-32);
else
switch (x)
{
case ’0’:x0++; break;
case ’1’: x1++; break;
case ’2’: x2++; break;
case ’3’: x3++; break;
case ’4’: x4++; break;
case ’5’: x5++; break;
case ’6’: x6++; break;
case ’7’: x7++; break;
case ’8’: x8++; break;
case ’9’: x9++; break;
}
}
if(nr==0) g<<’\n’<<0<<’\n’;
else g<<’\n’<<nr<<’\n’;
f.close();
g.close();
return 0;
}
13.2 numerus
Problema 2 - numerus 100 de puncte
La ora de matematică distractivă, domnul profesor Numerus
propune elevilor săi să completeze cu numere naturale o grilă cu 6
coloane numerotate cu literele A, B, C, D, E şi F şi cu un număr in-
finit de linii. Grila va fi completată cu numere naturale, ı̂ncepând
cu numărul 1. Pe liniile impare completarea se va face de la stânga
la dreapta, iar pe cele pare de la dreapta la stânga. Ultimul număr
de pe o linie va fi identic cu penultimul număr (ı̂n sensul com-
pletării) de pe aceeaşi linie. ı̂n figura alăturată aveţi completate
primele 7 linii ale grilei. Deoarece pe tablă sau pe o foaie de hârtie
numărul de linii este limitat, deci grila poate fi efectiv comple-
tată doar pentru un număr mic de linii, domnul profesor Numerus
Figura 13.1: Numerus
doreşte ca elevii săi să determine, cu ajutorul calculatorului, imag-
inea unei anumite linii a grilei şi locul sau locurile pe care se poate afla un număr natural dat
Cerinţe
Deduceţi regula după care se completează linia k a grilei şi scrieţi un program care să citească
numerele naturale k şi n şi care să determine:
a) numerele naturale de pe linia k, vizualizate de la stânga la dreapta;
b) linia pe care se află ı̂n grilă numărul natural n;
c) coloana sau coloanele pe care se află ı̂n grilă numărul natural n.
Date de intrare
Fişierul numerus.in conţine o singură linie pe care sunt scrise două numere naturale k şi n,
separate pritr-un spaţiu.
Date de ieşire
CAPITOLUL 13. OJI 2011 13.2. NUMERUS 163
Exemple
ifstream f("numerus.in");
ofstream g("numerus.out");
long n,i,k,a,b,l,c;
int main()
{
f>>k>>n;
a=5*(k-1)+1;
b=5*k;
if(k%2==1)
{
for(i=a;i<=b;i++) g<<i<<’ ’;
g<<b;
}
else
{
g<<b<<’ ’;
for(i=b;i>=a;i--) g<<i<<’ ’;
}
g<<’\n’;
l=n/5;
if(n%5!=0)l++;
g<<l<<’\n’;
if(n%5==0)
if(l%2==0) g<<’A’<<’ ’<<’B’;
else g<<’E’<<’ ’<<’F’;
else if(l%2==1) {char c=’A’+n%5-1;g<<c;}
else{char c=’F’-n%5+1;g<<c;}
g<<’\n’;
f.close();
g.close();
return 0;
}
ifstream f("numerus.in");
ofstream g("numerus.out");
long n,k;
int main()
{
long lin;
f>>k>>n;
lin=n/5;
//prima cerinta
if(k%2==0)
g<<5*k<<’ ’<<5*k<<’ ’<<5*k-1<<’ ’<<5*k-2<<’ ’<<5*k-3<<’ ’<<5*k-4<<’\n’;
else
g<<5*k-4<<’ ’<<5*k-3<<’ ’<<5*k-2<<’ ’<<5*k-1<<’ ’<<5*k<<’ ’<<5*k<<’\n’;
// a treia cerinta
if(lin%2==0)
if(n%5==0) g<<’A’<<’ ’<<’B’;
else g<<(char)(’B’+(5-n%5));
else if(n%5==0) g<<’E’<<’ ’<<’F’;
CAPITOLUL 13. OJI 2011 13.2. NUMERUS 165
else g<<(char)(’E’-(5-n%5));
g<<’\n’;
f.close();
g.close();
return 0;
}
int main()
{
long k, n;
long i, r, rd;
ifstream fin("numerus.in");
ofstream fout("numerus.out");
if(k % 2 == 1)
{
for(i = 1; i<= 5; i++)
fout << (k-1)*5 +i<< " ";
fout << k *5<<"\n";
}
else
{
fout << k*5<< " ";
for(i = 0; i< 5; i++)
fout << k * 5 - i<< " ";
fout << "\n";
}
if( n%5 == 0)
{
rd = n/5;
fout <<rd<<’\n’;
}
else
{
rd = (n/5 +1);
fout << rd<< "\n";
}
if(n%10 == 0 )
fout << ’A’<<" "<<’B’<<"\n";
else
if(n%5 == 0) fout << ’E’<<" "<<’F’<< "\n";
if(rd % 2 == 1)
{
r = n%5;
switch(r)
{
case 1: fout << ’A’<<"\n";break;
case 2: fout << ’B’<<"\n";break;
case 3: fout << ’C’<<"\n";break;
case 4: fout << ’D’<<"\n";break;
}
}
else
{
r = n%5;
switch(r)
{
case 1: fout << ’F’<<"\n";break;
case 2: fout << ’E’<<"\n";break;
case 3: fout << ’D’<<"\n";break;
case 4: fout << ’C’<<"\n";break;
}
CAPITOLUL 13. OJI 2011 13.2. NUMERUS 166
fin.close();
fout.close();
return 0;
}
OJI 2010
14.1 sir
Problema 1 - sir 100 de puncte
Se generează un şir de numere naturale ai cărui primi termeni sunt, ı̂n ordine:
1, 12, 21, 123, 231, 312, 1234, 2341, 3412, 4123, 12345, 23451, ...
Cerinţe
Deduceţi regula după care sunt generaţi termenii şirului şi scrieţi un program care să citească
numerele naturale k, x, a şi b şi care să determine:
a) ultima cifră a sumei tuturor termenilor şirului care sunt formaţi din cel mult k cifre;
b) succesorul termenului x ı̂n şirul dat, x fiind un termen al şirului;
c) numărul de termeni ai şirului care au cifra cea mai semnificativă egală cu a şi nu conţin ı̂n
scrierea lor cifra b.
Date de intrare
Fişierul de intrare sir.in conţine o singură linie pe care sunt scrise cele patru numere naturale k,
x, a şi b, separate prin câte un spaţiu.
Date de ieşire
167
CAPITOLUL 14. OJI 2010 14.1. SIR 168
Exemple
sir.in sir.out Explicaţii
3 45123 3 6 0 Termenii şirului formaţi fiecare din cel mult k 3 cifre sunt:
51234 1, 12, 21, 123, 231, 312. Suma lor fiind egală cu 700, pe
3 prima linie a fişierului sir.out se va scrie cifra 0 (ultima cifră
a sumei).
Succesorul termenului 45123 este 51234, valoare care se va
scrie pe a doua linie a fişierului sir.out.
Sunt 3 numere care ı̂ncep cu cifra 3 şi care nu conţin cifra 6
şi anume: 312, 3412, 34512. Astfel, numărul 3 se scrie pe a
treia linie a fişierului sir.out.
#include<fstream>
int main()
{ofstream g("sir.out");
long x,y,p=1,z;
int k,s=0,a,b,i,c,sa;
ifstream f("sir.in");
f>>k>>x>>a>>b;
s=1; sa=1;
for(i=2;i<=k;i++)
{
s=(s+sa+i)%10;
sa=(sa+i)%10;
}
g<<s<<endl;
//cerinta b)
y=x; k=1;
while(y>9)
{ k++; y/=10; p=p*10; }
if(y==k)
{ z=0;
for(i=1;i<=k+1; i++)
z=z*10+i;
}
else z=(x%p)*10+y;
g<<z<<endl;
//cerinta c)
if(a<b) g<<b-a;
else g<<0;
f.close();
g.close();
return 0;
}
#include <fstream>
unsigned k,a,b,uc,i,nr;
unsigned long x;
CAPITOLUL 14. OJI 2010 14.1. SIR 171
ifstream f("sir.in");
ofstream g("sir.out");
int main()
{
f>>k>>x>>a>>b;
//a)
for(i=0;i<k*(k+1)/2;i++)
uc=(uc+s[i]%10)%10;
g<<uc<<’\n’;
//b)
i=0;
while(s[i]<=x) i++;
g<<s[i]<<’\n’;
//c)
if(a<b)g<<(9-a+1)-(9-b+1);
else g<<0;
f.close();
g.close();
return 0;
}
# include <fstream>
# include <math.h>
int k,a,b,u,i,c;
long x,y,p;
int main()
{ ifstream f("sir.in");
ofstream g("sir.out");
f>>k>>x>>a>>b;
//a
u=0;
for(i=1;i<=k;i++) u=(u+i*(i+1)/2)%10;
g<<u<<endl;
//b
u=0;y=x;
while(y){u++;c=y%10; y=y/10;}
if(c==u)
for(i=1;i<=u+1;i++)y=y*10+i;
else
{
p=pow(10,u-1);
y=x%p*10+x/p;
}
g<<y<<endl;
//c
c=(b>a)?b-a:0;
g<<c;
f.close();
g.close();
return 0;
}
#include <fstream>
int k,a,b,u,i,n,v[11];
long x;
int main()
{ ifstream f("sir.in");
ofstream g("sir.out");
f>>k>>x>>a>>b;
//a
u=0;
for(i=1;i<=k;i++) u=(u+i*(i+1)/2)%10;
g<<u<<endl;
//b
n=0;
while(x){n++;v[n]=x%10;x=x/10;}
if(v[n]==n)
for(i=1;i<=n+1;i++)g<<i;
else
{
for(i=n-1;i>=1;i--) g<<v[i];
g<<v[n];
}
g<<endl;
//c
u=(b>a)?b-a:0;
g<<u;
f.close();
g.close();
return 0;
}
#include<fstream>
ifstream f("sir.in");
ofstream g("sir.out");
int main()
{
int k,a,b;
long x;
f>>k>>x>>a>>b;
//punctul a)
int i,uc=0;
uc=(k*(k+1)*(k+2)/6)%10;
g<<uc<<"\n";
//punctul b)
long aux=x,p=1;
int nrcif=0,pc;
uc=x%10;
while(aux)
{
nrcif++;
p=p*10;
aux=aux/10;
}
p=p/10;
if(x>1)
{
CAPITOLUL 14. OJI 2010 14.2. TREN 173
if(nrcif-1==uc)
for(i=1;i<=nrcif+1;i++)
g<<i;
else
g<<(x%p)*10+x/p;
}
else
g<<"12";
g<<"\n";
//punctul c)
if(b<=a)
g<<"0";
else
g<<b-a;
return 0;
}
#include <fstream>
int main()
{ long x; int v[10];
int k,i,s=0,a,b;
ifstream f("sir.in");
ofstream g("sir.out");
f>>k>>x>>a>>b;
for(s=1,i=2;i<=k;i++)
s=(s+i*(i+1)/2)%10;
g<<s<<endl;
k=0;
while(x)
{
k++; v[k]=x%10; x=x/10;
}
if(v[k]==k)
for(i=1;i<=k+1;i++)
g<<i;
else
{ v[0]=v[k];
for(i=k-1;i>=0;i--)
g<<v[i];
}
if(a<b)g<<endl<<b-a;
else g<<endl<<0;
g.close();
return 0;
}
14.2 tren
Problema 2 - tren 100 de puncte
CAPITOLUL 14. OJI 2010 14.2. TREN 174
Un elev ı̂n clasa a V-a, Rareş, s-a gândit să studieze mersul trenurilor ce trec prin gara din
oraşul său, ı̂ntr-o zi. Gara are 2 linii, numerotate cu 1 şi 2, pe care sosesc şi pleacă trenurile. În
acea zi, ı̂n gară sosesc T trenuri. Pentru fiecare tren din cele T , Rareş cunoaşte linia L pe care
va sosi, momentul sosirii, adică ora H şi minutul M , precum şi durata de timp S de staţionare
(exprimată ı̂n minute). El a decis ca perioada de studiu a celor T trenuri să ı̂nceapă cu momentul
sosirii primului tren ı̂n gară din cele T şi să se ı̂ncheie odată cu momentul plecării ultimului tren
din cele T .
Din sala de aşteptare Rareş poate vedea cele 2 linii. Rareş are ı̂nsă o problemă: atunci când
un tren se află ı̂n gară pe linia 1, el nu poate vedea trenul staţionat ı̂n acelaşi timp pe linia 2.
De exemplu, dacă un tren ajunge ı̂n gară pe linia 1 la ora 14 21 şi staţionează 5 minute atunci
trenul va pleca din gară la ora 14 26. Astfel, ı̂n intervalul de timp 14 21 14 26, Rareş nu
poate vedea ce se ı̂ntâmplă pe linia 2. Trenul de pe linia 2 va putea fi vizibil ı̂ncepând cu minutul
următor, adică de la 14 27.
Cerinţe
Scrieţi un program care să determine pentru un număr T de trenuri care trec prin gară ı̂n
perioada de studiu din acea zi:
a numărul maxim de trenuri Z care au staţionat pe aceeaşi linie;
a numărul X de trenuri pe care Rareş le vede;
a durata de timp maximă Y (exprimată ı̂n număr de minute consecutive), din perioada de
studiu, ı̂n care Rareş nu a văzut niciun tren.
Date de intrare
Fişierul de intrare tren.in conţine pe prima linie numărul T de trenuri şi pe fiecare din
următoarele T linii, ı̂n ordinea sosirii trenurilor ı̂n gară, câte patru numere naturale L, H, M
şi S, separate prin câte un spaţiu, ce reprezintă linia L pe care soseşte trenul, momentul sosirii
trenului (ora H şi minutul M ) şi durata de timp S de staţionare.
Date de ieşire
Fişierul de ieşire tren.out conţine pe prima linie, separate prin câte un spaţiu, valorile cerute
Z, X şi Y (ı̂n această ordine).
- 2 & T & 100; 0 & H & 23; 0 & M & 59; 1 & S & 9; T , H, M , S sunt numere naturale;
- ı̂n acelaşi moment de timp nu pot pleca/sosi mai multe trenuri;
- ı̂n acelaşi moment de timp nu poate pleca un tren şi altul să sosească;
- pe aceeaşi linie nu pot staţiona mai multe trenuri ı̂n acelaşi moment de timp;
- pentru aflarea corectă a numărului Z se acordă 20% din punctajul pe test;
- pentru aflarea corectă a numărului X se acordă 40% din punctajul pe test;
- pentru aflarea corectă a numărului Y se acordă 40% din punctajul pe test.
Exemple
a) Solutia cu vectori retine in vectorul g starea fiecarui minut de pe parcursul unei zile.
In fiecare moment Rares vede cel mult un tren.
Vectorul v, retine starea fiecarui tren care a trecut prin gara.
# include <fstream.h>
ifstream fi("tren.in"); ofstream fo("tren.out");
int x,t,y,z,u,t1,l,h,m,s,i,j,vine,pleaca,g[1441],v[101],inc=1441,sf;
void main()
{ fi>>t;
for(i=1;i<=t;i++)
{ fi>>l>>h>>m>>s;
vine=h*60+m;pleaca=vine+s;
if(i==1)inc=vine;
if(sf<pleaca) sf=pleaca;
if(l==1) { t1++; for(j=vine;j<=pleaca;j++)g[j]=i;}
else
for(j=vine;j<=pleaca;j++)if(g[j]==0)g[j]=i;
//trenul de pe linia 2 este vizibil numai daca nu avem tren pe linia 1
}
b) Solutia fara vectori memoreaza in t1 numarul de trenuri care ajung pe linia 1 si actualizeaza
pentru fiecare tren sosit valorile x, y si z. Un tren care ajunge pe linia 1 va fi intotdeauna vizibil.
CAPITOLUL 14. OJI 2010 14.2. TREN 176
Un tren care ajunge pe linia 2 va fi vizibil daca in timpul stationarii exista cel putin un minut in
care linia 1 nu este ocupata.
Pentru determinarea intervalului maxim in care ambele linii sunt libere trebuie sa calculam
cea mai mare diferenta dintre momentul in care a plecat un tren si a sosit altul si in tot acest timp
liniile au fost libere.
# include <fstream.h>
ifstream f("tren.in");
ofstream g("tren.out");
int x=1,t,y,z,t1,l,h,m,sta,s,p,am2,i,p1,p2,u;
void main()
{ f>>t;
f>>l>>h>>m>>sta;
u=h*60+m+sta;
if(l==1) t1++,p1=u;
else p2=u;
for(i=2;i<=t;i++)
{ f>>l>>h>>m>>sta;
s=h*60+m; p=s+sta; //s-momentul sosirii, p-momentul plecarii
if(s-u>y) y=s-u;
if(s>p1+1 && am2==1 && p2>p1) x++,am2=0;
// vad trenul care se afla acum pe linia 2
if(l==1) x++,t1++,p1=p;
else
if (s>p1) x++,am2=0,p2=p;
// vine un tren pe linia 2 si linia 1 este libera
else
if (p>p1) p2=p,am2=1;
// vine un tren pe linia 2 si linia 1 este ocupata
u=(p1>p2)?p1:p2;
}
if(am2)x++;
z = (t1>t-t1) ? t1 : t-t1;
if(y) y--;
f.close();
g.close();
}
int timp[1382];
int t,i,j,l,h,m,s,x,y,z,nrt1,nrt2,ts,tp,tmp;
ifstream f("tren.in");
ofstream g("tren.out");
CAPITOLUL 14. OJI 2010 14.2. TREN 177
int main()
{
f>>t;
for(i=1;i<=t;i++)
{
f>>l>>h>>m>>s;
if(l==1) nrt1++;
else nrt2++;
ts=h*60+m;tp=ts+s;
for(j=ts;j<=tp;j++)
if(l==1) timp[j]=i;
else if(l==2 && timp[j]==0) timp[j]=i;
}
//b)
for(i=1;i<=1381;i++)
if(timp[i]!=timp[i-1] && timp[i]!=0) x++;
//c)
i=0;while(timp[i]==0) i++;
for(;i<=1381;i++)
if(timp[i]==0) tmp++;
else
{
if(tmp>y) y=tmp; tmp=0;
}
z=(nrt1+nrt2+abs(nrt1-nrt2))/2;
g<<z<<" "<<x<<" "<<y;
f.close();
g.close();
return 0;
}
ifstream fi("tren.in");
ofstream fo("tren.out");
long lin[1441];
int main()
{ long t,z,x,y,h,m,s,i,os,op,l;
fi>>t;
long n1,n2,j,pi=1441,pf=0;
n1=0; n2=0;
for(i=1;i<=t;i++)
{
fi>>l>>h>>m>>s;
os=h*60+m;
op=os+s;
if(pi>os)pi=os;
if(pf<op)pf=op;
if(l==1)n1++; else n2++;
for(j=os;j<=op;j++)
{ if(l==1) lin[j]=lin[j]+n1;
else lin[j]=n2*1000+lin[j];
}
}
z=n1;
if(z<n2) z=n2;
y=0;
x=0;
long val=lin[pi],t1,t2;
unsigned long d=0;
t1=t2=0;
i=pi;
CAPITOLUL 14. OJI 2010 14.2. TREN 178
while(i<=pf)
{
if(lin[i]==0){i++;d++;}
else
{ val=lin[i];
if(val%1000)
{ if(t1!=val%1000)
{
t1=val%1000;
x++;
}
if((lin[i]%1000==val%1000)&&(i<=pf))i++;
}
else
{ if(t2!=val/1000)
{
t2=val/1000;
x++;
}
if((lin[i]/1000==val/1000)&&(val%1000==0)&&(i<=pf))i++;
}
if(d>y)y=d;
d=0;
}
}
fo.close();
fi.close();
return 0;
}
ifstream f("tren.in");
ofstream g("tren.out");
int x=1,t,y,z,t1,l,h,m,sta,s,p,am2,i,p1,p2,u;
int main()
{ f>>t;
f>>l>>h>>m>>sta;
u=h*60+m+sta;
if(l==1) t1++,p1=u;
else p2=u;
for(i=2;i<=t;i++)
{
f>>l>>h>>m>>sta;
s=h*60+m; p=s+sta;
if(s-u>y) y=s-u;
if(s>p1+1 && am2==1 && p2>p1) x++,am2=0;
if(l==1) x++,t1++,p1=p;
else if (s>p1) x++,am2=0,p2=p;
else if (p>p1) p2=p,am2=1;
u=(p1>p2)?p1:p2;
}
if(am2)x++;
z=(t1>t-t1)?t1:t-t1;
if(y)y--;
f.close();
g.close();
return 0;
}
CAPITOLUL 14. OJI 2010 14.2. TREN 179
ifstream fi("tren.in");
ofstream fo("tren.out");
int x,t,y,z,u,t1,l,h,m,s,i,j,vine,pleaca,g[1441],v[101],inc=1441,sf;
int main()
{ fi>>t;
for(i=1;i<=t;i++)
{ fi>>l>>h>>m>>s;
vine=h*60+m;pleaca=vine+s;
if(i==1)inc=vine;
if(sf<pleaca) sf=pleaca;
if(l==1) { t1++; for(j=vine;j<=pleaca;j++)g[j]=i;}
else for(j=vine;j<=pleaca;j++)if(g[j]==0)g[j]=i;
}
z=(t1>t-t1) ? t1:t-t1;
y=0;
for(i=inc;i<=sf;i++)
{ v[g[i]]=1;
if(g[i]==0) u++;
else
{
if(u>y)y=u;
u=0;
}
}
x=0;
for(i=1;i<=t;i++) x=x+v[i];
fi.close();
fo.close();
return 0;
}
ifstream f("tren.in");
ofstream g("tren.out");
int x,t,y,z,u,t1,l,h,m,s,i,j,vine,pleaca,l1[1441],l2[1441],v[101],inc=1441,sf;
int main()
{ f>>t;
for(i=1;i<=t;i++)
{ f>>l>>h>>m>>s;
vine=h*60+m;pleaca=vine+s;
if(inc>vine) inc=vine;
if(sf<pleaca) sf=pleaca;
if(l==1) { t1++; for(j=vine;j<=pleaca;j++)l1[j]=i;}
else for(j=vine;j<=pleaca;j++)l2[j]=i;
}
z=(t1>t-t1) ? t1 : t-t1;
y=0;
for(i=inc;i<=sf;i++)
{ v[l1[i]]=1;
if(l1[i]==0)v[l2[i]]=1;
CAPITOLUL 14. OJI 2010 14.2. TREN 180
if(l1[i]+l2[i]==0) u++;
else
{
if(u>y)y=u;
u=0;
}
}
x=0;
for(i=1;i<=t;i++) x=x+v[i];
g<<z<<’ ’<<x<<’ ’<<y;
f.close();
g.close();
return 0;
}
ifstream f("tren.in");
ofstream g("tren.out");
int t,l,h,m,s;
int nr1,nr2,z,gasit,ultim;
int tp,x;
int maxx,y,timpc,poz;
int main()
{
int i;
f>>t;
for(i=1;i<=t;i++)
{
f>>l>>h>>m>>s;
/*Daca exista un tren pe linia 2, iar pe linia 1 sosesc trenuri
la interval de o secunda unul de altul, trenul de pe linia 2 nu se vede
si deci va fi scazut din numaratoare (o singura data!: ultim=tp;)
ultim reprezinta timpul de plecare din statie al trenului de pe linia 2*/
if(gasit)
{
gasit=0;
x--;
ultim=tp;
}
if(l==1)
{
nr1++;
x++;
if(ultim>h*60+m && h*60+m-tp==1 && i>1)
gasit=1;
tp=h*60+m+s;
}
else
{
nr2++;
if(h*60+m>tp||h*60+m+s>tp)
{
x++;
ultim=h*60+m+s;
}
}
if(h*60+m>maxx)
{
timpc=h*60+m-maxx;
maxx=h*60+m+s+1;
if(timpc>y && i>1) y=timpc;
}
else
if(h*60+m+s>maxx)
maxx=h*60+m+s+1;
CAPITOLUL 14. OJI 2010 14.2. TREN 181
return 0;
}
182
Capitolul 15
ONI 2023
15.1 cadouri
Problema 1 - Cadouri 100 de puncte
Înaintea vacanţei de Paşte, la şcoală, s-au primit cadouri pentru elevii din clasa a V-a. Sunt
N cutii cu bomboane şi se cunoaşte numărul de bomboane din fiecare cutie. Numărul de cutii
de bomboane primite de fiecare copil trebuie să fie acelaşi. Acest număr trebuie să
fie mai mare sau egal cu 2.
Cutiile cu bomboane vor fi oferite ı̂n ordinea primirii, primele cutii primului copil, următoarele
cutii celui de al doilea copil, următoarele cutii celui de al treilea copil etc.
Se doreşte să se ı̂mpartă cutiile cu bomboane unui număr cât mai mare de copii. De asemenea,
mai este o condiţie: să se ı̂mpartă copiilor toate cutiile, sau cel mult una dintre cutii să rămână
neoferită.
În cazul că se ia decizia ca o cutie să nu fie dată copiilor, aceasta se păstrează de către doamna
dirigintă pentru a-i servi pe aceştia la ı̂ntoarcerea la şcoală, iar restul cutiilor cu bomboane se pun
pe catedră ı̂n ordinea ı̂n care au fost primite, fără ca elevii să ştie despre cea păstrată.
Alegerea acestei cutii trebuie făcută astfel ı̂ncât numărul total de bomboane care se
ı̂mpart să fie cât mai mare.
Cerinţe
Pentru ambele cerinţe trebuie determinat şi numărul de bomboane din cutia care eventual se
păstrează.
Date de intrare
Date de ieşire
Fişierul de ieşire cadouri.out conţine două numere naturale, separate printr-un singur spaţiu
liber, cu următoarea semnificaţie: pentru C = 1 prima valoare este numărul maxim de copii care
primesc cadouri iar a doua este numărul de bomboane din cutia păstrată; pentru C = 2 prima
valoare este numărul maxim de bomboane primite de un copil iar a doua reprezintă numărul de
bomboane din cutia păstrată.
Dacă nu se păstrează nicio cutie, ı̂n fişierul de ieşire a doua valoare scrisă va fi 0 (atât ı̂n cazul
cerinţei 1 cât şi ı̂n cazul cerinţei 2).
183
CAPITOLUL 15. ONI 2023 15.1. CADOURI 184
# Punctaj Restrictii
1 23 C=1
2 77 C=2
Exemple:
Propusa de: prof. Nicoli Marius, Colegiul Naţional Fraţii Buzeşti, Syncro Soft Craiova
Notăm cu n numărul de cutii primite la şcoală. Pentru a oferi cadouri la un număr maxim de
elevi se vor distribui câte două cutii fiecăruia. Dacă numărul de cutii este impar este necesar să
se păstreze una dintre ele. Pentru a asigura distribuirea unui număr total maxim de bomboane,
cutia păstrată trebuie să fie una cu număr minim de bomboane.
Pentru cerinţa 1. Este necesară determinarea valorii minime din şirul dat şi se afişează
valorile n©2 şi acest minim.
Pentru cerinţa 2. Dacă n este par se vor distribui toate cutiile iar soluţia este maximul din
şirul de sume de câte două elemente consecutive, v 1 v 2, v 3 v 4, ... (am notat cu v şirul
dat la intrare).
Pentru cazul cu n impar apar două situaţii care trebuie analizate.
Dacă valoarea minimă din şir este pe poziţie impară, maximul care poate fi dat unui copil
se poate obţine fie dintre valorile v 1 v 2, v 3 v 4, ... formate ı̂nainte de poziţia apariţiei
minimului fie dintre valorile v n v n 1, v n 2 v n 3 formate după poziţia apariţiei
minimului.
Dacă minimul este pe o poziţie pară (să o notăm ı̂n continuare cu p o poziţie unde se află
minimul), trebuie să mai luâm ı̂n calcul şi valoarea v p 1 v p 1.
Întrucât elementele şirului dat nu sunt distincte, se observă că şi minimul poate apărea de mai
multe ori. Astfel, trebuie realizate cele prezentate mai sus pentru fiecare poziţie unde se găseşte
un element cu valoarea minimă (notăm mai departe cu p o astfel de poziţie).
O abordare care şterge ı̂n mod repetat elementul de pe o poziţie p şi aplică strategia descrisă
pentru cazul cu n par nu se ı̂ncadrează ı̂n timp pe toate testele.
Pentru a obţine un program care rulează mai rapid vom calcula un şir (notat ms) care la
poziţia i curentă memorează cea mai mare sumă a unei valori de forma v 1 v 2, v 3 v 4, ...
cu indici mai mici decât i precum şi un alt şir (notat md) care memorează rezultatele unui calcul
similar din dreapta: la pozit,ia curentă se află maximul sumelor de câte două elemente din perechi
de forma v n v n 1, v n 2 v n 3, cu indici mai mari ca poziţia curentă. Astfel, la
fiecare poziţie p unde se află un element cu valoare minimă este suficient să luăm ı̂n calcul valorile
msp 1, mdp 1 (dacă p este impar), respectiv msp 2, mdp 2 şi v p 1 v p 1
(dacă p este par).
CAPITOLUL 15. ONI 2023 15.1. CADOURI 185
int main ()
{
ifstream fin ("cadouri.in");
ofstream fout("cadouri.out");
fin>>c>>n;
minim = 2000000000;
for (i=1;i<=n;i++)
{
fin>>v[i];
if (v[i] < minim) minim = v[i];
}
for (i=2;i<=n;i+=2)
{
s = v[i] + v[i-1];
ms[i] = max(ms[i-2], s);
}
for (i=n-1;i>=1;i-=2)
{
d = v[i] + v[i+1];
md[i] = max(md[i+2], d);
}
if (c == 1) { fout<<n/2<<" "; }
else
{
if (n%2 == 0) fout<<ms[n]<<" ";
else
{ /// n impar
for (i=1;i<=n;i++)
{
if (v[i] == minim)
{
if (i%2 == 1)
{
/// minim pe pozitie impara
sol = max(sol, ms[i-1]);
sol = max(sol, md[i+1]);
}
else
{
sol = max(sol, v[i-1]+v[i+1]);
sol = max(sol, ms[i-2]);
sol = max(sol, md[i+2]);
}
}
}
fout<<sol<<" ";
}
}
15.2 legos
Problema 2 - Legos 100 de puncte
Un joc de lego are P piese care sunt cuburi identice. Dorel se joacă cu ele pentru a construi
diverse jucării, dar pentru aceasta are nevoie de ajutorul vostru.
Cerinţe
2. Numărul de piese din cel mai ı̂nalt turn care se poate construi. Un turn din piese de lego
Dorel ı̂l construieşte astfel:
La ı̂nceput va face un pătrat pe care ı̂l numeşte parter (sau etajul 0). Peste acesta va pune 4
piese ı̂n colt,uri pe care le numeşte piloni. Apoi, peste piloni, va pune un nou pătrat pe care ı̂l
numeşte etaj 1.
Peste acesta va pune din nou piloni, peste care va pune etajul 2. şi va continua, până la ultimul
etaj.
Peste ultimul etaj nu pune piloni.
Toate etajele construite au acelaşi număr de piese şi au forma de pătrat cu latura de cel puţin 3
piese. Înălţimea unui turn este dată de numărul de etaje. Pilonii nu sunt consideraţietaje, aceştia
fac parte din structura turnului. Dacă se pot construi mai multe turnuri având aceeaşi ı̂nălţime,
atunci Dorel vrea să ştie numărul de piese al turnului cu cele mai multe piese.(Vezi figura 2).
3. Numărul de terenuri de legoball care se pot construi folosind toate piesele de lego. Un teren
de legoball are forma unui dreptunghi ı̂n care fiecare latură este formată din cel puţin 3 piese (ca
ı̂n figura 3).
CAPITOLUL 15. ONI 2023 15.2. LEGOS 187
Date de intrare
Fişierul legos.in conţine două numere naturale nenule C şi P , separate printr-un singur spaţiu
liber, reprezentând cerinţa respectiv numărul de piese de lego pe care le are Dorel.
Date de ieşire
Pentru fiecare din cele 3 cerinţe fişierul legos.out va conţine un singur număr care reprezintă
răspunsul la acea cerint,ă.
1&C&3
1 & P & 1 000 000 000
Pentru cerinţa 2 un turn poate fi format doar din parter, dar nu poate fi format din parter
şi piloni (deoarece ar avea piloni peste ultimul etaj).
# Punctaj Restricţii
1 31 C=1
2 33 C=2
3 36 C=3
Exemple:
Pentru a optimiza această soluţie se face observaţia adiţională că numărul de piese este de
forma 9 13 nrEtaje 1.
Din aceasta se obtine formula generală a numărului de etaje din cel mai ı̂nalt turn şi apoi
formula pentru numărul de piese din cel mai ı̂nalt turn cu etaje de mărime 3 x 3. Se repetă
raţionamentul pentru 4 x 4.
Pentru cerinţa 3 trebuie să numărăm ı̂n câte moduri poate fi scris P ca produs de două
numere cu menţiunea că nici unul dintre numere să nu fie mai mic decât 3.
Optimizarea este similară cu cea pentru verificarea primalităţii unui număr, vom itera până
când d * d depăşeşte P .
Pentru fiecare divizor vom adăuga 2 la răspuns (corespunzător pentru d x Pd şi Pd x d), cu
menţiunea că dacă divizorul ridicat la puterea a doua este P se va adauga doar 1 la răspuns (Pd
= d deci cele două moduri sunt la fel, d x d şi d x d).
int main()
{
FILE* f=fopen("legos.in", "r");
FILE* g=fopen("legos.out", "w");
int c, P, i, ans=0;
if(c==1)
{
for(i=3;i*i<=P;++i);
fprintf(g, "%d\n", (i-1)*(i-1));
}
else if(c==2)
{
if(P<16)
fprintf(g, "%d\n", 9);
else if(P<22)
fprintf(g, "%d\n", 16);
else
fprintf(g, "%d\n", (P-9)/13*13+9);
}
else
{
for(i=3;i*i<P;++i)
if(P%i==0)
ans+=2;
if(i*i==P)
++ans;
fclose(f);
fclose(g);
return 0;
}
15.3 patinaj
Problema 3 - Patinaj 100 de puncte
Clubul Sportiv SEPI are şi o secţie de patinaj artistic. Conducerea clubului şi-a propus să
participe la proba de perechi a următoarei olimpiade şi are de luat unele decizii privind echipele
pe care le poate ı̂nscrie.
Fiecare echipă participantă la olimpiadă trebuie să fie formată dintr-o pereche de patinatori
(o fată şi un băiat) şi un antrenor. În plus, valorile membrilor unei echipe trebuie să fie cât mai
apropiate.
Valoarea unui sportiv şi respectiv a unui antrenor este calculată pe baza rezultatelor obţinute
la competiţiile anterioare. Acestea sunt codificate sub forma unui singur număr cu cel mult 9 cifre.
Fiecare cifră a numărului reprezintă un rezultat anterior, iar suma cifrelor reprezintă val-
oarea sportivului, respectiv antrenorului.
De exemplu, numărul 18305 codifică rezultatele 1, 8, 3, 0, 5, obţinute la ultimele 5 concursuri,
ceea ce corespunde valorii 17 (= 1 + 8 + 3 + 0 + 5).
La olimpiadă fiecare sportiv şi fiecare antrenor poate să facă parte din cel mult o echipă ı̂nscrisă.
În plus, pentru fiecare echipă, dacă notăm cu VM maximul dintre valorile antrenorului, fetei şi
băiatului şi cu Vm minimul dintre valorile antrenorului, fetei şi băiatului, ı̂nscrierea ı̂n concurs este
permisă doar dacă VM Vm & 1.
Cerinţe
Cunoscând numerele care codifică rezultatele antrenorilor, fetelor şi băieţilor, scrieţi un pro-
gram care să determine:
1. Numărul maxim de echipe, NP , pe care le poate ı̂nscrie Clubul Sportiv SEPI la olimpiadă
astfel ı̂ncât acestea să respecte regulile de mai sus.
2. Valoarea maximă, V , a unui antrenor al clubului care poate antrena o pereche de patinatori
(fată, băiat), ce poate fi ı̂nscrisă la olimpiadă conform regulilor de mai sus şi numărul de
variante NV ı̂n care se poate alege o echipă care poate fi pregătită de un antrenor de valoare
V.
Date de intrare
Date de ieşire
Exemple:
Propusa de:
prof. Manz Victor-Claudiu, Colegiul Naţional de Informatică Tudor Vianu, Bucureşti
Prima observaţie importantă este că, deşi codificările rezultatelor anterioare pot fi numere
destul de mari, valorile asociate sunt cuprinse ı̂ntre 0 (suma cifrelor lui 0 este 0) şi 81 (suma
cifrelor lui 999999999 este 81). Prin urmare, putem construi vectorii de frecvenţă nra asociat
valorilor antrenorilor, nrf asociat valorilor fetelor şi nrb asociat valorilor băieţilor.
Pentru cerinţa 1, pentru fiecare i cuprins ı̂ntre 0 şi 81 vom aduna la rezultat numărul
echipelor cu valoarea membrilor i sau i 1.
Pentru i cuprins ı̂ntre 0 şi 80 acest număr este min nrai nrai 1, nrf i nrf i
1, nrbi nrbi 1.
Pentru fiecare i este necesară actualizarea valorilor nrai 1, nrf i 1, nrbi 1, deoarece
atunci când numărăm echipele cu valoarea membrilor i + 1 sau i + 2 trebuie să excludem antrenorii
şi sportivii pe care i-am folosit deja ı̂n echipe luate ı̂n considerare la pasul i.
Pentru echipele cu valoarea tuturor membrilor 81 mai trebuie adunat
min nra81, nrf 81, nrb81.
Pentru cerinţa 2 vom parcurge valorile posibile ale antrenorilor şi vom determina cel mai
mare i cu proprietatea că există cel puţin un antrenor cu valoarea i şi există atât băieţi, cât şi fete
cu valori din mulţimea ri 1, ix sau există atât băieţi, cât şi fete cu valoari din mulţimea ri, i 1x.
CAPITOLUL 15. ONI 2023 15.3. PATINAJ 191
Dacă există un astfel de i, pe care ı̂l notăm cu i0, atunci putem forma echipe cu antrenori
de valoarea i0 luând (ı̂n toate modurile posibile) antrenori cu valoarea i0 şi sportivi cu valori
din mulţimea ri0 1, i0x sau luând antrenori cu valoarea i0 şi sportivi cu valori din mulţimea
ri0, i0 1x.
E nevoie de atenţie pentru a nu număra de două ori echipele ı̂n care toţimembrii au valoarea
exact i0.
int main()
{
ifstream in("patinaj.in");
ofstream out("patinaj.out");
int c, n;
in >> c >> n;
do
{
sc += x % 10;
x /= 10;
}
while (x != 0);
nr_a[sc]++;
}
nr_b[sc]++;
}// for i
do
{
sc += x % 10;
x /= 10;
}
while (x != 0);
nr_f[sc]++;
}// for i
CAPITOLUL 15. ONI 2023 15.3. PATINAJ 192
if (c == 1)
{
int nr = 0;
nr += minim;
in.close();
out.close();
return 0;
}
ONI 2022
16.1 Culori
Problema 1 - Culori 100 de puncte
Pe o foaie a unui caiet de matematică sunt N rânduri de
pătrăţele pe care Andrei le-a numerotat de sus ı̂n jos cu valori
de la 1 la N . Pe fiecare rând, Andrei colorează unul sau mai
multe pătrăţele având la dispoziţie un set de 9 creioane de culori
diferite, culori ce sunt codificate cu valori distincte de la 1 la
9. Pentru fiecare rând al caietului, Andrei stabileşte un număr
de pătrăţele alăturate ce le va colora şi procedează astfel: alege
un creion cu care colorează primul pătrăţel (cel din stânga foii
sale), apoi procedează la fel pentru al doilea pătrăţel şi aşa mai
departe până termină de colorat numărul de pătrăţele stabilit de el pentru rândul respectiv (pot
exista două sau mai multe pătrăţele colorate la fel). Lungimea unui rând este astfel determinată
de numărul tuturor pătrăţelelor colorate de pe acel rând.
Cerinţe
Date de intrare
Date de ieşire
193
CAPITOLUL 16. ONI 2022 16.1. CULORI 194
Exemple:
Propusa de: Prof. Iordaiche Eugenia-Cristiana, Liceul Teoretic ”Grigore Moisil” Timişoara
Cerinţa 1. O soluţie posibilă pentru determinarea lungimii maxime a unui rând ce are pro-
prietatea că oricare două pătrăţele alăturate au culori diferite, constă ı̂n parcurgerea liniară a tu-
turor pătrăţelelor fiecărui rând şi compararea succesivă a culorilor pentru oricare două pătrăţele
alăturate. Actualizăm la fiecare pas Lmax cu lungimea rândului corect identificat, conform
cerinţei.
Kmax este o variabilă de tip contor ı̂n care vom număra toate rândurile de pătrăţele ale
caietului, ce au lungimea egală cu Lmax.
Cerinţa 2. Pentru a determina cel mai mare număr format prin lipirea tuturor cifrelor unui
rând de pătrăţele, putem utiliza un algoritm de compararea lexicografică a două şiruri de cifre,
parcurgându-le element cu element de la dreapta la stânga. Identificăm astfel, cel mai mare număr
natural ce se poate construi cu cifrele unui rând de pătrăţele. Acest număr va fi memorat cifră cu
cifră ı̂ntr-un tablou unidimensional.
CAPITOLUL 16. ONI 2022 16.2. JOC 195
Parcurgem fiecare rând de pătrăţele de la dreapta la stânga, cifră cu cifră şi comparăm din
punct de vedere lexicografic două şiruri de cifre. In momentul ı̂n care găsim un şir de cifre mai mare
din punct de vedere lexicografic, actualizăm datele memorate ı̂n tabloul ce va memora rezultatul
final şi continuăm până ı̂n momentul ı̂n care vom compara toate şirurile de cifre de pe rândurile
caietului.
16.2 Joc
Problema 2 - Joc 100 de puncte
Doi copii vor să joace un joc cu doi pioni şi o tablă formată din N căsuţe numerotate de la 1
la N, aşezate una după cealaltă, pe aceeaşi linie. Jocul are următoarele reguli:
se aşază pionii pe prima căsuţă de pe tablă (fiecare copil are propriul pion);
primul copil este cel care ı̂ncepe jocul;
copiii vin la tabla de joc alternativ;
cel care este la rând face, după regula de mai josuna sau mai multe mutări ı̂nainte să cedeze
locul celuilalt:
– calculează o valoare X ı̂n modul descris mai jos;
– ı̂şi mută pionul ı̂nainte cu X poziţii iar, dacă valoarea X calculată este 6, are dreptul la
calcularea unei alte valori X, deci la ı̂ncă o mutare, necedând ı̂ncă locul celuilalt copil,
iar dacă valoarea X este diferită de 6 cedează locul la tablă;
X se calculează după regula:
– dacă numărul mutării este impar atunci:
X = ((numărul mutării + ((numărul căsuţei pionului + N ) mod 10)) mod 6) + 1
– dacă numărul mutării este par atunci:
X=
((((numărul mutării+1) mod 5)+((numărul căsuţei pionului+N ) mod 10)) mod 6)+1
unde N este numărul căsuţelor tablei de joc, numărul mutării semnifică a câta mutare
este, mod este operaţia prin care se obţine restul ı̂mpărţirii ı̂ntregi a două numere, iar
valoarea rezultată, X, este una dintre cifrele 1, 2, 3, 4, 5 sau 6, cum de altfel se deduce
din formulele de mai sus.
ı̂n urma ı̂naintării, dacă pionul ajunge pe o căsuţă ocupată ı̂n acel moment de celălalt pion, ı̂i
ia locul acestuia, iar pionul care ocupa căsuţa este trimis la căsuţa cu numărul 1 (ı̂ntoarcerea
acestui pion la poziţia 1 nu se contorizează ca mutare);
dacă un pion, după ı̂naintare, ar ajunge ı̂n afara tablei de joc, este aşezat pe căsuţa N
(ultima);
este câştigător copilul care ajunge primul cu pionul la căsuţa N de pe tabla de joc, şi atunci
jocul se ı̂ncheie.
Cerinţe
Date de intrare
Pe prima linie a fişierului joc.in se află două numere naturale, C şi N separate printr-un spaţiu.
Dacă C = 1, atunci se rezolvă doar prima cerinţă, dacă C = 2, atunci se rezolvă doar a doua
cerinţă iar dacă C = 3, atunci se rezolvă doar cea de-a treia cerinţă.
Date de ieşire
Pe parcursul jocului, copii pot ajunge pe căsuţe pe care le-au mai vizitat
Se garantează că numărul căsuţelor ocupate de copii este mai mic decât 100.000
Problema nu urmăreşte găsirea vreunei proprietăţi speciale pentru şirurile de valori calculate
prin formulele date.
Exemple:
joc.in joc.out
1 10 4
2 10 2
3 10 1 4 6 10
Explicaţii
In primul exemplu C = 1 deci se rezolvă prima cerinţă. N = 10 are 4 divizori.
In al doilea exemplu C = 2 deci se rezolvă a doua cerinţă.
CAPITOLUL 16. ONI 2022 16.2. JOC 197
Primul copil este câştigător. Cifrele calculate au fost, ı̂n ordine, 3 5 2 2 6, cifra 2 a apărut de
cele mai multe ori adică de 2 ori.
În al treilea exemplu C=3 deci se rezolvă a treia cerinţă. Primul copil este câştigător, el a
ocupat ı̂n această ordine căsuţele 4 6 10.
Propusa de: Prof. Dabelea Delia, Colegiul Naţional ”Spiru Haret” Târgu Jiu
Cerinţa 1. O soluţie posibilă ar fi descompunerea ı̂n factori primi ai numărului natural N,
numărul divizorilor acestuia fiind egal cu produsul puterilor factorilori primi crescuţi cu o unitate.
Cerinţa 2. Ne putem folosi de un vector de frecvenţă cu doar 7 elemente, indexate de la 0 la
6, ı̂n care, contorizăm fiecare cifră X calculată. După construirea acestuia, valoarea maximă din
el reprezintă numărul maxim de apariţii căutat. Un rezultat corect depinde, evident, de simularea
corectă a jocului.
Cerinţa 3. Pentru gestionarea corectă a mutărilor alternative a pionilor pe tablă, vom folosi
două variabile (să le notăm a pentru primul copil şi b pentru al doilea copil), variabile, care nu vor
avea niciodată valoare identică. Spre exemplu a=1 şi b=0 sau a=0 şi b=1 (1 mută, 0 nu mută)
ı̂n funcţie de copilul care deplasează pionul.
CAPITOLUL 16. ONI 2022 16.3. ROTIRE25 198
Numerele căsuţelor vizitate de pioni ı̂n timpul jocului se păstrează ı̂n doi vectori (un vector
pentru pionul primului copil şi altul pentru pionul celui de-al doilea copil).
Simulăm jocul printr-o structură repetitivă care se ı̂ncheie ı̂n momentul ı̂n care un pion ajunge
pe ultima căsuţă. La fiecare pas ı̂naintăm pionul copilului care este la mutare X căsuţe, păstrăm
numărul noii căsuţe ı̂n vectorul corespunzător şi respectăm celelalte reguli din enunt.
16.3 Rotire25
Problema 3 - Rotire25 100 de puncte
George a primit ca temă la matematică următoarea problemă. Se dă un număr X, asupra
acestui număr se pot face următoarele transformări:
George trebuie să aplice alternativ cele două transformări asupra numărului X. Prima dată
aplică transformarea 1, apoi pe rezultatul obţinut se aplică transformarea 2, apoi pe rezultat se
aplică iar transformarea 1, apoi iar transformarea 2 şi aşa mai departe. George trebuie să aplice
asupra numărului X exact K transformări, ı̂n ordinea descrisă mai sus.
Cerinţe
Date de intrare
Pe prima linie a fişierului de intrare rotire25.in se află trei numere separate prin câte un
spaţiu C, X şi K. Dacă C = 1 se va rezolva doar prima cerinţă, iar dacă C = 2 se va rezolva doar
a doua cerinţă.
Date de ieşire
Exemple:
Propusa de: stud. Banu Denis Andrei - Facultatea de Informatică, Universitatea Alexandru
Ioan Cuza, Iaşi
Cerinţa 1.
Subtask 1 - 7 puncte. Când numărul obţinut ı̂n urma ı̂nmulţirilor este & 10 . Se poate calcula
18
X * X * X * ... * X (de K ori) folosind structura repetitivă for, iar rezultatul poate să fie reţinut
ı̂ntr-o variabilă de tipul long long. Se ia ultima cifră a acestui rezultat şi se ı̂nmulţeşte cu prima
cifră a lui X.
Subtask 2 - 11 puncte. Când K 100.000. Trebuie să observăm că atunci când ı̂nmulţim două
numere, ultima cifră a rezultatului este dată de ı̂nmulţirea ultimei cifre din primul număr cu
ultima cifră din al doilea număr. Este suficient să reţinem ultima cifră a rezultatului după fiecare
ı̂nmulţire. Astfel rezultatul va rămâne mic şi va putea fi stocat ı̂ntr-o variabilă de tip int. Putem
folosi din nou structura repetitivă for, iar la final ı̂nmulţim rezultutatul cu prima cifră a lui X.
Toată cerinţa 1 - 29 de puncte. Când K & 10 . De data aceasta nu mai putem sa iterăm de
9
K ori deoarece ar dura prea mult. Trebuie sa observăm că ı̂nmulţirea unei cifre cu ea ı̂nsăşi de K
ori are o anumită periodicitate astfel:
0, 1, 5 şi 6 - au perioada 1. De oricâte ori am ı̂nmulţi una dintre aceste cifre cu ea, rezultatul
va avea ultima cifră egală cu aceasta.
4 şi 9 - au perioada 2.
2, 3, 7 şi 8 - au perioada 4.
Ca urmare, dacă X are ultima cifră 0, 1, 5, 6 rezultatul va fi tot acea cifră indiferent de valoarea
lui K . Dacă ultima cifră este 4 sau 9, dacă K este impar rezultatul este acea cifră adică 4 respectiv
9, dacă este par rezultatul este ultima cifră ı̂nmulţită o dată cu ea, adică 4*4 = 16 6 respectiv
9 * 9 = 81 1.
Cerinţa 2.
CAPITOLUL 16. ONI 2022 16.3. ROTIRE25 200
Subtask 1 - 39 de puncte. Când K & 100.000. Putem simula transformările şi la final afişăm
rezultatul.
Toată cerinţa 2 - 71 de puncte. Când K & 100.000. Trebuie să observăm că după ce am
făcut primele 2, 3 transformări, şirul rezultat ı̂n urma aplicării transformărilor este periodic. De
exemplu, pentru X = 13:
Întotdeauna perioada va fi 2. Putem să facem simularea ı̂ntr-un mod asemănător cu subtaskul
1 şi să reţinem numărul de la transformarea curentă şi numărul din urmă cu două transformări. În
momentul ı̂n care numărul curent ajunge egal cu numărul din urmă cu două transformări, atunci
am găsit numerele din perioadă. Dacă K are aceeaşi paritate cu pasul curent, afişăm numărul
curet, dacă nu, mai facem o transformare şi afişăm numărul obţinut ı̂n urma acestei transformări.
Obs. Pentru a scăpa de cazurile particulare, atunci când K este mic, se poate face simulare
exact ca la subtaskul 1.
ONI 2021
17.1 ktlon
Problema 1 - ktlon 100 de puncte
Doua echipe, F şi R, formate din n jucători fecare, au participat ı̂n cadrul noii ediţii ktlon la
k probe.
După fecare probă s-au ı̂nregistrat ı̂n registrul ktlon 2 n valori: primele n reprezintă numărul
de puncte câştigate ı̂n cadrul probei de jucatorii echipei F şi urmu atoarele n reprezintă numărul
de puncte câştigate ı̂n cadrul probei de jucatorii echipei R.
Pentru ca o echipă să câştige o probă este necesar ca cel puţin unul din jucătorii săi să obţină un
număr de puncte strict mai mare decât fecare din punctajele obţinute de către jucătorii celeilalte
echipe.
Echipa câştigătoare a probei primeşte un număr de stele. Pentru a stabili numărul de stele
primite, mai ı̂ntâi se determină numărul M de jucători care au obţinut un număr de puncte
strict mai mare decât fiecare din punctajele obţinute de jucătorii celeilalte echipe. Apoi echipa
câştigătoare primeşte un număr de stele egal cu diferenţa dintre suma celor mai mari M punctaje
obţinute de jucătorii echipei câştigătoare şi suma celor mai mari M punctaje obţinute de jucătorii
celeilalte echipe.
De exemplu, dacă jucătorii celor două echipe au obţinut punctajele (8; 5; 8; 3; 9; 7) şi (5; 7;
5; 4; 5; 1), atunci M 3 deoarece trei punctaje ale jucatorilor echipei F (8, 8, 9) sunt mai mari
decât toate punctajele obţinute de jucătorii echipei R.
Echipa F câştigă proba şi primeşte 8 stele = (9 + 8 + 8) - (7 + 5 + 5).
Dacă niciun jucător al niciunei echipe nu obţine un număr de puncte strict mai mare decât
toate punctajele obţinute de jucătorii celeilalte echipe, proba se ı̂ncheie cu remiza şi nicio echipă
nu primeşte nicio stea (M 0).
Competiţia este câştigată de echipa care acumulează un număr maxim de stele la finalul tuturor
probelor.
Cerinţe
Cunoscând n - numărul de jucători din fiecare echipa, k - numărul de probe şi pentru fiecare
probă punctajele obţinute de cei 2 n jucători ai celor două echipe, determinaţi:
1. numărul de probe câştigate de echipa R;
2. numărul de stele obţinut de echipa câştigătoare.
Date de intrare
Fişierul de intrare ktlon.in conţine pe prima linie un număr C reprezentând cerinţa care
trebuie să fie rezolvata (1 sau 2). Pe a doua linie se află două numere naturale n şi k, care
reprezintă numărul de jucători ai fiecărei echipe, respectiv numărul de probe, iar pe fiecare din
următoarele k linii, câte 2 n numere naturale: primele n reprezintă numărul de puncte câştigate
ı̂n cadrul probei curente de jucătorii echipei F şi următoarele n reprezintă numărul de puncte
câştigate ı̂n cadrul probei curente de jucătorii echipei R.
Numerele de pe aceeaşi linie sunt separate prin câte un spaţiu.
Date de ieşire
201
CAPITOLUL 17. ONI 2021 17.1. KTLON 202
a 1 & C & 2.
a 1 & n & 10 000.
a 1 & kle50.
a Punctajele obţinute de concurenţi sunt numere naturale cuprinse ı̂ntre 0 şi 200 000 inclusiv.
a Pentru teste valorând 35 de puncte cerinţa este 1.
a Pentru teste valorând 30 de puncte cerinţa este 2 şi se garanteaza ca 0leM le1 pentru toate
probele aceluiaşi test.
a Pentru teste valorând 35 de puncte cerinţa este 2 şi se garanteaza ca 0 & M & 5 pentru toate
probele aceluiaşi test.
Exemple:
Pentru rezolvarea cerinţ ei 2, o abordare posibilă este următoarea: pentru fiecare din cele k
probe, atât pentru echipa F , cât şi pentru echipa R, se determină cele mai mari cinci punctaje
obţinute de jucătorii echipei, dacă n ' 5, sau primele n punctaje ı̂n caz contrar, ı̂n ordine de-
screscătoare. Cât timp primele cel mult cinci punctaje maxime corespunzătoare unei echipei sunt
strict mai mari decât punctajul maxim obţinut de jucătorii celeilalte echipe se adună la numărul
de stele corespunzător acesteia numărul de stele obţinut la proba curentă, conform enunţului
problemei. Se afişează la final numărul maxim de stele obţinut de o echipă.
17.2 iepuras
Problema 2 - iepuras 100 de puncte
Pentru că ı̂i plac cifrele, Skippie, iepuraşul norocos a stabilit cum se obţine cifra de control a
unui număr: se efectuează suma cifrelor sale, apoi suma cifrelor acestei sume, până când suma
obţinută este un număr format dintr-o singură cifră. Această ultimă cifră, spune Skippie, poartă
numele de cifră de control.
Skippie, a ascuns ı̂n padure n oua roşii. Pe fiecare ou a pictat câte un număr natural nenul.
Iar acum se ı̂ntreabă care este suma dintre cel mai mare ş i cel mai mic număr natural care se pot
forma din toate cifrele distincte folosite ı̂n scrierea numărului pictat.
În pluş, pentru ca lui Skippie ı̂i plac problemele complicate, pentru fecare numar pictat pe
câte un ou, el ar vrea să afle şi de câte ori apare cifra de control a numarului ı̂n scrierea tuturor
numerelor naturale mai mici sau egale decât numărul pictat.
Cerinţe
1. Pentru fecare dintre cele n numere pictate de Skippie, aflaţi suma dintre cel mai mare şi cel
mai mic număr natural care se pot forma din toate cifrele distincte folosite ı̂n scrierea numărului
pictat.
2. Pentru fiecare dintre cele n numere pictate de Skippie, aflaţi de câte ori apare cifra de control
a numărului pictat ı̂n scrierea tuturor numerelor naturale mai mici sau egale decât numărul pictat.
Date de intrare
Fişierul de intrare iepuras.in conţine un numar natural C. Acesta poate avea valorile 1 sau
2 ş i reprezintă cerinţa problemei. Cea de-a doua linie a fşierului de intrare conţine un număr
natural n reprezentând numărul de oua roşii pictate de Skippie. Fiecare dintre următoarele n
linii ale fişierului de intrare conţine câte un număr natural nenul reprezentând numerele pictate
de iepuraş pe cele n oua roşii.
Date de ieşire
Fişierul de ieşire iepuras.out va conţine n numere ı̂ntregi, fecare pe o linie separată. În ordinea
apariţiei numerelor pictate de iepuraş ı̂n fişierul de intrare, se afişează răspunsurile la cerinţa C.
Exemple:
CAPITOLUL 17. ONI 2021 17.2. IEPURAS 204
Propunator: prof. Georgeta Iulia Balacea - Colegiul Naţional ”Vasile Alecsandri” Galaţi
Pentru rezolvarea problemei se utilizeaza tipuri de date simple: ı̂ntregi şi un vector de frecvenţă.
În plus se utilizează elemente de matematică din programa şcolară a clasei a V-a. (Operaţii cu
numere naturale, scrierea ı̂n baza 10 a unui număr natural) şi structuri elementare de control
(structura alternativă şi structura repetitivă).
Cerinţa 1
Se descompune ı̂n cifre fiecare număr N dintre cele n numere citite şi se reţine numărul de
apariţii al cifrelor lui N ı̂ntr-un vector cif 10 (cu cel mult 10 elemente).
Pentru determinarea numărului maxim (Nmax ) care se poate obţine din cifrele distincte ale
numărului N se parcurge vectorul de frecvenţă, de la poziţia 9 către poziţia 0. Dacă cifra i apare
ı̂n scrierea zecimală a numărului N (cif i j 0) atunci Nmax Nmax 10 i.
Pentru determinarea numărului minim (Nmin ) care se poate obţine din cifrele distincte ale
numu arului N se parcurge vectorul de frecvenţă, de la poziţia 1 către poziţia 9 şi se caută prima
valoare nenulă. Fie aceasta j. Atunci Nmin j şi se marchează faptul că s-a folosit cifra j,
atribuind lui cif j valoarea 0. Se parcurge apoi vectorul de frecvenţă de la 0 către 9. Dacă cifra
i apare ı̂n scrierea zecimală a numărului N (cif i j 0) atunci Nmin Nmin 10 i.
Se afişează suma dintre cele două numere obţinute, Nmax şi Nmin .
CAPITOLUL 17. ONI 2021 17.2. IEPURAS 205
Pentru fiecare număr N , dintre cele n numere citite, se iniţializează vectorul de frecvenţă cif
cu 0.
Cerinţa 2
Pentru a putea rezolva cerinţa a doua, mai ı̂ntâi vom analiza câteva cazuri particulare şi vom
ı̂ncerca să răspundem la câteva ı̂ntrebari:
(1) câte numere mai mici decât 243 au cifra 5 pe poziţia zecilor?
50 51 52 53 54 55 56 57 58 59
150 151 152 153 154 155 156 157 158 159
Raspuns: 20
(2) câte numere mai mici decât 253 au cifra 5 pe poziţia zecilor?
50 51 52 53 54 55 56 57 58 59
150 151 152 153 154 155 156 157 158 159
250 251 252 253
Raspuns: 24
(3) câte numere mai mici decât 263 au cifra 5 pe poziţia zecilor?
50 51 52 53 54 55 56 57 58 59
150 151 152 153 154 155 156 157 158 159
250 251 252 253 254 255 256 257 258 259
Raspuns: 30
Analizând cu atenţie aceste trei exemple, ne dăm seama că se disting trei cazuri. Pentru fiecare
dintre aceste cazuri putem deduce câte o regulă generală prin care să calculăm răspunsurile:
Fie:
a s = cifra sutelor
a z = cifra zecilor
a u = cifra unitaţilor
Atunci:
a dacă z $ 5, atunci răspunsul este s 10
a dacă z 5, atunci răspunsul este s 10 u 1
a dacă z % 5, atunci răspunsul este s 1 10
Dacă vom analiza exemple cu mai multe cifre, putem generaliza următoarele reguli:
Fie un numar care scris pe cifre arată astfel: ss...sszuu...uu.
Fie CC cifra sa de control.
Fie nrU numărul de cifre notate cu u ı̂n scrierea de mai sus.
Atunci:
a dacă z $ CC, atunci numărul de numere mai mici sau egale cu ss...sszuu...uu care conţin
nrU
cifra CC pe poziţia cifrei notată cu z este ss...ss 10
a dacă z CC, atunci numărul de numere mai mici sau egale cu ss...sszuu...uu care conţin
nrU
cifra CC pe poziţia cifrei notată cu z este ss...ss 10 uu...uu 1
a dacă z % CC, atunci numărul de numere mai mici sau egale cu ss...sszuu...uu care conţin
nrU
cifra CC pe poziţia cifrei notată cu z este ss...ss 1 10
Calculând ı̂n prealabil cifra de control, iterând prin cifrele numarului şi cu ajutorul acestor
reguli, putem calcula răspunsul cerinţei a doua.
Cerinţa 2 (explicaţie alternativa)
Cifra de control a unui număr natural nenul este egală cu 9 dacă numărul este multiplu de 9
sau este egală cu restul ı̂mparţirii la 9 a numărului dat, dacă restul este nenul.
Soluţia problemei se bazează pe scrierea ı̂n baza 10 a unui număr natural.
Pentru fecare dintre cele n numere scrise de iepuraş pe ouă se determină cifra de control.
Numărul de apariţii al cifrei de control ı̂n scrierea tuturor numerelor naturale nenule mai mici
sau egale cu un număr natural N se determină analizând scrierea ı̂n baza 10 a numarului.
Fie n0 cifra unitaţilor, n1 este cifra zecilor, ... şi nk cifra cea mai semnifcativa a numărului
natural N . Atunci
2 k
N n0 n1 10 n2 10 ... nk 10 .
Notăm cu c cifra de control a numărului natural nenul N .
Soluţia care analizează apariţia cifrei de control c ı̂n scrierea tuturor numerelor naturale nenule
mai mici sau egale cu numărul N descompunând ı̂n cifre toate numerele din interval rezolvă sufcient
de rapid grupa de teste ı̂n valoare de 24 de puncte.
Pentru punctaj maxim ı̂nsă, va trebui să găsim un alt mod de a calcula răspunsul.
Se calculează de câte ori apare cifra c pe poziţia unitaţilor ı̂n toate numerele naturale mai mici
sau egale cu N .
CAPITOLUL 17. ONI 2021 17.3. TAIERI 206
Astfel, cifra c apare pe poziţia unitaţilor de N ©10 ori. Dacă n0 (cifra unităţilor numărului N )
este mai mare sau egal cu c atunci numărul de apariţii al cifrei de control se măreşte cu 1.
Se calculează apoi de câte ori apare cifra c pe poziţia zecilor ı̂n toate numerele naturale mai
mici sau egale cu N .
Astfel, cifra c apare pe poziţia zecilor de N ©100 ori. Dacă n1 (cifra zecilor numărului N ) este
mai mare decât c atunci numărul de apariţii al cifrei de control se măreşte cu 10, ı̂n schimb, dacă
n1 este egală cu cifra de control atunci numărul de apariţii al cifrei de control se măreşte cu n0 1.
În general, se calculează de câte ori apare cifra c pe poziţia p ı̂n toate numerele naturale mai
mici sau egale cu N .
p1
Astfel, cifra c apare pe poziţia p de N ©10 ori. Dacă np este mai mare decât c atunci
p
numărul de apariţii al cifrei de control se măreşte cu 10 , ı̂n schimb, dacă np este egală cu c atunci
p
numărul de apariţii al cifrei de control se măreşte cu N %10 1.
De exemplu, pentru numarul 123, cifra de control este 6.
Cifra 6 apare pe poziţia unitaţilor de 12 ori, pe poziţia zecilor de 1 10 10 ori şi niciodata
pe poziţia sutelor. În total, ı̂n scrierea zecimală a numerelor 1, 2, 3, 4, 5, 6, 7, ... 60, 61, 62, ...
123 cifra 6 apare de 22 de ori.
17.3 taieri
Problema 3 - taieri 100 de puncte
Avem la dispoziţie n bare metalice cu aceeaşi grosime, dar lungimi diferite. Putem alege
oricare bară şi să o tăiem, obţinând alte două bare, de lungimi mai mici. Ne dorim ca, folosind
doar această operaţie (deci fără să le putem suda), să obţinem un număr de bare de anumite
lungimi date. Mai exact, dându-se un set de 4 numere a, b, c, d, trebuie să decidem dacă putem
obţine a bare de lungime 1, b bare de lungime 2, c bare de lungime 4 şi d bare de lungime 8.
Odată aplicată o tăiere de lungime L asupra unei bare, restul poate fi ı̂n continuare folosit pentru
a tăia alte bare de oricare dintre lungimile dorite.
Cerinţe
Cunoscând n - numărul de bare metalice şi lungimile celor n bare metalice avute la dispoziţie,
pentru fiecare din seturile de 4 numere a b c d date, determinaţi dacă, pornind de la cele n lungimi
date, se pot obţine barele de lungimile dorite.
Date de intrare
Pe prima linie a fiş ierului de intrare taieri.in se află numărul natural n. Pe linia a doua se află
cele n numere naturale ce reprezintă lungimile barelor iniţiale. Pe linia a treia se află un număr
natural m ce reprezintă numărul de seturi de 4 numere. Pe fiecare din următoarele m linii se află
câte patru numere naturale a b c d cu semnificaţia de mai sus.
Numerele de pe aceeaşi linie sunt separate prin câte un spaţiu.
Date de ieşire
Fişierul de ieşire taieri.out va conţine m valori 0 şi 1, separate prin câte un spaţiu. Pentru
fiecare set de 4 numere, ı̂n ordinea apariţiei lor ı̂n fişierul de intrare, se scrie ı̂n fişierul de ieşire
valoarea 1, dacă se poate obţine numărul dorit de bare pentru toate cele 4 lungimi din setul
corespunzător, respectiv 0 ı̂n caz contrar.
a Lungimile barelor sunt numere naturale nenule cel mult egale cu 10 000 000.
a 0 & a, b, c, d & 10 000 000.
a Pentru teste ı̂n valoare de 16 puncte 1 & n & 1 000, 1 & m & 1 000, iar pentru toate seturile
dintr-un test avem b 0, c 0 şi d 0.
a Pentru alte teste ı̂n valoare de 28 puncte 1 & n & 1 000 şi 1 & m & 1 000.
a Pentru alte teste ı̂n valoare de 56 de puncte 1 & n & 100 000 şi 1 & m & 100 000.
Exemple:
Numărul maxim de bare de lungime 8 (notat N r8) care se pot obţine (adunăm la o
variabilă valorila V i©8 pentru toate elementele din vector); Înlocuim apoi fiecare valoare
cu V i%8.
Pe noul vector, reluăm procedeul pentru lungimile 4, 2, 1, calcuând astfel 4 valori.
CAPITOLUL 17. ONI 2021 17.3. TAIERI 208
Apoi, pentru un set de 4 lungimi date a, b, c, d este suficient sa consultăm cele 4 valori calculate
anterior (N r1, N r2, N r4, N r8). Dacă d % N r8, nu avem soluţie. În caz contar adunăm
la N r4 valoarea (N r8 d 2 (surplusul de lungime 8 permite obţinerea de număr dublu de
bare de lungime 4). Acelaşi raţionament ı̂l aplicăm apoi pentru 4, 2, 1, ı̂n această ordine.
Această soluţie permite traversarea vectorului iniţial de un număr constant de valori pentru a
obţine informaţiile N r, iar ı̂n etapa a doua, pentru fiecare set a, b, c, d este sufcient să interogăm
doar cele 4 valori N r.
209
Capitolul 19
ONI 2019
19.1 Copii
Problema 1 - Copii 100 de puncte
Iliuţă şi Pandele au ı̂nvăţat la şcoală operaţii aritmetice cu numere naturale. Astfel cei doi
fraţi exersează operaţiile folosindu-se de o tablă. Iliuţă spune un număr natural X, iar Pandele
scrie pe tablă rezultatul ı̂nmulţirii tututor numerelor naturale de la 1 la X. Glumeţ, Iliuţă şterge
cifrele egale cu 0 de la finalul numărului scris de Pandele.
Ca să ı̂l ierte, Pandele spune şi el un număr natural Y şi ı̂i cere lui Iliuţă să determine un
număr natural Z care este cel mai mare divizor al lui Y având un număr impar de divizori.
Cerinţe
Cunoscându-se numerele spuse de copii, scrieţi un program care rezolvă următoarele cerinţe:
1) afişează ultimele K cifre ale produsului calculat de Pandele, după ştergerea cifrelor egale cu
0 de la finalul acestuia;
2) afişează numărul Z cu semnificaţia de mai sus şi numărul de divizori ai acestuia.
Date de intrare
Fişierul copii.in conţine pe prima linie numărul C, care reprezintă numărul cerinţei şi poate
avea doar valorile 1 sau 2. Pentru prima cerinţă fişierul conţine pe a doua linie numărul X, iar pe
cea de a treia linie numărul K. Pentru a doua cerinţă fişierul conţine pe a doua linie numărul Y.
Date de ieşire
Pentru cerinţa 1), pe prima linie a fişierului copii.out se vor afişa cele K cifre cerute, fără
spaţii, ı̂n ordine de la stânga la dreapta.
Pentru cerinţa 2), pe prima linie se vor afişa, ı̂n această ordine, numărul Z determinat şi
numărul de divizori ai acestuia. Numerele vor fi separate printr-un spaţiu.
1 & X & 10
6
a
1 & Y & 10
12
a
a 1&K&9
a Numărul rămas după ştergerea zerourilor de la finalul produsului are cel puţin K cifre;
a Pentru rezolvarea primei cerinţe se acordă 40 de puncte;
a Pentru rezolvarea celei de a doua cerinţe se acordă 60 de puncte.
Exemple
210
CAPITOLUL 19. ONI 2019 19.1. COPII 211
int main ()
{
ifstream cin ("copii.in");
ofstream cout ("copii.out");
int c, k;
long long x;
cin >> c >> x;
assert (c == 1 || c == 2);
if (c == 1)
{
cin >> k;
int m = 1;
for (int i = 1; i <= k; ++i)
CAPITOLUL 19. ONI 2019 19.1. COPII 212
m *= 10;
while (ci % 5 == 0)
{
++nr5;
ci /= 5;
}
}
nr2 = nr5;
while (x % i == 0)
{
x /= i;
++expp[p];
}
}
i += 1LL;
}
if (x > 1LL)
{
prim[++p] = x;
expp[p] = 1;
}
CAPITOLUL 19. ONI 2019 19.1. COPII 213
cout << divizor << " " << numar << ’\n’;
}
return 0;
}
ifstream fin("copii.in");
ofstream fout("copii.out");
int C; // nr cerinta
void rezolva1()
{
void rezolva2()
{
int main()
{
fin>>C;
cout<<"C = "<<C<<"\n";
return 0;
}
ifstream fin("copii.in");
ofstream fout("copii.out");
int C; // nr cerinta
int X, K; // pentru C=1 ... (K cifre) <=9 ...10ˆ9 ... incape pe int ...
long long Y; // pentru C=2 ... atentie ... Y <= 10ˆ12 ... !!!
int k10; // k10 = 10ˆk ... pentru ultimele k cifre (fac modulo k10)
long long p1x; // produs de la 1 la x ... pastrez numai (p1x % k10) ...X*10ˆk =
// = 10ˆ6*10ˆ9 = 10ˆ15 = long long ... !!!
void rezolva1()
{
fin>>X;
fin>>K;
cout<<"X = "<<X<<"\n"; // atentie la X=1 sau X=2 sau X=3 ... !!!
cout<<"K = "<<K<<"\n";
k10=1;
for(int i=1; i<=K; i++) k10=k10*10; // k10 *= 10;
cout<<"\n k10 = "<<k10<<"\n\n";
nr5=0;
for(int i=1; i<=X; i++) // pentru 1*2*3*...*X (nu prea are rost de la 1 ...)
{
int ci=i; // copia lui i ... ca sa nu il stric pe i ...
void rezolva2()
{
CAPITOLUL 19. ONI 2019 19.1. COPII 215
int main()
{
fin>>C;
cout<<"C = "<<C<<"\n";
return 0;
}
ifstream fin("copii.in");
ofstream fout("copii.out");
int C; // nr cerinta
int X, K; // pentru C=1 ... (K cifre) <=9 ...10ˆ9 ... incape pe int ...
long long Y; // pentru C=2 ... atentie ... Y <= 10ˆ12 ... !!!
long long Z; // Z divizor <= Y <= 10ˆ12 ... ==> long long
long long ndivz;// nr divizori ai lui Z
int k10; // k10 = 10ˆk ... pentru ultimele k cifre (fac modulo k10)
long long p1x; // produs de la 1 la x ... pastrez numai (p1x % k10) ...X*10ˆk =
// = 10ˆ6*10ˆ9 = 10ˆ15 = long long ... !!!
void rezolva1()
{
fin>>X;
fin>>K;
cout<<"X = "<<X<<"\n"; // atentie la X=1 sau X=2 sau X=3 ... !!!
cout<<"K = "<<K<<"\n";
k10=1;
for(int i=1; i<=K; i++) k10=k10*10; // k10 *= 10;
cout<<"\n k10 = "<<k10<<"\n\n";
nr5=0;
for(int i=1; i<=X; i++) // pentru 1*2*3*...*X (nu prea are rost de la 1 ... dar...)
{
int ci=i; // copia lui i ... ca sa nu il stric pe i ...
ci=ci/2; // scot un 2
nr2--;
}
void rezolva2()
{
fin>>Y;
//Y=1LL*2*2*3*3*3*3*5*7*7*7;
cout<<"Y = "<<Y<<"\n\n"; // atentie la Y=1 sau Y=2 sau Y=3 ... !!!
//getchar();
int fp; // factor prim de incercat: 2, 3, 5, 7, 9(?), 11, 13, 15(?), 17, 19,
21(?), ...
int nfp; // de cate ori apare factorul prim fp
long long cy=Y; // copia lui Y ... atentie la ... long long ... !!!
fp=2;
nfp=0;
while((cy > 0) && (cy%fp == 0)) // 2-urile ...
{
nfp++;
cy=cy/fp;
//getchar();
}
if(nfp>0)
cout<<"fp = "<<fp<<" nfp = "<<nfp<<"\n";
//getchar();
fp=3;
while(fp*fp <= cy)
{
// fp=2; // scapa in bucla infinita ... !!!
nfp=0;
ndivz=ndivz*(1LL+nfp);
if(nfp>0)
cout<<"fp = "<<fp<<" nfp = "<<nfp<<" Z = "<<Z<<
" ndivz = "<<ndivz<<" cy = "<<cy<<"\n\n";
fp=fp+2;
//getchar();
}
cout<<"\n --- cy = "<<cy<<" --- \n\n"; // ce a ramas ...
cout<<Z<<’ ’<<ndivz<<’\n’;
}
int main()
{
fin>>C;
cout<<"C = "<<C<<"\n";
return 0;
}
19.2 Numere
Problema 2 - Numere 100 de puncte
Într-o zi, Ioana a scris toate numerele naturale de N cifre fiecare ı̂ndeplinind, simultan, condiţiile:
- numărul format din primele două cifre este pătrat perfect;
- a treia cifră este obligatoriu număr prim;
- nu conţine două cifre pare alăturate şi nici două cifre impare alăturate.
De exemplu, numerele de trei cifre, scrise de Ioana, sunt:
163, 165, 167, 252, 363, 365, 367, 492, 812.
Cerinţe
Date de intrare
CAPITOLUL 19. ONI 2019 19.2. NUMERE 218
Fişierul de intrare numere.in conţine pe prima linie un număr natural C. Numărul C poate
avea doar valorile 1 sau 2. Pe a doua linie se află, ı̂n cazul primei cerinţe, numărul N, iar ı̂n cazul
celei de-a doua cerinţe, numărul X.
Date de ieşire
Dacă valoarea lui C este 1, se va rezolva doar cerinţa 1). În acest caz, fişierul de ieşire
numere.out va conţine pe prima linie un număr natural, reprezentând rezultatul determinat
pentru prima cerinţă.
Dacă valoarea lui C este 2, se va rezolva doar cerinţa 2). În acest caz, fişierul de ieşire
numere.out va conţine pe prima linie un număr natural, reprezentând rezultatul determinat
pentru cea de a doua cerinţă.
Restricţii şi precizări
a 3 & N & 29
a 100 & X & 20 000 000
a Pentru rezolvarea primei cerinţe se acordă 30 de puncte, iar pentru rezolvarea celei de a doua
cerinţe se acordă 70 de puncte.
Exemple
numere.in numere.out Explicaţii
1 45 Numerele de patru cifre, scrise de Ioana, sunt:
4 1630, 1632, 1634, 1636, 1638, 1650, 1652, 1654, 1656,
1658, 1670, 1672, 1674, 1676, 1678, 2521, 2523, 2525,
2527, 2529, 3630, 3632, 3634, 3636, 3638, 3650, 3652,
3654, 3656, 3658, 3670, 3672, 3674, 3676, 3678, 4921,
4923, 4925, 4927, 4929, 8121, 8123, 8125, 8127, 8129.
2 167 Cel mai apropiat număr de 200 este 167 (numerele de
200 trei cifre, scrise de Ioana, sunt: 163, 165, 167, 252, 363,
365, 367, 492, 812).
Prof. Ana-Maria Arişanu, Colegiul Naţional Mircea cel Bătrân, Rm. Vâlcea
a) Numerele ce respectă condiţiile din enunţ pot ı̂ncepe cu 16, 25, 36, 49 sau 81
Caz 1. Dacă ı̂ncep cu 16 sau 36 a treia cifra poate fi 3, 5 sau7.
Caz 2. Dacă ı̂ncep cu 25, 49 sau 81 a treia cifra poate fi doar 2
Începând cu a patra cifra avem câte 5 posibilităţi, respectiv 0, 2, 4, 6 sau 8 (pentru cazul 1) şi
1, 3, 5, 7 sau 9 (pentru cazul 2)
Numărul de numere de N cifre care respectă condiţiile din enunţ este:
2 3 5 n 3 3 5 n 3 9 5 n 3
b) Fie k numărul de cifre ale numărului X.
Construim xmin ca fiind cel mai mic număr de k cifre ce respectă condiţiile din enunţ %
xmin = 163010101 ...
Construim xmax ca fiind cel mai mare număr de k cifre ce respectă condiţiile din enunţ %
xmax = 812989898...
Determinăm cel mai mic număr, mai mare decât x ce respectă condiţiile din enunţ (dacă
există). Acest număr nu poate fi mai mare decât xmax.
Determinăm cel mai mare număr, mai mic decât x ce respectă condiţiile din enunţ (dacă
există). Acest număr nu poate fi mai mic decât xmin.
Dintre cele două numere determinate se afişează cel mai aproape de X.
CAPITOLUL 19. ONI 2019 19.2. NUMERE 219
ifstream f("numere.in");
ofstream g ("numere.out");
int main()
{
int p,n,x,dif1=20000000,dif2=20000000,y,xx;
long long xmin,xmax,i, nr1,nr2;
unsigned long long nr;
f>>p;
if (p==1)
{
f>>n;
nr=9;
for (i=1; i<=n-3; i++)
nr=nr*5;
g<<nr<<’\n’;
}
else
{
f>>x;
y=x;
xmin=163;
xmax=812;
i=3;
while (y>999)
{
i++;
if (i%2==0)
{
xmin=xmin*10;
xmax=xmax*10+9;
}
else
{
xmin=xmin*10+1;
xmax=xmax*10+8;
}
y=y/10;
}
if (x<xmin) g<<xmin;
else
if (x>xmax) g<<xmax;
else
{
for (xx=x-1; xx>=xmin; xx--)
{
int v[11],k=0,n2,i,xxx=xx, bun=1;
while (xxx>99)
{
k++;
v[k]=xxx%10;
xxx=xxx/10;
}
if (xxx!=16 && xxx!=25 && xxx!=36 && xxx!=49 && xxx!=81) bun=0;
else if ((xxx==16|| xxx==36)&& (v[k]!=3 && v[k]!=5 && v[k]!=7))
bun=0;
else if ((xxx==25 || xxx==49 ||xxx==81) && v[k]!=2) bun=0;
else
for (i=k-1; i>=1; i--)
if (v[i]%2==v[i+1]%2) bun=0;
if (bun)
{
CAPITOLUL 19. ONI 2019 19.2. NUMERE 220
nr1=xx;
dif1=x-nr1;
break;
}
}
if (dif1<=dif2)
g<<nr1<<’\n’;
else
g<<nr2<<’\n’;
}
}
}
Atenţie la enunţ: ... ” cel mai apropiat număr de X, diferit de X,” ...
Exemplu pentru 3 cifre:
100 163 165 167 252 363 365 367 492 812 999
Figura 19.1: Numere cu 3 cifre
Dacă X este ı̂n stı̂nga zonei zona16 (de exemplu X 150) atunci rezultatul este 163.
Dacă X este ı̂n dreapta zonei zona81 (de exemplu X 900) atunci rezultatul este 812.
Altfel, X are doi vecini, unul ı̂n stânga şi unul ı̂n dreapta.
Dacă, de exemplu, X 166, cei doi vecini sunt 165 şi 167 din accelaşi grup zona16.
Dacă, de exemplu, X 444, cei doi vecini sunt 367 şi 492 din grupuri diferite dar adiacente.
Mai precis, X 444 este ı̂ntre zonele zona36 şi zona49 iar cei doi vecini sunt: cel mai mare din
zona zona36 şi cel mai mic din zona zona49.
Exemplu pentru 4 cifre:
1000 1630 16.. 1678 252. 3630 36.. 3678 492. 812. 9999
10000 16301 16... 16789 252.. 36301 36... 36789 492.. 812.. 99999
Pentru nc 5 zona
Celelalte zone NU mai sunt precizate ı̂n enunţul problemei dar sunt uşor de intuit! Pentru
nc 6, 7, 8 zonele sunt tot mai depărtate (de 0) şi conţin tot mai multe numere fiecare!
Pentru nc 8 reprezentarea tabelară ne va ajuta să programăm mai uşor!
Pentru 16:
1 2 3 4 5 6 7 8
Pentru 25:
1 2 3 4 5 6 7 8
Pentru 36:
1 2 3 4 5 6 7 8
Pentru 49:
CAPITOLUL 19. ONI 2019 19.2. NUMERE 222
1 2 3 4 5 6 7 8
Pentru 81:
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7
1 2 3 4 5 6 7
3 6 5 4 0 0 0 err!
3 6 5 4 1 0 1
... ... ... ... ... ... ...
3 6 5 8 9 8 9 max365
3 6 7 0 1 0 1 min367
... ... ... ... ... ... ...
1 2 3 4 5 6 7
1 2 3 4 5 6 7
1 2 3 4 5 6 7
1 2 3 4 5 6 7
1 2 3 4 5 6 7
ifstream fin("numere.in");
CAPITOLUL 19. ONI 2019 19.2. NUMERE 225
ofstream fout("numere.out");
int C;
int N;
int X; // 20.000.000 incape pe "int"
int nr3c[9] = { 163, 165, 167, 252, 363, 365, 367, 492, 812 };
long long rez1=9; // unsigned long long ... este mai OK!
void rezolva1()
{
fin>>N;
rez1=9LL;
for(int i=1; i<=min(N-3,28-3); i++)// N=28 este ultimul care este ok
rez1=rez1*5;
// inmultirea rez*5
int t=0; // cifra de transport ... la inmultire
for(i=0; i<=poz; i++)
{
int cifra=v[i]*5+t;
v[i]=cifra%10;
t=cifra/10;
}
if(t>0) { v[i]=t; poz++; }
for(i=poz; i>=0; i--) fout<<v[i];
fout<<’\n’;
}
else
fout<<rez1<<’\n’;
}
void rezolva2()
{
int main()
{
fin>>C;
if(C==1) rezolva1();
if(C==2) rezolva2();
return 0;
}
int nr3c[9] = { 163, 165, 167, 252, 363, 365, 367, 492, 812 };
long long rez1=9; // unsigned long long ... este mai OK!
int rez2, rez2min, rez2max; // solutie pentru Cerinta 2
CAPITOLUL 19. ONI 2019 19.2. NUMERE 226
222
nrcifrex(X);
vcifrex(X);
x123=X;
for(int i=ncx; i>=4; i--) x123=x123/10;
x12=x123/10;
x3=x123%10;
calcpozincorecta();
int x123min=f123min(x123);
int x123max=f123max(x123);
rez2min=rez2max=0;
for(int i=1; i<=ncx; i++)
{
rez2min=rez2min*10+vcifxs[i];
rez2max=rez2max*10+vcifxd[i];
}
fout<<rez2<<’\n’;
}
333
void vcifrex(int x)
{
for(int i=1; i<=ncx; i++)
{
vcifx[ncx-i+1]=x%10;
x=x/10;
}
}
void calcpozincorecta()
{
if(x12 != 16 && x12 != 25 && x12 != 36 && x12 != 49 && x12 != 81)
pozincorecta=2;
else
if(!(x3 == 2 || x3 == 3 || x3 == 5 || x3 == 7) && (x3+x2)%2==1)
pozincorecta=3;
else
{
int i=4;
while((i<=ncx) && (vcifx[i]+vcifx[i-1])%2==1) i++;
pozincorecta=i;
}
}
return c123min;
}
return c123max;
}
int poz=ncx;
while(vcifxd[poz]>=8) // nu pot sa adun 2 (sa rapana paritatea ok!)
poz=poz-1;
vcifxd[poz]=vcifxd[poz]+2;
int poz=ncx;
while(vcifx[poz]<=1) // nu pot sa scad 2 (sa ramana paritatea ok!)
poz=poz-1;
vcifxs[poz]=vcifx[poz]-2;
if(vcifxs[i-1]%2==0) vcifxs[i]=9;
else vcifxs[i]=8;
}
444
void pozincorecta45678()
{
if(vcifx[pozincorecta]>=1) // pot sa scad 1 ... corectez paritatea !!!
{
calcvcifxs();
succesor();
}
else // sigur pot sa adun 1 ... corectez paritatea !!!
{
calcvcifxd();
predecesor();
}
rez2min=rez2max=0;
for(int i=1; i<=ncx; i++)
{
rez2min=rez2min*10+vcifxs[i];
rez2max=rez2max*10+vcifxd[i];
}
rez2=rez2min;
if(rez2max-X < X-rez2min) rez2=rez2max; // mai aproape de X
}
CAPITOLUL 19. ONI 2019 19.2. NUMERE 229
555
ifstream fin("numere.in");
ofstream fout("numere.out");
int C;
int N;
int X; // 20.000.000 incape pe "int"
int nr3c[9] = { 163, 165, 167, 252, 363, 365, 367, 492, 812 };
long long rez1=9; // unsigned long long ... este mai OK!
int rez2, rez2min, rez2max; // solutie pentru Cerinta 2
void rezolva1()
{
fin>>N;
rez1=9LL;
for(int i=1; i<=min(N-3,28-3); i++)// N=28 este ultimul care este ok
rez1=rez1*5;
// inmultirea rez*5
int t=0; // cifra de transport ... la inmultire
for(i=0; i<=poz; i++)
{
int cifra=v[i]*5+t;
v[i]=cifra%10;
t=cifra/10;
}
if(t>0) { v[i]=t; poz++; }
for(i=poz; i>=0; i--) fout<<v[i];
fout<<’\n’;
}
else
fout<<rez1<<’\n’;
}
void nrcifrex(int x)
{
ncx=0;
while(x>0) { ncx++; x=x/10; }
}
CAPITOLUL 19. ONI 2019 19.2. NUMERE 230
void vcifrex(int x)
{
for(int i=1; i<=ncx; i++)
{
vcifx[ncx-i+1]=x%10;
x=x/10;
}
}
int poz=ncx;
while(vcifx[poz]<=1) // nu pot sa scad 2 (sa ramana paritatea ok!)
poz=poz-1;
vcifxs[poz]=vcifx[poz]-2;
int poz=ncx;
while(vcifxd[poz]<=1) // nu pot sa scad 2 (sa ramana paritatea ok!)
poz=poz-1;
vcifxs[poz]=vcifxd[poz]-2;
int poz=ncx;
while(vcifxd[poz]>=8) // nu pot sa adun 2 (sa ramana paritatea ok!)
poz=poz-1;
vcifxd[poz]=vcifxd[poz]+2;
int poz=ncx;
while(vcifxd[poz]>=8) // nu pot sa adun 2 (sa ramana paritatea ok!)
poz=poz-1;
vcifxd[poz]=vcifxd[poz]+2;
}
CAPITOLUL 19. ONI 2019 19.2. NUMERE 231
return c123min;
}
return c123max;
}
void calcpozincorecta()
{
if(x12 != 16 && x12 != 25 && x12 != 36 && x12 != 49 && x12 != 81)
pozincorecta=2;
else
if(!(x3 == 2 || x3 == 3 || x3 == 5 || x3 == 7) && (x3+x2)%2==1)
pozincorecta=3;
else
{
int i=4;
while((i<=ncx) && (vcifx[i]+vcifx[i-1])%2==1) i++;
pozincorecta=i;
}
}
void pozincorecta23() // 163 165 167 252 363 365 367 492 812
{
if(x123<163) { rez2=f123min(163); return;}
if(x123>812) { rez2=f123max(812); return;}
void pozincorecta45678()
{
if(vcifx[pozincorecta]>=1) // pot sa scad 1 ... corectez paritatea !!!
{
calcvcifxs();
succesor();
}
else // pot sa adun 1 ... corectez paritatea !!!
{
calcvcifxd();
predecesor();
}
rez2min=rez2max=0;
for(int i=1; i<=ncx; i++)
{
rez2min=rez2min*10+vcifxs[i];
rez2max=rez2max*10+vcifxd[i];
}
rez2=rez2min;
if(rez2max-X < X-rez2min) rez2=rez2max; // mai aproape de X
}
void rezolva2()
{
fin>>X;
nrcifrex(X);
vcifrex(X);
x123=X;
for(int i=ncx; i>=4; i--) x123=x123/10;
x12=x123/10;
x3=x123%10;
calcpozincorecta();
int x123min=f123min(x123);
int x123max=f123max(x123);
rez2min=rez2max=0;
for(int i=1; i<=ncx; i++)
{
rez2min=rez2min*10+vcifxs[i];
rez2max=rez2max*10+vcifxd[i];
CAPITOLUL 19. ONI 2019 19.3. TRIO 233
fout<<rez2<<’\n’;
}
int main()
{
fin>>C;
if(C==1) rezolva1();
if(C==2) rezolva2();
return 0;
}
19.3 Trio
Problema 3 - Trio 100 de puncte
Trio este un joc ce conţine N piese de aceeaşi formă, aşezate una lângă alta pe o tablă de joc
şi numerotate de la stânga la dreapta cu valori de la 1 la N. Fiecare piesă are marcate pe ea trei
zone, iar ı̂n fiecare dintre ele este scrisă câte o cifră. Se consideră că o piesă pe care sunt scrise ı̂n
ordine, de la stânga la dreapta, cifrele C1,C2 şi C3 are următoarele proprietăţi:
este identică cu o altă piesă, dacă această piesă conţine exact aceleaşi cifre, ı̂n aceeaşi ordine
cu ale ei sau ı̂n ordine inversă. Astfel, piesa C1 C2 C3 este identică cu o altă piesă de
forma C1 C2 C3 şi cu o piesă de forma C3 C2 C1 .
este prietenă cu o altă piesă dacă aceasta conţine exact aceleaşi cifre ca piesa dată,
dar nu neapărat ı̂n aceeaşi ordine. Astfel, piesa C1 C2 C3 este prietenă cu piesele:
C1 C2 C3 , C1 C3 C2 , C2 C1 C3 , C2 C3 C1 , C3 C1 C2
şi C3 C2 C1 . Se observă că două piese identice sunt şi prietene!
Un grup de piese prietene este format din TOATE piesele prietene ı̂ntre ele, aflate pe tabla
de joc.
Cerinţe
1) Alegeţi o piesă de pe tabla de joc, astfel ı̂ncât numărul M al pieselor identice cu ea să fie
cel mai mare posibil şi afişaţi numărul M determinat;
2) Afişaţi numărul grupurilor de piese prietene existente pe tabla de joc;
3) Afişaţi numărul maxim de piese dintr-o secvenţă ce conţine piese aşezate una lângă alta pe
tabla de joc, pentru care prima piesă şi ultima piesă din secvenţă sunt prietene.
Date de intrare
- pe prima linie un număr natural C care reprezintă numărul cerinţei şi poate avea valorile 1,
2 sau 3.
- pe cea de-a doua linie un număr natural N ce reprezintă numărul pieselor de joc;
- pe următoarele N linii, câte trei cifre, despărţite prin câte un spaţiu, ce reprezintă, ı̂n ordine,
cifrele scrise pe câte o piesă de joc. Piesele sunt date ı̂n ordinea numerotării acestora pe tabla de
joc.
Date de ieşire
CAPITOLUL 19. ONI 2019 19.3. TRIO 234
Fişierul trio.out va conţine pe prima linie un singur număr natural ce reprezintă rezultatul
determinat conform fiecărei cerinţe.
Exemple
trio.in trio.out Explicaţii
1 2 .
6
133
459
133
954 Se rezolvă cerinţa 1. Alegând oricare din piesele 1, 3 sau 5 există
331 pe tablă dou piese identice cu piesa aleasă. Alegând oricare din piesele
945 2 sau 4 există doar o piesă ce este identică cu piesa aleasă.
Dacă alegem piesa 6 nu există pe tablă piese identice cu ea.
1 2 .
6
1 3 3
4 5 9
1 3 3
9 5 4 Se rezolvă cerinţa 2. Piesele 1 şi 5 formeză un grup de piese prietene.
3 3 1 Piesele 2, 4 şi 6 formează alt grup. Piesa 3 formeaz singură un grup.
9 4 5 În total, pe tablă, sunt 3 grupuri de piese prietene.
1 2 Se rezolvă cerina 3. Identificăm două secvenţe de lungime maximă,
6 egală cu 5, pentru care prima şi ultima piesă sunt prietene:
1 3 3
4 5 9
1 3 3
9 5 4
3 3 1
9 4 5
Cerinţa 1
- pentru determinarea numărului M ce reprezintă cel mai mare număr de piese de pe tabla de
joc, identice cu o piesă aleasă, se construieşte un vector de frecvenţă V cu ajutorul căruia se va
contoriza numărul pieselor identice;
- fiecărei piese C1 C2 C3 ı̂i vom asocia o valoare numerică C1*100+C2*10+C3, această
valoare este un număr natural din intervalul [0,999];
- se va ţine cont de faptul că pentru oricare două piese identice C1 C2 C3 şi
C3 C2 C1 vor avea asociată aceeaşi valoare numerică;
- V[C1*100+C2*10+C3] se va incrementa de fiecare dată când este ı̂ntâlnită pe tabla de joc o
piesă ce are asociată valoarea numerică prezizată mai sus;
CAPITOLUL 19. ONI 2019 19.3. TRIO 235
ifstream f("trio.in");
ofstream g("trio.out");
int N,C,nr,ap[1000],c[4],max_identice,nr_ord,nr_grupuri;
int main()
{
int i;
f>>C>>N;
nr=(c[1]*100+c[2]*10+c[3]);
ap[nr]++;
if(ap[nr]>max_identice)
max_identice=ap[nr];
nr_ord=c[1]*100+c[2]*10+c[3];
grup[nr_ord]=1;// vector de aparitii ptr grup
if(prima_poz[nr_ord]==0)
//memorez primul nr de ordine al unei piese din grup
prima_poz[nr_ord]=i;
else
//memorez ultimul numar de ordine al unei piese din acelasi grup
ultima_poz[nr_ord]=i;
}
if (C==1)
CAPITOLUL 19. ONI 2019 19.3. TRIO 236
g<<max_identice-1<<’\n’;
else
if (C==2)
{
for(i=0; i<=999; i++)
if(grup[i]) nr_grupuri++;
g<<nr_grupuri<<’\n’;
}
else
{
for(i=0; i<=999; i++)
if(ultima_poz[i]-prima_poz[i]>max_echivalente)
max_echivalente=ultima_poz[i]-prima_poz[i];
g<<max_echivalente+1<<’\n’;
}
return 0;
}
ifstream fin("trio.in");
ofstream fout("trio.out");
int C; // nr cerinta
int N;
void rezolva1()
{
for(int i=1; i<=N; i++)
{
fin>>c1>>c2>>c3;
}
}
void rezolva2()
{
for(int i=1; i<=N; i++)
{
fin>>c1>>c2>>c3;
}
}
void rezolva3()
{
for(int i=1; i<=N; i++)
{
fin>>c1>>c2>>c3;
}
}
int main()
{
fin>>C;
fin>>N;
if(C==1) rezolva1();
else
if(C==2) rezolva2();
else
if(C==3) rezolva3();
CAPITOLUL 19. ONI 2019 19.3. TRIO 237
return 0;
}
maxp=0;
for(int i=0; i<=999; i++)
if(nraparitii[i] > maxp)
maxp=nraparitii[i];
cout<<"maxp-1 = "<<maxp-1<<"\n";
fout<<maxp-1<<’\n’; // Atentie la textul cerintei si exemplul 1
}
nrgp=0;
for(int i=0; i<=999; i++)
if(nraparitii[i] > 0)
nrgp+=1;
cout<<"nrgp = "<<nrgp<<"\n";
fout<<nrgp<<’\n’; // Atentie la textul cerintei si exemplul 2
}
if(primaaparitie[p123]==0)
primaaparitie[p123]=i;
else
ultimaaparitie[p123]=i;
}
maxpiese=0;
for(int i=0; i<=999; i++)
if(ultimaaparitie[i] - primaaparitie[i] > maxpiese)
maxpiese=ultimaaparitie[i] - primaaparitie[i];
cout<<"maxpiese = "<<maxpiese+1<<"\n";
fout<<maxpiese+1<<’\n’; // Atentie la textul cerintei si exemplul 3
}
Capitolul 20
ONI 2018
20.1 desen
Problema 1 - desen 100 de puncte
La ora de desen, Gigel a primit ca temă un desen care să
fie realizat după următorul algoritm:
Pas 1: se desenează un triunghi, numerotat cu 1, ca ı̂n
Figura 1;
Pas 2: se ı̂mparte triunghiul 1 ı̂n trei poligoane (un drep-
tunghi şi două triunghiuri numerotate cu 2 şi 3) trasând două
segmente ca ı̂n Figura 2 ;
Pas 3: fiecare triunghi dintre cele două obţinute la Pas
2, se ı̂mparte ı̂n câte un dreptunghi şi câte două triunghiuri
(numerotate cu 4, 5, 6, 7) trasând câte două segmente ca ı̂n
Figura 3 ;
Pas 4: fiecare triunghi dintre cele patru obţinute la Pas
3, se ı̂mparte ı̂n câte un dreptunghi şi câte două triunghiuri
(numerotate cu 8, 9,10, 11, 12, 13, 14, 15) trasând câte două
segmente ca ı̂n Figura 4 ;
.......
Pas N : fiecare triunghi dintre triunghiurile obţinute la
Pas N 1, se ı̂mparte ı̂n câte un dreptunghi şi câte două
triunghiuri trasând câte două segmente.
Dacă valoarea lui K este ultimul număr folosit pentru nu-
merotarea triunghiurilor obţinute la Pas N 1, atunci tri-
unghiurile rezultate la Pas N vor fi numerotate cu numerele
naturale distincte consecutive K 1, K 2, K 3, ..., etc.
Cerinţe
Fişierul de intrare desen.in conţine pe prima linie un număr natural C reprezentând cerinţa
din problemă care trebuie rezolvată (1 sau 2).
Fişierul conţine pe a doua linie numărul natural K.
239
CAPITOLUL 20. ONI 2018 20.1. DESEN 240
Date de ieşire
Dacă C 1, atunci prima linie a fişierului de ieşire desen.out conţine cele două numere
naturale X şi Y , separate printr-un singur spaţiu, reprezentând răspunsul la cerinţa 1 a problemei.
Dacă C 2, atunci prima linie a fişierului de ieşire desen.out conţine un şir de numere
naturale ordonate crescător, separate prin câte un spaţiu, reprezentând răspunsul la cerinţa 2 a
problemei.
Exemple
desen.in desen.out Explicaţii
1 13 8 15 Cerinţa este 1, K 13. Aşa cum arată ı̂n Figura 4, la Pas 4
se obţin triunghiurile numerotate cu X 8, 9, 10, 11, 12, 13, 14,
Y 15.
2 13 136 Cerinţa este 2, K 13. Aşa cum arată Figura 4, triunghiul
numerotat cu K 13 se obţine din triunghiul 6. Triunghiul 6
este obţinut din triunghiul 3 care este obţinut din triunghiul 1.
Observăm că:
Exemple
Pas Cel mai mic număr folosit Cel mai mare număr folosit Număr triunghiuri
la numerotarea triunghiurilor la numerotarea triunghiurilor obţinute la acest
obţinute la acest pas obţinute la acest pas pas
0
Pas 1: 1 1 2
1
Pas 2: 2 3 2
2
Pas 3: 4 7 2
3
Pas 4: 8 15 2
Pas ...: ... ... ...
N 1 N N 1
Pas N: 2 2 1 2
Cerinţa 1.
Se determină valorile X şi Y cu proprietatea că:
N 1
X 2 & K & Y 2N 1 2 2N 1 1 2 X 1
Cerinţa 2.
Se afişează ı̂n ordine inversă valorile:
x1 K ©2, x2 x1 ©2, x3 x2 ©2, ..., xN 1
20.2 mostenire
Problema 2 - mostenire 100 de puncte
Regele Rufus doreşte să stabilească moştenitorul averii sale, adică să ofere parola de la seif
celui mai deştept dintre fiii săi. Iniţial, regele a avut parola X formată din N cifre nenule şi un
cod cheie Q (număr natural cu exact 9 cifre, distincte, toate nenule). În fiecare an din cei K ani
de domnie, folosind codul cheie Q, Rufus a modificat câte o secvenţă de cifre din parolă ajungând
la parola finală P .
Pentru fiecare secvenţă se cunoaşte poziţia S a primei cifre din secvenţă şi poziţia D a ultimei
cifre din secvenţă. Astfel, secvenţa este formată din cifrele situate pe poziţiile S, S 1, S 2, ...,
D ı̂n parola X.
Modificarea unei secvenţe din X constă ı̂n ı̂nlocuirea fiecărei apariţii a cifrei 1 cu prima cifră
a lui Q, apoi a fiecărei apariţii a cifrei 2 cu a doua cifră a lui Q, ..., a fiecărei apariţii a cifrei 9 cu
ultima cifră a lui Q.
Pentru a decide moştenitorul, regele le dă fiilor parola finală P , codul cheie Q, numărul K
de ani de domnie si cele K secvenţe de cifre care au fost modificate şi le cere să găsescă: parola
iniţială X, poziţia minimă Z din parola X care a apărut ı̂n cele mai multe secvenţe dintre cele
modificate de rege de-a lungul celor K ani de domnie şi cifrele distincte care au ocupat poziţia Z
ı̂n cei K ani.
Cerinţe
Scrieţi un program care citeşte numerele Q, N , K, cele N cifre ale parolei finale P şi cele K
perechi de poziţii S şi D, şi care rezolvă următoarele două cerinţe:
1. determină parola iniţială X;
2. determină poziţia minimă Z şi cifrele distincte care au ocupat această poziţie ı̂n cei K ani
de domnie.
Date de intrare
Date de ieşire
Dacă C 1, fişierul de ieşire mostenire.out va conţine pe prima linie cele N cifre ale parolei
initiale X, separate prin câte un spaţiu, ı̂n ordinea ı̂n care apar ı̂n X, reprezentând răspunsul la
cerinţa 1.
Dacă C 2, fişierul de ieşire mostenire.out va conţine pe prima linie numărul natural Z, iar
pe a doua linie cifrele distincte care au apărut pe poziţia minimă Z, reprezentând răspunsul la
cerinţa 2. Acestea vor fi afişate ı̂n ordine crescătoare, separate prin câte un spaţiu.
Exemple:
mostenire.in mostenire.out Explicaţii
1 273541337928 Cerinţa este 1, N=12, K=4.
712534698 12 4
147134714818
24
6 11
39
17
2 3 Cerinţa este 2, N=12, K=4.
712534698 12 4 1237 P=(1 4 7 1 3 4 7 1 4 8 1 8)
147134714818 Poziţiile care au apărut ı̂n cele mai multe secvenţe
24 sunt: 3,4,6,7 =¿ Z=3, iar cifrele distincte care au
6 11 ocupat succesiv această pozitie sunt 3,2,1,7. Aceste
39 cifre se vor scrie ı̂n fişier ı̂n ordine crescătoare
17
Cerinta 1
Se citesc succesiv intervalele S, D pe care s-au aplicat modificări.
Pentru secvenţa curentă, fiecare cifră poziţionată ı̂n secvenţă se ı̂nlocuieşte cu poziţia acestei
cifre ı̂n codul Q realizându-se astfel transformarea ı̂n sens invers.
Cerinta 2
Se poate utiliza un vector de frecvenţă cu N elemente. Pentru fiecare poziţie i din vector se
determină numărul secvenţelor ı̂n care a apărut acestă poziţie. Apoi, se stabileste pozitia minimă
Z cu număr maxim de apariţii.
După ce s-a stabilit pozitia Z, se determină cifrele ce au ocupat acestă poziţie, realizând de K
ori transformarea ı̂n sens invers. Se poate utiliza un vector de frecvenţă pentru a marca apariţia
acestor cifre şi pentru a le afişa ı̂n ordine strict crescătoare.
20.3 pyk
Problema 3 - pyk 100 de puncte
Fie k, n şi y trei numere naturale.
Fie X un şir format din n numere naturale: x1 , x2 , x3 , ..., xn .
Fie P produsul numerelor y, x1 , x2 , x3 , ..., xn , adică: P y x1 x2 x3 ... xn .
k
Numărul P este o ”k-putere” dacă există un număr natural z astfel ı̂ncât P z .
Cerinţe
Scrieţi un program care să citească numerele k, n, x1 , x2 , x3 , ..., xn şi care să determine:
1. cel mai mic număr şi cel mai mare număr din şirul X, formate doar din cifre identice;
2. descompunerea ı̂n factori primi a celui mai mic număr natural y (y ' 2) cu proprietatea că
numărul P y x1 x2 x3 ... xn este o ”k-putere”.
CAPITOLUL 20. ONI 2018 20.3. PYK 243
Date de intrare
Date de ieşire
Dacă C 1, atunci prima linie a fişierului de ieşire pyk.out conţine două numere naturale,
separate printr-un singur spaţiu, reprezentând răspunsul la cerinţa 1 a problemei. Dacă nu există
astfel de numere, prima linie a fişierului va conţine valoarea 1.
Dacă C 2, atunci fişierul de ieşire pyk.out conţine:
a pe prima linie, un număr natural m reprezentând numărul de factori primi distincţi din
descompunerea ı̂n factori primi a numărului y, determinat la rezolvarea cerinţei 2;
a pe fiecare dintre următoarele m linii (câte o linie pentru fiecare factor prim din descompunerea
ı̂n factori primi a lui y), câte două valori F şi E, separate printr-un singur spaţiu, reprezentând
factorul prim F şi exponentul E al acestui factor din descompunerea ı̂n factori primi a lui y.
Scrierea ı̂n fişier a acestor factori primi se va face ı̂n ordinea crescătoare a valorii lor.
Exemple
pyk.in pyk.out Explicaţii
1 4 1111 Cerinţa este 1, k 2, n 7.
27 Numerele din şirul X formate doar din cifre identice sunt:
122 1111 5 4 88 123 999 1111, 5, 4, 88, 999. Cel mai mic număr dintre acestea este
4, iar cel mai mare este 1111.
2 3 Cerinţa este 2, k 3, n 6. Produsul celor 6 numere din
36 21 şir este: 12*5*60*125*4*36=64800000
12 5 60 125 4 36 32 y 90 este cea mai mică valoare pentru care P 90
3
51 64800000 1800 devine o ”k-putere”.
Descompunerea ı̂n factori primi a lui y conţine m 3
1 2 1
factori primi : 2 3 5
Cerinta 1.
Se pot folosi două variabile xmin şi xmax pentru a memora valorile cerute. Se citesc succesiv
numerele din fişier. Se compară cifrele fiecărui număr. Dacă cifrele sunt identice, atunci numărul
curent se compară cu xmax şi xmin curent, actualizându-se valorile acestora.
Cerinţa 2.
O soluţie se poate obţine fără a calcula produsul numerelor astfel:
a Se determină numerele prime & 10000 folosind eventual Ciurul lui Eratostene (se vor memora
ı̂ntr-un vector v)
a Se citeşte din fişier fiecare număr din şirul X. Se poate determina frecvenţa de apariţie
pentru fiecare număr din şir cu ajutorul unui vector de frecvenţă (vectorul f r).
CAPITOLUL 20. ONI 2018 20.3. PYK 244
a Se parcurge vectorul f r. Pentru fiecare număr cu frecvenţa nenulă se verifică dacă este prim
(adică dacă apare ı̂n vectorul v).
În caz contrar se descompune ı̂n factori primi. Se contorizează fiecare apariţie a fiecărui factor
prim luând ı̂n calcul şi frecvenţa de apariţie a numărului descompus (se utilizează un vector w
ı̂n care elementul wj memorează produsul dintre frecvenţa de apariţie a factorului prim j şi
exponentul acestuia). Elementele wj % 0 au semnificaţia: factorul prim j are exponentul wj
ı̂n descompunerea ı̂n factori primi a lui y.
a Dacă factorii primi din produsul numerelor x1 , x2 , ..., xn au toţi exponenţii multiplu de k,
k
atunci produsul numerelor din şir este o k-putere şi y este 2
În caz contrar, numărul factorilor primi din descompunerea lui y este egal cu numărul valorilor
j din vectorul w, cu proprietatea că wj %k % 0. În y, exponentii acestor factori primi j vor fi
egali cu k wj %k (se incrementează exponentul până la primul multiplu de k).
ONI 2017
21.1 prime
Problema 1 - prime 100 de puncte
Eu sunt fascinată de numerele prime. Consider că numerele prime sunt ”scheletul” tuturor
numerelor sau ”atomii” acestora, pentru că orice număr natural mai mare decât 1 poate fi scris
ca un produs de numere prime. Recent am aflat şi alte proprietăţi interesante legate de numerele
prime, de exemplu:
1. În şirul Fibonacci există o infinitate de numere prime. Vă mai amintiţi şirul Fibonacci? 0,
1, 1, 2, 3, 5, 8, 13, ... Este şirul ı̂n care fiecare termen, exceptând primii doi, se obţine ca suma
celor doi termeni care ı̂l precedă.
2. Există numere naturale denumite ”economice”. Un număr natural este economic dacă
numărul de cifre necesare pentru scrierea sa este mai mare decât numărul de cifre necesare pentru
scrierea descompunerii sale ı̂n factori primi (adică decât numărul de cifre necesare pentru scrierea
factorilor primi şi a puterilor acestora). De exemplu 128 este economic pentru că 128 se scrie cu 3
7
cifre, iar descompunerea sa ı̂n factori primi se scrie cu două cifre (2 ); 4374 este economic pentru
7
că se scrie cu 4 cifre, ı̂n timp ce descompunerea sa ı̂n factori primi se scrie cu 3 cifre (2 3 )
Observaţi că atunci când un factor prim apare la puterea 1, aceasta nu este necesar să fie scrisă.
3. Multe numere naturale pot fi scrise ca sumă de două numere prime. Dar nu toate. De
exemplu, 121 nu poate fi scris ca sumă de două numere prime.
Cerinţe
Scrieţi un program care citeşte numărul natural n şi o secvenţă de n numere naturale, apoi
rezolvă următoarele cerinţe:
1. determină şi afişează câte dintre numerele din secvenţa dată sunt numere prime din şirul
Fibonacci;
2. determină şi afişează câte dintre numerele din secvenţa dată sunt numere economice;
3. determină şi afişează câte dintre numerele din secvenţa dată nu pot fi scrise ca sumă de
două numere prime.
Date de intrare
Fişierul de intrare prime.in conţine pe prima linie un număr natural c care reprezintă cerinţa
(1, 2 sau 3). Pe a doua linie se află numărul natural n. Pe a treia linie se află o secvenţă de n
numere naturale separate prin spaţii.
Date de ieşire
Fişierul de ieşire prime.out va conţine o singură linie pe care va fi scris răspunsul la cerinţa
din fişierul de intrare.
245
CAPITOLUL 21. ONI 2017 21.1. PRIME 246
a 1 $ n & 50
7
a Dacă c 1 sau c 3 numerele naturale din şir sunt mai mari decât 1 şi mai mici decât 10 .
14
a Dacă c 2 numerele naturale din şir sunt mai mari decât 1 şi mai mici decât 10 .
a Pentru rezolvarea corectă a cerinţei 1 se acordă 20 de puncte; pentru rezolvarea corectă a
cerinţei 2 se acordă 50 de puncte, iar pentru rezolvarea corectă a cerinţei 3 se acordă 30 de puncte.
Exemple
prime.in prime.out Explicaţii
1 3 Cerinţa este 1. Cele 3 numere prime din şirul Fibonacci existente
5 ı̂n secvenţă sunt 2, 13 şi 233.
2 10 13 997 233
2 2 Cerinţa este 2. Succesiunea conţine două numere economice
4 (128 şi 4374).
128 25 4374 720
3 4 Cerinţa este 3. Sunt 4 numere naturale din secvenţă care nu pot
5 fi scrise ca sumă de două numere prime: 57, 121, 11, 3.
57 30 121 11 3
Vom citi ı̂ntr-un vector a cele n valori şi vom determina vmax cea mai mare valoare din vector.
Pentru o abordare eficientă, pentru toate cele 3 cerinţe, pregenerăm numerele prime & 10
7
(sau & vmax pentru cerinţele 1 şi 3, respectiv sqrt vmax pentru cerinţa 2). Pentru aceasta vom
utiliza ciurul lui Eratostene, apoi vom transfera numerele prime ı̂ntr-un vector denumit prim, care
va avea nrprim elemente. Pentru cerinţa 2 poate fi util să precalculăm şi să reţinem ı̂ntr-un vector
şi lungimea fiecărui număr prim.
Pentru cerinţa 1 este suficient să generăm termenii şirului Fibonacci & vmax şi să memorăm
ı̂ntr-un vector acei termeni care sunt numere prime. Fiindcă numărul de termeni primi din şirul
Fibonacci & 10 este foarte mic, putem să căutăm secvenţial ı̂n acest şir fiecare element din
7
vectorul a şi să-l numărăm ı̂n cazul ı̂n care ı̂l găsim.
Pentru cerinţa 2 vom descompune fiecare număr din vectorul a ı̂n factori primi (eficient!!!
folosiţi numerele prime memorate ı̂n vectorul prim). Dacă numărul de cifre necesare pentru
scrierea factorilor primi şi a puterilor acestora este $ lungimea numărului curent din a, deducem
că este un număr economic şi ı̂l contorizăm.
Pentru cerinţa 3 vom parcurge vectorul a şi pentru fiecare element ai din vector verificăm
dacă poate fi scris ca sumă de două numere prime. Pentru aceasta parcurg vectorul de numere
prime până când se termină (sau, mai eficient, până când numărul prim curent p este mai mare
decât complementarul său ai p) sau până când găsesc un număr prim p pentru care ai p
este deasemenea prim. Dacă un astfel de număr prim nu a fost găsit, contorizez pe ai.
Dacă valoarea citită are numărul de cifre % numărul de cifre necesare pentru scrierea factorilor
primi şi a puterilor acestora, deducem că este un număr economic şi ı̂l contorizăm.
Cerinţa 3:
Aflăm numerele care pot fi scrise ca sumă de două numere prime. Din numărul total de numere
citite vom scădea numărul de numere care pot fi scrise ca sumă de două numere prime. Verificăm
doar numerele mai mari decât 3.
Orice număr par mai mare decât 3 poate fi scris ca sumă de două numere prime, prin
urmare pentru orice număr par mai mare decât 3 decrementăm contorul.
Pentru a găsi numerele impare care verifică această condiţie folosim proprietatea că suma dintre
două numere este impară doar dacă unul dintre cele două numere este par. Singurul număr prim
par este 2. Prin urmare este suficient să verificăm dacă diferenţa dintre numărul citit şi 2 este
număr prim. ı̂n caz afirmativ decrementăm contorul.
ifstream f("prime.in");
ofstream g("prime.out");
bool ciur[10000001];
int prim[665000],lg[665000];
int main()
{
int i,j,n,c,np,nf,f1,f2,f3;
long long a[51],mx;
int fib[26];
f>>c>>n;
for (i=0;i<n;i++)
{
f>>a[i];
if (a[i]>mx) mx=a[i];
}
if (c==2)
mx=sqrt(mx);
// nr prime cu ciur
ciur[0]=ciur[1]=1;
for (i=2;i*i<=mx;i++)
if (ciur[i]==0)
for (j=i*i;j<=mx;j=j+i)
ciur[j]=1;
np=0;
int p=9,k=1;
for (i=2;i<=mx;i++)
if (ciur[i]==0)
{
prim[np]=i;
while (i>p)
{
p=(p+1)*10-1;
k++;
}
lg[np++]=k;
}
// fibonacci prime
nf=0;
f1=0; f2=1; f3=1;
CAPITOLUL 21. ONI 2017 21.1. PRIME 248
while (f3<=mx)
{
if (ciur[f3]==0)
fib[nf++]=f3;
f1=f2; f2=f3; f3=f1+f2;
}
if (c==1)
{
int k=0;
for (i=0;i<n;i++)
for (j=0;j<nf;j++)
if (a[i]==fib[j])
{
k++;
break;
}
g<<k<<"\n";
}
else
if (c==2)
{
int k=0;
for (i=0;i<n;i++)
{
long long y=a[i],w=a[i];
f1=0;
f2=0;
while (y>0) { f1++; y/=10; }
for (j=0;prim[j]<a[i];j++)
if (ciur[a[i]-prim[j]]==0)
{
k++;
break;
}
}
}
g<<n-k<<"\n";
}
return 0;
}
ifstream fin("prime.in");
ofstream fout("prime.out");
bool ciur[VMAX];
int nrprim, nr, n;
int prim[PMAX];
int lgprim[PMAX];
long long int a[NMAX], vmax;
int fib[NMAX];
int nrfib;
int main()
{int cerinta, i, j, d, lg, lgx, f1, f2, f3, p, gasit;
long long int cx;
fin>>cerinta>>n;
for (i=0; i<n; i++)
{
fin>>a[i];
if (a[i]>vmax) vmax=a[i];
}
//ciur
if (cerinta==2) vmax=sqrt((double)vmax);
ciur[0]=ciur[1]=1;
for (d=2; d*d<=vmax; d++)
if (!ciur[d])
for (j=d*d; j<=vmax; j+=d)
ciur[j]=1;
}
nr=0;
for (i=0; i<n; i++)
{
for (j=0; j<nrfib && a[i]!=fib[j]; j++);
if (j<nrfib) nr++;
}
fout<<nr<<’\n’;
fout.close();
return 0;
}
if (cerinta==2)
{
nr=0;
//descompunere in factori primi eficient
for (i=0; i<n; i++)
{
cx=a[i]; lgx=0; do {lgx++; cx/=10;} while (cx);
lg=0;
for (j=0; j<nrprim && prim[j]*prim[j]<=a[i] && lg<lgx; j++)
{
for (p=0; a[i]%prim[j]==0; p++,a[i]/=prim[j]);
if (p)
{
lg+=lgprim[j];
if (p>1)
{
cx=p;
do {lg++; cx/=10;} while(cx);
}
}
}
if (a[i]>1)
{cx=a[i]; do {lg++; cx/=10;} while (cx);}
if (lg<lgx)
nr++;
}
fout<<nr<<’\n’;
fout.close();
return 0;
}
//cerinta 3
nr=0;
for (i=0; i<n; i++)
{
for (gasit=j=0; j<nrprim && a[i]>prim[j]; j++)
if (!ciur[a[i]-prim[j]]) {gasit=1; break;}
if (!gasit) nr++;
}
fout<<nr<<’\n’;
fout.close();
return 0;
}
ifstream fin("prime.in");
ofstream fout("prime.out");
bool prim(int n)
{
if (n<2) return 0;
if(n==2) return 1;
CAPITOLUL 21. ONI 2017 21.1. PRIME 251
if(n%2==0) return 0;
for(int d=3; d*d<=n; d=d+2)
if(n%d==0)
return 0;
return 1;
}
bool fibo(int n)
{
int a,b,c;
a=b=c=1;
while(c<n)
{
c=a+b;
a=b;
b=c;
}
return c==n;
}
int main()
{
int i,n,c,v[50],x=0, a;
long long a1,j;
fin>>c>>n;
if(c==1)
{
for(i=0; i<n; i++)
{
fin>>a;
if (fibo(a)&&prim(a))
x++;
}
fout<<x;
}
else if(c==2)
{
for(i=0; i<n; i++)
{
fin>>a1;
CAPITOLUL 21. ONI 2017 21.2. ROBOT 252
if (descompun(a1)<nrcif(a1))
{
x++;
cout<<a1<<"\n";
}
}
fout<<x;
}
else
{
x=n;
for(i=0; i<n; i++)
{
fin>>a;
if(n>3)
{
//orice numar par mai mare dcat 4 se poate scrie
// ca suma a doua numere prime
if(a%2==0) x--;
else if (prim(a-2))
{
x--;
}
}
}
fout<<x;
}
return 0;
}
21.2 robot
Problema 2 - robot 100 de puncte
Vlad a inventat un nou joc. Jocul conţine N standuri aşezate ı̂n linie dreaptă. Fiecare stand
are o etichetă pe care este scris un număr natural. Eticheta este considerată corectă dacă numărul
ı̂ndeplineşte următoarele două condiţii:
- conţine atât cifre pare, cât şi cifre impare;
- ı̂ncepe cu cifrele impare aşezate ı̂n ordine crescătoare, urmate de cifrele pare ı̂n ordine de-
screscătoare.
De exemplu, eticheta 137860 este corectă, dar etichetele 23541, 135, 64 şi 3146 nu sunt corecte.
Pentru jocul său, Vlad a construit robotul reparator care ştie să verifice numere şi să le repare,
dacă este necesar. Robotul reparator se deplasează ı̂n linie dreaptă şi se opreşte pe rând la fiecare
dintre cele N standuri. La fiecare stand, robotul verifică eticheta şi dacă nu este corectă, o
”repară”.
Pentru a repara eticheta, robotul aranjează cifrele impare ı̂n ordine crescătoare, apoi, ı̂n con-
tinuare, aranjează cifrele pare ı̂n ordine descrescătoare; dacă eticheta nu conţine nicio cifră impară,
cea mai mare cifră pară o ı̂nlocuieşte cu 9; dacă eticheta nu conţine nicio cifră pară, cea mai mică
cifră impară o ı̂nlocuieşte cu 0.
Deplasarea de la un stand la altul durează t secunde, verificarea etichetei unui stand durează
v secunde, iar repararea acesteia durează r secunde. Cursa robotului se ı̂ncheie după ce robotul a
verificat toate cele N standuri şi a reparat etichetele incorecte.
Cerinţe
Scrieţi un program care citeşte numărul N de standuri, timpul (ora h, minutul m, secunda
s) când robotul ajunge la primul stand, timpii t, v şi r cu semnificaţia din enunţ şi etichetele
standurilor şi care rezolvă următoarele cerinţe:
1. calculează şi afişează timpul (ora, minutul şi secunda) când robotul a ı̂ncheiat verificarea
tuturor celor N standuri şi repararea etichetelor incorecte;
2. repară (unde este necesar) etichetele standurilor şi afişează etichetele celor N standuri la
final.
CAPITOLUL 21. ONI 2017 21.2. ROBOT 253
Date de intrare
Fişierul de intrare robot.in conţine pe prima linie un număr natural C, reprezentând cerinţa
care urmează să fie rezolvată (1 sau 2).
Pe linia a doua se află numerele naturale N , h, m, s, iar pe linia a treia numerele naturale t,
v, r, cu semnificaţia din enunţ. Numerele aflate pe aceeaşi linie sunt separate prin câte un spaţiu.
Pe următoarele N linii se află etichetele standurilor, ı̂n ordinea aşezării acestora, câte o etichetă
pe o linie.
Date de ieşire
Dacă C 1, fişierul de ieşire robot.out va conţine o singură linie pe care vor fi scrise 3 numere
naturale separate prin câte un spaţiu hf mf sf , reprezentând ora, minutul şi respectiv secunda
la care robotul termină repararea.
Dacă C 2, fişierul de ieşire robot.out va conţine N linii pe care vor fi scrise etichetele
standurilor, ı̂n ordinea aşezării acestora, după ce robotul a ı̂ncheiat verificarea şi repararea, câte
o etichetă pe o linie.
Exemple
robot.in robot.out Explicaţii
1 11 21 49 Cerinţa este 1. Există 3 standuri.
3 11 20 50 Pentru simplitate notăm cu h:m:s ora h, m minute şi s secunde.
7 5 15 La primul stand robotul ajunge la ora 11:20:50. Primul stand
376572 are eticheta 376572, care este incorectă, deci robotul o repară.
3564 Aici va petrece 5 secunde pentru veri-ficare şi 15 secunde pentru
123 reparare, deci va pleca de aici la ora 11: 21:10.
La al doilea stand va ajunge la ora 11:21:17; eticheta sa 3564
este corectă deci robotul nu o va mo-difica; aici va petrece 5
secunde pentru verificare şi pleacă la ora 11:21:22.
La al treilea stand va ajunge la ora 11:21:29. Al treilea stand
are eticheta incorectă 123, robotul o repară, deci aici va petrece
5+15=20 secunde şi ora la care ı̂ncheie cursa este 11:21:49.
2 357762 Cerinţa este 2. Există 3 standuri.
3 11 20 50 3564 Primul stand are eticheta 376572, care este incorectă, robotul o
7 5 15 130 repară şi aceasta devine 357762.
376572 La al doilea stand eticheta 3564 este corectă. deci robotul nu o
3564 va modifica.
113 Al treilea stand are eticheta incorectă 113, robotul o repară şi
devine 130.
- aşezăm ı̂n continuare cifrele pare ce apar ı̂n număr ı̂n ordine descrescătoare şi contorizăm
concomitent numărul lor
Numărul citit este corect dacă ı̂ndeplineşte simultan condiţiile:
- numărul citit este egal cu numărul construit
- numărul este format atât din cifre pare cât şi din cifre impare
Pentru rezolvarea cerinţei 1)
- contorizăm numerele corecte ı̂n variabila ncorecte
- la final, calculăm timpul astfel:
s=s+(N-1)*(t+v)+(N-ncorecte)*r+v;
m=m+s/60;
s=s%60;
h=h+m/60;
m=m%60;
- scriem ı̂n fişier timpul calculat
Pentru rezolvarea cerinţei 2)
După construirea numărului prin aşezarea cifrelor pare şi impare, dacă acesta conţine:
a) doar cifre pare, ı̂nlocuieşte prima cifră a numărului construit cu cifra 9
b) doar cifre impare, şterge prima cifră a numărului construit şi adaugă 0 la sfârşit
Scriem ı̂n fişier numărul calculat
int main()
{ int N,i,cod,h,m,s,ok,cod1,cod2,ap[10],c,c1,j,T,t,v,r,
ncorecte=0,cif,ci,cp,pp,p2,pi;
ifstream in("robot.in");
ofstream out("robot.out");
in>>T;
in>>N>>h>>m>>s;
in>>t>>v>>r;
if(T==2)
for(i=1;i<=N;i++)
{
in>>cod;
cod2=0;
ci=0;cp=0;pp=1;pi=1;
for(cif=1;cif<=9;cif=cif+2)
{
cod1=cod;
while(cod1>0)
{ if(cod1%10==cif)
{
cod2=cod2*10+cif;ci++; pi*=10;
}
cod1/=10;
}
}
for(cif=8;cif>=0;cif=cif-2)
{
cod1=cod;
while(cod1>0)
{ if(cod1%10==cif)
{
cod2=cod2*10+cif;
cp++;
CAPITOLUL 21. ONI 2017 21.2. ROBOT 255
pp*=10;
}
cod1/=10;
}
}
if(cod==cod2&&ci*cp!=0)
out<<cod<<’\n’;
else
{
if(ci*cp!=0)
out<<cod2<<’\n’;
else
{
if(ci==0)
cod2=cod2%(pp/10)+9*(pp/10);
else
cod2=cod2%(pi/10)*10;
out<<cod2<<’\n’;
}
}
}
else
{
for(i=1;i<=N;i++)
{
in>>cod;
cod2=0;
ci=0;cp=0;pp=1;pi=1;
for(cif=1;cif<=9;cif=cif+2)
{
cod1=cod;
while(cod1>0)
{ if(cod1%10==cif)
{
cod2=cod2*10+cif;ci++;
pi*=10;
}
cod1/=10;
}
}
for(cif=8;cif>=0;cif=cif-2)
{
cod1=cod;
while(cod1>0)
{
if(cod1%10==cif)
{
cod2=cod2*10+cif;cp++;
pp*=10;
}
cod1/=10;
}
}
if(cod==cod2&&ci*cp!=0)
{
ncorecte++;
}
}
s=s+(N-1)*(t+v)+(N-ncorecte)*r+v;
m=m+s/60;
s=s%60;
h=h+m/60;
m=m%60;
out<<h<<" "<<m<<" "<<s<<"\n";
}
in.close();
out.close();
return 0;
}
CAPITOLUL 21. ONI 2017 21.2. ROBOT 256
ifstream f("robot.in");
ofstream g("robot.out");
while (x>0)
{
cif[x%10]++;
if (x%2==0) np++;
else
ni++;
x=x/10;
}
if (np==0)
{
for (i=1;i<=9;i+=2)
if (cif[i]>0)
{
cif[i]--;
cif[0]=1;
break;
}
}
else
if (ni==0)
{
for (i=8;i>=0;i-=2)
if (cif[i]>0)
{
cif[i]--;
cif[9]=1;
break;
}
}
y=0;
for (i=1;i<=9;i+=2)
for (j=0;j<cif[i];j++)
y=y*10+i;
for (i=8;i>=0;i-=2)
for (j=0;j<cif[i];j++)
y=y*10+i;
return y;
}
int main()
{
int c,n,h,m,s,t,v,r,i;
long long u,x,y;
f>>c;
f>>n>>h>>m>>s>>t>>v>>r;
for (i=0;i<n;i++)
{
f>>x;
y=verif(x);
if (x!=y)
{
s=s+r;
if (s>60)
{
CAPITOLUL 21. ONI 2017 21.2. ROBOT 257
s-=60; m++;
if (m>60)
{
m-=60; h++;
}
}
}
if (c==2)
g<<y<<’\n’;
}
if (c==1)
{
s=s+t*(n-1)+v*n;
m=m+s/60;
s=s%60;
h=h+m/60;
m=m%60;
g<<h<<" "<<m<<" "<<s<<"\n";
}
return 0;
}
ifstream fin("robot.in");
ofstream fout("robot.out");
int main()
{int i, rez, cx, x, cate, maxpar, minimpar, p10, corect, c, uc, j, timp, hf, mf, sf;
fin>>cerinta;
fin>>n>>h>>m>>s>>t>>v>>r;
if (cerinta ==1)
{
for (i=1; i<=n; i++)
{
fin>>x;
corect=1;
cx=x;
if (x%2==1) corect=0;
else
{ c=x%10; x/=10;
while (x>0 && x%2==0)
{
uc=x%10;
if (uc<c) corect=0;
c=uc;
x=x/10;
}
if (x==0) corect=0;
else
{c=x%10; x/=10;
while (x>0)
{
uc=x%10;
if (uc%2==0) corect=0;
if (uc>c) corect=0;
c=uc;
x/=10;
}
}
}
if (corect) nr++;
}
timp=h*3600+m*60+s+(n-nr)*r+t*(n-1)+v*n;
hf=timp/3600; timp=timp%3600; mf=timp/60; sf=timp%60;
CAPITOLUL 21. ONI 2017 21.2. ROBOT 258
p10/=10;
if (maxpar==-1) rez=(rez%p10)*10;
if (minimpar==10) rez=9*p10+rez%p10;
}
fout<<rez<<’\n’;
}
}
fout.close();
return 0;
}
ifstream f("robot.in");
ofstream g("robot.out");
CAPITOLUL 21. ONI 2017 21.2. ROBOT 259
int main()
{int n,p,h,m,s,t,v,r,ok,a,b,c,i,d;
unsigned long long T=0;
f>>p;
if(p==1)
{
f>>n>>h>>m>>s;
f>>t>>v>>r;
b=0;
for(i=1;i<=n;i++)
{
f>>a;
T=T+t+v;
d=a;
ok=1;
if(a%2!=0)ok=0;
else
{
c=a%10;
a=a/10;
while(c<=a%10 and a%2!=1)
{
c=a%10;
a=a/10;
}
c=a%10;
a=a/10;
if(c%2==0)ok=0;
else
{
while(c>=a%10 and a%2==1)
{
c=a%10;
a=a/10;
}
if(a!=0) ok=0;
}
}
if(!ok)
{
T=T+r;
int x=0,y=0,z1=1,z2=1,j,v;
for(j=1;j<=9;j=j+2)
{
a=d;
while(a!=0)
{
if(a%10==j){x=x*10+j;z1=z1*10;}
a=a/10;
}
}
for(j=8;j>=0;j=j-2)
{
a=d;
while(a!=0)
{
if(a%10==j){y=y*10+j;z2=z2*10;}
a=a/10;
}
}
if(x==0)
{
z2=z2/10;
v=9*z2+y%z2;
}
else
if(y==0)
if(z2>1)v=x*z2;
CAPITOLUL 21. ONI 2017 21.2. ROBOT 260
else
{
z1=z1/10;
v=(x%z1)*10;
}
else v=x*z2+y;
}
}
T=T-t;
h=h+T/3600;
T=T%3600;
m=m+T/60;
T=T%60;
s=s+T;
if(s>=60)
{
m=m+s/60;
s=s%60;
}
if(m>=60)
{
h=h+m/60;
m=m%60;
}
if(p==2)
{
f>>n>>h>>m>>s;
f>>t>>v>>r;
b=0;
for(i=1;i<=n;i++)
{
f>>a;
T=T+t+v;
d=a;
ok=1;
if(a%2!=0)ok=0;
else
{
c=a%10;
a=a/10;
while(c<=a%10 and a%2!=1)
{
c=a%10;
a=a/10;
}
c=a%10;
a=a/10;
if(c%2==0)ok=0;
else
{
while(c>=a%10 and a%2==1)
{
c=a%10;
a=a/10;
}
if(a!=0)ok=0;
}
}
if(!ok)
{
T=T+r;
int x=0,y=0,z1=1,z2=1,j,v;
for(j=1;j<=9;j=j+2)
CAPITOLUL 21. ONI 2017 21.3. ROUA 261
{
a=d;
while(a!=0)
{
if(a%10==j){x=x*10+j;z1=z1*10;}
a=a/10;
}
}
for(j=8;j>=0;j=j-2)
{
a=d;
while(a!=0)
{
if(a%10==j){y=y*10+j;z2=z2*10;}
a=a/10;
}
}
if(x==0)
{
z2=z2/10;
v=9*z2+y%z2;
}
else
if(y==0)
if(z2>1)v=x*z2;
else
{
z1=z1/10;
v=(x%z1)*10;
}
else v=x*z2+y;
g<<v<<endl;
}
else g<<d<<endl;
}
}
}
21.3 roua
Problema 3 - roua 100 de puncte
Un copil doreşte să vopsească ouăle de Paşte, având la dispoziţie vopsele de culoare roşie,
galbenă, verde şi albastră. Fiecare culoare va fi reprezentată printr-un singur caracter astfel: ’r’
pentru culoarea roşie, ’g’ pentru galben, ’v’ pentru verde, ’a’ pentru albastru.
Pentru a vopsi ouăle, le aşază ı̂n rând, unul după altul. Astfel, o colorare va fi o succesiune de
N caractere din mulţimea {’r’,’g’,’v’,’a’}, reprezentând, ı̂n ordinea aşezării, culorile celor N ouă.
Numim ”roua” o secvenţă de R caractere cu proprietatea că dintre acestea exact R 1 caractere
reprezintă culoarea roşie, iar un caracter reprezintă una dintre celelalte 3 culori. De exemplu
secvenţele roua de lungime 3 sunt ”grr”, ”rgr”, ”rrg”, ”vrr”, ”rvr”, ”rrv”,”arr”, ”rar”, ”rra”.
Copilul consideră că o colorare este R-frumoasă, dacă oricare R caractere consecutive din
colorare formează o secvenţă roua. De exemplu, pentru N 11 ouă, şirul ”arrrvrrrarr” reprezintă
o colorare 4-frumoasă.
Cerinţe
Cunoscând N , numărul de ouă vopsite, şi numărul natural R, scrieţi un program care determină
şi afişează:
1. numărul de secvenţe ”roua” de lungime R existente ı̂n colorarea celor N ouă;
2. numărul total al colorărilor R-frumoase pentru cele N ouă.
Date de intrare
CAPITOLUL 21. ONI 2017 21.3. ROUA 262
Fişierul de intrare roua.in conţine pe prima linie un număr natural C reprezentând cerinţa
din problemă care trebuie rezolvată (1 sau 2). A doua linie din fişier conţine numerele naturale N
şi R, separate prin spaţiu, reprezentând numărul de ouă şi lungimea unei secvenţe ”roua”. Dacă
C 1, fişierul va conţine şi o a treia linie pe care se află colorarea celor N ouă.
Date de ieşire
Fişierul de ieşire roua.out va conţine o singură linie pe care va fi scris un număr natural,
reprezentând răspunsul la cerinţa specificată ı̂n fişierul de intrare.
Exemple
roua.in roua.out Explicaţii
1 4 Cerinţa este 1. Există N=7 ouă.
7 3 vrrrgrr Secvenţele roua de lungime 3 existente ı̂n colorare sunt ”vrr”,
”rrg”, ”rgr”, ”grr”.
2 15 Cerinţa este 2. Există 4 ouă.
43 Colorările 3-frumoase ale celor 4 ouă sunt ”grrg”, ”grrv”, ”grra”,
”vrrg”, ”vrrv”, ”vrra”, ”arrg”, ”arrv”, ”arra”, ”rgrr”, ”rvrr”,
”rarr”, ”rrgr”, ”rrvr”, ”rrar”.
Variabilele N şi R memorează numărul de caractere, respectiv lungimea unei secvenţe roua.
1. În variabilele p1 şi p2 memorăm penultima, respectiv ultima poziţie a unui caracter diferit
de ’r’.
Pentru fiecare caracter c citit din fişier avem cazurile:
a) c=’r’, incrementăm nr de secvenţe roua dacă p1 ¡ poziţia curentă - R şi p2 ¿ poziţia curentă
-R
b) c j ’r’, incrementăm nr de secvenţe roua dacă poziţia curentă - p2 ' R, actualizăm valorile
lui p1 şi p2.
2. O secvenţă roua este formată din R caractere şi este de forma ”rrr..rXr...r”, unde X este
oricare dintre caracterele ’a’,’g’ sau ’v’ şi ocupă orice poziţie de la 1 la R, ı̂n cadrul unei secvenţe.
Calculăm a N %R, b N ©R.
Pentru deducerea formulei, analizăm mai ı̂ntai cazul a 0.
a) Dacă a 0, există ı̂n şir b grupe de căte R valori consecutive.
Pentru o colorare R-frumoasă, caracterul X poate avea o valoare din 3 valori posibile şi ocupă
aceeaşi poziţie ı̂n cadrul fiecărei grupe.
Poziţia caracterului X este o valoare de la 1 la R =¿ putem forma
b
3 colorări R-frumoase ı̂n care X ocupă poziţia 1,
b
3 colorări R-frumoase ı̂n care X ocupă poziţia 2,
...,
b
3 colorări R-frumoase ı̂n care X ocupă poziţia R .
CAPITOLUL 21. ONI 2017 21.3. ROUA 263
b
In total avem R 3 colorări posibile.
b) Dacă a j 0, există ı̂n şir b grupe de căte R valori şi o grupă cu ultimele a valori din şir .
Pentru o colorare R-frumoasă, caracterul X va ocupa
b1
- fie o poziţie ı̂ntre 1 şi a ı̂n b 1 grupe, caz ı̂n care se formează a 3 colorări
b
- fie o poziţie ı̂ntre a 1 şi R ı̂n primele b grupe =¿ se formează R a 3 colorări.
In total, numărul de colorări va fi
b1 b b b b b
a3 R a 3 = a 3 3 R a 3 = 3 a 3 R a = 3 2 a R.
Pentru N & 70 numărul de colorări se poate calcula direct ı̂n long long, iar pentru N % 70 se
va realiza ı̂nmulţirea dintre un număr mare şi un număr de o cifră.
int main()
{
in>>P;
if(P==1)
{
in>>N>>R>>c;i=1;
while(c==’r’&&i<N)in>>c,i++;
if(c!=’r’){p2=i;if(p2>=R)nroua=1;}
if(c==’r’&&i==N){out<<0<<’\n’;return 0;}
out<<nroua<<’\n’;
}
else
{
///P=2
in>>N>>R;
a=N%R;b=N/R;
if(N<=70)
{
long long p=1;
for(i=1;i<=b;i++,p*=3);
p=p*(2*a+R);
out<<p<<’\n’;
return 0;
}
for(i=v[0];i>=1;i--)
out<<v[i];
out<<’\n’;
}
}
ifstream f("roua.in");
ofstream g("roua.out");
int main()
{
int c,n,r,x,ct,i,j;
char ch[10001];
long long v,p;
f>>c;
f>>n>>r;
if (c==1)
{
x=0;
ct=0;
for (i=0;i<r;i++)
{
f>>ch[i];
if (ch[i]==’r’) x++;
}
if (x==r-1) ct++;
for (i=r;i<n;i++)
{
f>>ch[i];
if (ch[i-r]==’r’) x--;
if (ch[i]==’r’) x++;
if (x==r-1) ct++;
}
g<<ct<<"\n";
}
else
{
// 3ˆ(n/r)*(2*(n%r)+r)
int c[10001],nc=0;
x=n/r;
// 3ˆ(n/r)
nc=1; c[0]=1;
for (i=1;i<=n/r;i++)
{
c[0]=3*c[0];
p=c[0]/10;
c[0]=c[0]%10;
for (j=1;j<nc;j++)
{
c[j]=3*c[j]+p;
CAPITOLUL 21. ONI 2017 21.3. ROUA 265
p=c[j]/10;
c[j]=c[j]%10;
}
while (p>0)
{
c[nc++]=p%10;
p=p/10;
}
}
v=2*(n%r)+r;
if (v>1)
{
p=0;
for (i=0;i<nc;i++)
{
c[i]=v*c[i]+p;
p=c[i]/10;
c[i]=c[i]%10;
}
while (p>0)
{
c[nc]=p%10; nc++;
p=p/10;
}
}
for (i=nc-1;i>=0;i--)
g<<c[i];
g<<"\n";
}
return 0;
}
ifstream f("roua.in");
ofstream g("roua.out");
int t[10001];
int main()
{int p,r,n;
f>>p>>n>>r;
if(p==1)
{
int a=1,b=0,h;
char c;
f>>c;
while(c==’r’ and a<=n)
{
f>>c;
a++;
}
if(c==’r’)g<<0;
else
{
if(a>=r)b++;
h=a-1;
for(int i=a+1;i<=n;i++)
{
f>>c;
if(c==’r’)
{
if(i-a<r and i-a+h+1>=r)b++;
}
else
{
h=i-a-1;
CAPITOLUL 21. ONI 2017 21.3. ROUA 266
a=i;
if (h>=r-1)b++;
}
}
}
g<<b;
}
else
{
int a,j,k,b=0,c;
a=2*(n%r)+r;
k=0;
while(a>0)
{
t[++k]=a%10;
a=a/10;
}
b=0;
for(int i=1;i<=n/r;i++)
{
for(j=1;j<=k;j++)
{
c=t[j]*3+b;
t[j]=c%10;
b=c/10;
}
if(c>9)t[++k]=c/10;
b=0;
}
for(int i=k;i>=1;i--)
g<<t[i];
}
f.close();
g.close();
return 0;
}
ONI 2016
22.1 Norocos
Problema 1 - Norocos 100 de puncte
Un număr natural nenul m se numeşte norocos dacă pătratul lui se poate scrie ca sumă de
m numere naturale consecutive. Un număr natural m se numeşte k-norocos, dacă este egal cu
produsul a exact k numere prime distincte. Observaţi că ı̂ntre cele două proprietăţi definite nu
există nicio legătură.
Cerinţe
Date de intrare
Fişierul de intrare norocos.in conţine pe prima linie un număr natural C. Pentru toate testele
de intrare, numărul C are una din valorile 1 sau 2. Pe linia a doua a fişierului se găsesc numerele
naturale N şi k, cu semnificaţia din enunţ, iar pe a treia linie se găsesc N numere naturale,
separate prin câte un spaţiu.
Date de ieşire
Exemple
267
CAPITOLUL 22. ONI 2016 22.1. NOROCOS 268
a)
m este norocos m
2
a a 1 a 2 ... a m 1 m2
ma m 1m©2
2m
2
2ma m 1m 2m 2a m 1
m 2a 1
m număr impar, a m 1©2
Prin urmare problema se reduce la a determina cel mai mare şi cel mai mic număr impar
dintr-un şir de n numere.
b)
Pentru rezolvarea acestei cerinţe trebuie să descompunem fiecare număr x ı̂n factori primi.
Trebuie să avem grijă de următoarele aspecte:
- Să ne oprim din algoritmul de descompunere imediat ce detectăm că numărul nu poate fi
k-norocos, de exemplu dacă am găsit un factor prim la putere mai mare decât unu, sau dacă am
descoperit mai mult de k factori primi.
- Optimizarea descompunerii ı̂n factori primi a numărului x prin ı̂mpărţire doar la divizorii d
cu proprietatea d d & x. Dacă am ajuns cu bine la finalul descompunerii şi dacă x este mai mare
decât 1 ı̂nseamnă că el este un număr prim la puterea 1, deci vom incrementa numărul de divizori
găsiţi.
int main ()
{
ifstream fin ("norocos.in");
ofstream fout("norocos.out");
fin>>t>>n>>k;
for (i=1;i<=n;i++)
{
fin>>x;
if (t == 1 && x%2 == 1)
{
a++;
if (x < amin) { amin = x; }
CAPITOLUL 22. ONI 2016 22.2. OGLINDA 269
if (x == 1) continue;
if (t == 2)
{
ok = 1;
r = (int)sqrt(x);
d = 2;
nr = 0;
if (e != 1)
{
ok = 0;
break;
}
nr++;
if (nr > k)
{
ok = 0;
break;
}
}
d++;
}
if (x!=1) nr++;
if (nr != k) ok = 0;
if (ok) sol++;
}
}
if (t == 1)
{
if (a == 0) { fout<<a<<"\n"; }
else { fout<<amin<<" "<<amax<<"\n"; }
}
else fout<<sol<<"\n";
return 0;
}
22.2 Oglinda
Problema 2 - Oglinda 100 de puncte
Pentru un număr natural N se consideră şirul a 1, 2, 3..., N , deci ai i pentru orice i,
1 & i & N.
Asupra acestui şir se pot aplica operaţii de două tipuri:
a) la operaţia de tipul 1 se specifică două valori i şi j, cu 1 & i & j & N . Efectul acestei
operaţii asupra şirului este de oglindire a secvenţei din şir care ı̂ncepe cu elementul de pe poziţia
i şi se termină cu cel de pe poziţia j. De exemplu, dacă ı̂n şirul a 1, 2, 3, 4, 5, 6, 7 se aplică
CAPITOLUL 22. ONI 2016 22.2. OGLINDA 270
operaţia 3 6, atunci şirul devine a 1, 2, 6, 5, 4, 3, 7. Iar ı̂n şirul a 1, 4, 3, 2, 5, 6, 7, dacă se
aplică operaţia 4 6, atunci a 1, 4, 3, 6, 5, 2, 7.
b) Operaţia de tipul 2 conţine un indice i, 1 & i & N , şi cere să afişăm valoarea elementului
care se află ı̂n acel moment pe poziţia i ı̂n şir.
Se consideră M astfel de operaţii ı̂ntr-o ordine dată.
Cerinţe
Scrieţi un program care să determine şi să afişeze rezultatul pentru fiecare operaţie de tipul 2.
Date de intrare
Fişierul de intrare oglinda.in conţine pe prima linie două numere naturale N şi M , separate
printr-un spaţiu. Pe fiecare dintre următoarele M linii este specificată câte o operaţie de tipul 1
sau 2. O linie poate să conţină două sau trei numere, astfel: 1 i j (indicând o operaţie de tipul
1) respectiv 2 i (indicând o operaţie de tip 2). Valorile de pe aceeaşi linie sunt separate prin câte
un spaţiu.
Date de ieşire
Fişierul de ieşire oglinda.out conţine un număr de linii egal cu numărul de operaţii de tipul
2 care sunt definite ı̂n fişierul de intrare. Pe fiecare linie este afişat câte un număr natural
reprezintând rezultatul pentru o operaţie de tip 2 prezentă ı̂n fişierul de intrare, ı̂n ordinea ı̂n
care acestea sunt definite.
Restricţii şi precizări
a 1 & N & 1000000
a 1 & M & 2000
a Pentru teste ı̂n valoare de 40 de puncte, vom avea 1 & N & 2000.
a Se garantează că 1 & i & j & N la operaţiile de tipul 1 şi că 1 & i & N la operaţiile de tip 2.
a Se garantează că există cel puţin o operaţie de tipul 2.
Exemple
oglinda.in oglinda.out Explicaţii
10 4 3 Şirul iniţial este: 1 2 3 4 5 6 7 8 9 10
23 6 Rezultatul operaţiei 2 3 are ca efect afişarea elementului de pe
127 1 poziţia 3 (care este chiar 3).
23 Rezultatul operaţiei 1 2 7 are ca efect transformarea şirului ı̂n:
21 1 7 6 5 4 3 2 8 9 10.
Rezultatul operaţiei 2 3 are ca efect afişarea elementului de pe
poziţia 3 (care acum este 6).
Rezultatul operaţiei 2 1 are ca efect afişarea elementului de pe
poziţia 1 (care acum are valoarea 1).
int main ()
{
ifstream fin ("oglinda.in");
ofstream fout("oglinda.out");
fin>>n>>m;
for (i=1;i<=m;i++)
{
fin>>t;
if (t == 1)
{
k++;
fin>>S[k]>>D[k];
}
else
{
fin>>a;
for (j=k; j>=1; j--)
{
if (S[j] <= a && a <= D[j])
{
x = a - S[j];
a = D[j] - x;
}
}
fout<<a<<"\n";
}
}
return 0;
}
22.3 Perechi
Problema 3 - Perechi 100 de puncte
Fie un şir a1 , a2 , ..., an de numere naturale, unde n este impar. Avem la dispoziţie o singură
operaţie admisă şi anume: putem aduna la două poziţii diferite din şir o aceeaşi valoare naturală
nenulă.
Cerinţe
1. Să se verifice dacă şirul poate să aibă toate elementele egale după aplicarea unei singure
operaţii.
2. Folosind de mai multe ori operaţia admisă, să se obţină şirul cu toate elementele egale, dar
valoarea egală obţinută să nu depăşească dublul valorii maxime din şirul iniţial.
Date de intrare
Fişierul perechi.in conţine pe prima linie un număr natural C, pe a doua linie numărul n, iar
pe linia a treia, separate prin câte un spaţiu, valorile a1 , a2 , ..., an .
CAPITOLUL 22. ONI 2016 22.3. PERECHI 272
Date de ieşire
Exemple
perechi.in perechi.out Explicaţii
1582882 256 C 1, deci se va rezolva doar prima cerinţă! Adunând valoarea
6 la poziţiile 2 şi 5 se va obţine şirul constant 8 8 8 8 8
2 122 C 2, deci se va rezolva doar a doua cerinţă! Valoarea maximă
5 344 din şir este 10, deci valoarea finală trebuie să fie maximum 20.
8 5 6 3 10 243 Trebuie efectuate cel mult 5 operaţii pentru 100 puncte.
Aplicând operaţia 1 2 2, obţinem şirul 10 7 6 3 10
Aplicând operaţia 3 4 4, obţinem şirul 10 7 10 7 10
Aplicând operaţia 2 4 3, obţinem şirul 10 10 10 10 10
1 0 C 1, deci se va rezolva doar prima cerinţă! Nu se poate efectua
5 o singură operaţie astfel ı̂ncât toate elementele şirului să devină
82782 egale.
2 131 C 2, deci se va rezolva doar a doua cerinţă! Valoarea maximă
3 122 din şir este 3, deci valoarea finală trebuie să fie maximum 6.
123 Trebuie efectuate cel mult 3 operaţii pentru 100 puncte.
Aplicând operaţia 1 3 1, obţinem şirul 2 2 4
Aplicând operaţia 1 2 2, obţinem şirul 4 4 4
Cerinţa 1
CAPITOLUL 22. ONI 2016 22.3. PERECHI 273
Se verifică dacă ı̂n şir sunt doar două valori distincte, una care apare de 2 ori, cealaltă care
apare de n 2 ori. În caz afirmativ, se verifică dacă valoarea care apare de două ori este mai mică
decât cealaltă valoare.
Cerinţa 2
Ordonăm crescător şirul. Deoarece trebuie să rămână ordinea iniţială, păstrăm indicii ele-
mentelor ordonate.
După sortare pornim de la stânga la dreapta şi luăm iniţial primele două elemente ale şirului
sortat (cele mai mici).
Fie acestea a şi b cu a & b. Adunăm la cele două componente valoarea dată de diferenţa dintre
cel mai mare din elementele şirului (acesta se găseşte pe ultima poziţie ı̂n şirul sortat şi ı̂l notăm
cu max) şi a.
După această operaţie, pe primele două poziţii vom avea valorile max şi b max a (& max).
Deci acum valoarea maximă ı̂n şir, max, se află sigur pe a doua poziţie.
Procedăm analog cu componentele de pe poziţiile 3 şi 4 (notate la fel cu a şi b), adunând la
acestea valoarea max a, obţinând valorile max şi b max a.
Similar se procedează cu toate perechile de pe poziţiile 2p 1, 2p.
Ultima de acest fel este n 2, n 1 (nu uităm că n este impar).
În acest moment am efectuat (n-1) div 2 operaţii de adunare, iar valoarea de pe prima
poziţie este egală cu cea de pe ultima poziţie, iar ı̂n rest, valorile de pe poziţiile 2p sunt egale cu
valorile de pe poziţiile 2p 1.
Maximul ı̂n şir este pe penultima poziţie n 1.
Vom aduna la toate cuplurile egale atât cât este necesar să ajungem la valoarea maximă (deci
ı̂ncă (n-1) div 2 operaţii).
În total am efectuat n 1 operaţii, deci ne ı̂ncadrăm ı̂n limita de n operaţii efectuate.
int a[Dim];
int P[Dim];
int n;
void Cerinta1()
{
int i, cnt;
ofstream fout(outFile);
void Cerinta2()
{
int i, ultim, v;
CAPITOLUL 22. ONI 2016 22.3. PERECHI 274
ofstream fout(outFile);
ultim = n;
for (i = 1; i < n; i += 2)
{
v = a[ultim] - a[i];
if (v > 0)
{
a[i] += v;
a[i + 1] += v;
fout << P[i] << " " << P[i + 1] << " " << v << "\n";
a[++ultim] = a[i];
P[ultim] = P[i];
a[++ultim] = a[i + 1];
P[ultim] = P[i + 1];
}
}
int main()
{
int i, j, C;
int aux;
//citire
ifstream fin(inFile);
fin >> C;
fin >> n;
for (i = 1; i <= n; ++i)
{
fin >> a[i];
P[i] = i;
}
fin.close();
//sortare
for (i = 1; i < n; ++i)
for (j = i + 1; j <= n; ++j)
if (a[i] > a[j])
{
aux = a[i];
a[i] = a[j];
a[j] = aux;
aux = P[i];
P[i] = P[j];
P[j] = aux;
}
if (C == 1) Cerinta1();
else Cerinta2();
return 0;
}
ONI 2015
23.1 iepuras
Problema 1 - iepuras 100 de puncte
Iepuraşul Coconaş vrea să ajungă la grădina cu morcovi. Pentru aceasta el trebuie să traverseze
prin salturi o zonă cu proprietăţi speciale. Zona este formată din N căsuţe numerotate de la 1 la
N , dispuse una după cealaltă, iar fiecare căsuţă conţine un număr natural ce reprezintă cantitatea
de energie necesară iepuraşului pentru a sări ı̂ntr-o altă căsuţă. Iepuraşul pleacă dintr-o anumită
căsuţă şi se deplasează, de la stânga la dreapta, spre grădina cu morcovi după următoarele reguli:
a numărul ı̂nscris ı̂n căsuţa ı̂n care se află iepuraşul reprezintă numărul de căsuţe peste care
el va sări;
a dacă numărul ı̂nscris ı̂n căsuţa ı̂n care se află iepuraşul este număr prim, atunci energia lui
se dublează şi va sări peste un număr dublu de căsuţe;
a numărarea căsuţelor peste care va sări se face de la stânga la dreapta şi ı̂ncepe cu căsuţa
imediat următoare.
Astfel, dacă iepuraşul se află ı̂n căsuţa a treia şi numărul ı̂nscris ı̂n această căsuţă este 5,
iepuraşul va ajunge ı̂n căsuţa cu numărul de ordine 13 (13 3 2 5).
a dacă iepuraşul ajunge ı̂ntr-o căsuţă care conţine numărul 0, el rămâne acolo pentru că nu
mai are energie să sară mai departe, altfel el continuă să sară după regulile descrise mai sus;
a iepuraşul ajunge la grădina cu morcovi dacă ultimul salt pe care ı̂l face depăşeşte căsuţa N .
Cerinţe
Scrieţi un program care citeşte trei numere naturale P , N şi K iar apoi N numere naturale şi
determină:
1) dacă iepuraşul poate ajunge sau nu, la grădina cu morcovi pornind din căsuţa K şi numărul
de salturi pe care le face iepuraşul pornind din căsuţa K;
2) căsuţa de pornire a iepuraşului, astfel ı̂ncât drumul parcurs de el să traverseze un număr
maxim de căsuţe. Pentru a determina numărul de căsuţe se vor lua ı̂n calcul: căsuţa de pornire,
toate căsuţele peste care iepuraşul a sărit şi toate căsuţele ı̂n care a ajuns ı̂n urma salturilor.
Iepuraşul poate porni din oricare căsuţă. În cazul ı̂n care există două sau mai multe căsuţe de
pornire care conduc la acelaşi număr maxim de căsuţe traversate se va lua ı̂n considerare căsuţa
cu numărul de ordine cel mai mic.
Date de intrare
Fişierul de intrare iepuras.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 fişierului iepuras.in se găsesc, ı̂n această ordine, numerele naturale N şi K,
separate prin câte un spaţiu.
Pe a treia linie se găsesc N numere naturale separate prin câte un spaţiu, reprezentând valorile
din fiecare căsuţă ı̂n ordine de la 1 la N .
Date de ieşire
Dacă valoarea lui P este 1, se va rezolva numai punctul 1) din cerinţe. În acest caz, fişierul
de ieşire iepuras.out va conţine pe prima linie cuvântul DA ı̂n cazul ı̂n care iepuraşul a ajuns ı̂n
275
CAPITOLUL 23. ONI 2015 23.1. IEPURAS 276
grădina cu morcovi, respectiv cuvântul NU ı̂n caz contrar, iar pe a doua linie va conţine un număr
natural reprezentând numărul de salturi pe care le face iepuraşul pornind din căsuţa K.
Dacă valoarea lui P este 2, se va rezolva numai punctul 2) din cerinţe. În acest caz, fişierul
de ieşire iepuras.out va conţine pe prima linie două numere naturale separate printr-un spaţiu
reprezentând, ı̂n ordine, căsuţa de pornire şi numărul maxim de căsuţe determinat, iar pe a doua
linie, un şir de numere naturale separate prin câte un spaţiu reprezentând numerele din căsuţele ı̂n
care iepuraşul nu s-a aflat sau nu a sărit pe parcursul drumului, de la stânga la dreapta, ı̂ncepând
cu căsuţa 1. Dacă numărul maxim de căsuţe traversate este chiar N linia a doua nu va conţine
niciun număr.
Exemple
iepuras.in iepuras.out Explicaţii
NU P 1, pentru acest test, se rezolva cerinţa 1).
2 Iepuraşul pleacă din căsuţa 3, sare ı̂n căsuţa cu
numărul de ordine 7 şi mai departe, ı̂n căsuţa
cu numărul de ordine 11, unde găsind numărul
0 se opreşte.
2 2 13 P 2, pentru acest test, se rezolvă cerinţa
14 3 2601120021 2). Pentru a traversa un număr maxim de
23601121400231 căsuţe, iepuraşul pleacă din căsuţa cu numărul
de ordine 2 şi sare, pe rând, ı̂n căsuţele cu
numerele de ordine 8, 9, 13, şi apoi ı̂n grădină,
traversând astfel 13 căsuţe (de la căsuţa 2 la
căsuţa 14). Iepuraşul nu s-a aflat sau nu a
sărit ı̂n căsuţele de pe poziţiile 1, 3, 4, 5, 6, 7,
10, 11, 12 şi 14.
Cerinţa 2
Calculăm numărul de căsuţe peste care poate sări iepuraşul (ca la cerinţa 1) pornind din căsuţa
1.
CAPITOLUL 23. ONI 2015 23.1. IEPURAS 277
Dacă indicele căsuţei la care ajunge iepuraşul este mai mare strict decat N atunci
numărul de căsuţe = N - poziţia de pornire + 1
altfel
numărul de căsuţe = indicele căsuţe - poziţia de pornire + 1.
Actualizăm maximum şi poziţia de pornire.
Repetăm algoritmul pentru restul căsuţelor până la N .
Scriem poziţia de pornire şi valoarea numărului maxim de căsuţe ı̂n fişier.
Scriem toate căsuţele de la 1 până la căsuţa de pornire determinată mai sus apoi scriem toate
căsuţele de pe traseul iepuraşului, cu excepţia căsuţei de pornire şi a celor ı̂n care a sărit.
Dacă ultima căsuţă ı̂n care ajunge iepuraşul are indicele strict mai mic decât N , scriem restul
căsuţelor până la N .
2
Soluţia are complexitatea O n .
Soluţia 2
Cerinţa 1
Se memorează numerele din casuţe ı̂ntr-un vector v.
Se simulează săriturile iepuraşului ce porneşte din căsuţa k şi se opreste fie când ajunge la o
căsuţă ce conţine numărul 0 fie când ajunge ı̂n grădina cu morcovi.
Cerinţa 2
Pentru a determina numărul maxim de căsuţe traversate se construieşte ı̂ncepând cu poziţia
n, un vector suplimentar a cu semnificaţia:
ai = poziţia ı̂n care se opreşte iepuraşul ce porneşte din căsuţa cu numărul i.
~
n; dacă pornim din poziţia i iepuraşul ajunge ı̂n grădină
i;
dacă ai 0
ai
ai 2 ai; dacă ai este număr prim
ai ai; dacă ai nu este număr prim
Pentru fiecare poziţie i, ı̂ncepând cu poziţia n se determină numărul căsuţelor traversate ca
fiind l ai i 1 şi se actualizează valoarea maximă, reţinându-se poziţia.
void prim(int n)
{
int i,j;
for (i=2;i<=n;i++)
x[i]=1;
for (i=2;i<=sqrt(n);i++)
if (x[i])
for (j=i;j<=n/i;j++)
x[i*j]=0;
}
int main()
CAPITOLUL 23. ONI 2015 23.1. IEPURAS 278
{
int N, K, P, i, j, l, nr=0, Max=0, poz; //nr-numar salturi din pozitia i
ifstream in("iepuras.in");
ofstream out("iepuras.out");
in>>P>>N>>K;
for(i=1;i<=N;i++) in>>v[i];
prim(100);
if(P==1)
{ //cerinta 1
j=K; nr=0;
while(v[j] && j<=N)
{
nr++;
if(x[v[j]])
j+=2*v[j];
else
j+=v[j];
}
if(j<=N)
{
out<<"NU"<<endl;
out<<nr;
}
else
{
out<<"DA"<<endl;
out<<nr;
}
}
else
{
//cerinta 2
i=1,j=1;
while(i<=N && j<=N)
{
j=i;nr=1;
while(v[j] && j<=N)
{
if(x[v[j]])
j+=2*v[j];
else
j+=v[j];
}
if(j>N)
nr=N-i+1;
else
nr=j-i+1;
if(nr>Max)
poz=i, Max=nr;
i++;
}
out<<poz<<’ ’<<Max<<’\n’;
for(i=1;i<=poz-1;i++)
out<<v[i]<<’ ’;
j=poz;
for(i=1;i<=Max && i<=N;i++)
{
if(x[v[j]])
j+=2*v[j];
else
j+=v[j];
poz=j;
}
CAPITOLUL 23. ONI 2015 23.1. IEPURAS 279
for(i=j+1;i<=N;i++)
out<<v[i]<<’ ’;
}
return 0;
}
bool prim(int x)
{
for(int d=2; d*d<=x; d++)
if(x%d==0) return false;
return (x>=2);
}
int main()
{
freopen("iepuras.in", "r",stdin);
freopen("iepuras.out","w",stdout);
if(P==1)
{ Countstep=0;
for(i=K; i<=N && A[i]; i+=step, Countstep++)
{
if (Prim[A[i]]) step=A[i]*2;
else step=A[i];
}
if (i>N) i = N;
if(i- I + 1>CountMax)
{
CountMax=i- I + 1;
Pos = I;
}
}
if (Prim[A[i]]) Pos+=A[i]*2;
else Pos+=A[i];
}
return 0;
}
bool prim(int x)
{
for(int d=2; d*d<=x; d++)
if(x%d==0) return false;
return (x>=2);
}
int main()
{
freopen("iepuras.in", "r",stdin);
freopen("iepuras.out","w",stdout);
if(P==1)
{ Countstep=0;
for(i=K; i<=N && A[i]; i+=step, Countstep++)
{
if (Prim[A[i]]) step=A[i]*2;
else step=A[i];
}
if (i>N) i = N;
if(i- I + 1>CountMax)
{
CountMax=i- I + 1;
Pos = I;
}
}
else Pos+=A[i];
}
return 0;
}
int v[100001];
int a[100001];
int main()
{
ifstream f("iepuras.in");
ofstream g("iepuras.out");
int n,p,k,i,j,nr=0,l;
f>>p>>n>>k;
for (i=1; i<=n; i++) f>>v[i];
if (p==1)
{
while (k<=n && v[k]!=0)
{
nr++;
if (prim (v[k])) k=k+2*v[k];
else k=k+v[k];
}
if (k>n) g<<"DA"<<’\n’<<nr<<’\n’;
else g<<"NU"<<’\n’<<nr<<’\n’;
}
else
{
int vm=-1;
for (i=n; i>=1; i--)
{
if (v[i]==0)
a[i]=i;
else
if (prim(v[i]))
{
j=i+2*v[i];
if (j<n) a[i]=a[j];
else a[i]=n;
}
else
{
j=i+v[i];
if (j<n) a[i]=a[j];
else a[i]=n;
}
l=a[i]-i+1;
if (vm<=l){vm=l; k=i;}
}
g<<k<<’ ’<<vm<<’\n’;
CAPITOLUL 23. ONI 2015 23.1. IEPURAS 282
int u=1;
g<<’\n’;
}
return 0;
}
int v[100001];
int a[100001];
int main()
{
ifstream f("iepuras.in");
ofstream g("iepuras.out");
int n,p,k,i,j,nr=0,l,x;
f>>p>>n>>k;
i=0;
while (f>>x)
{
i++; v[i]=x;
assert (v[i]>=0&&v[i]<=100);
}
assert(p==1 || p==2);
assert(n>=1&& n<=7000);
assert(k<=n && k>=1);
assert(i==n);
if (p==1)
{
while (k<=n && v[k]!=0)
{
nr++;
if (prim (v[k])) k=k+2*v[k];
else k=k+v[k];
}
if (k>n) g<<"DA"<<’\n’<<nr<<’\n’;
else g<<"NU"<<’\n’<<nr<<’\n’;
CAPITOLUL 23. ONI 2015 23.1. IEPURAS 283
}
else
{
int vm=-1;
for (i=n; i>=1; i--)
{
if (v[i]==0)
a[i]=i;
else
if (prim(v[i]))
{
j=i+2*v[i];
if (j<n) a[i]=a[j];
else a[i]=n;
}
else
{
j=i+v[i];
if (j<n) a[i]=a[j];
else a[i]=n;
}
l=a[i]-i+1;
if (vm<=l){vm=l; k=i;}
}
g<<k<<’ ’<<vm<<’\n’;
int u=1;
g<<’\n’;
}
return 0;
}
ifstream f("iepuras.in");
ofstream g("iepuras.out");
bool c[MAX],e1[100001];
int e[100001],salturi,N,P,M,K,pozMin,nrMax;
int main()
{
int i,j,aux;
c[1]=1;
//generare ciur
M=sqrt(MAX);
for(i=2;i<=M;i++)
if(c[i]==0)
for(j=i*i;j<=MAX;j+=i)c[j]=1;
CAPITOLUL 23. ONI 2015 23.1. IEPURAS 284
//citire
f>>P>>N>>K;
for(i=1;i<=N;i++)f>>e[i];
if(P==1)//1)
{
//sarituri iepure
for(i=K;i<=N;)
if(e[i]==0)break;
else
{
salturi++;aux=e[i];if(c[aux]==0)aux*=2; i=i+aux;
}
//verficare
if(i<=N)g<<"NU"<<’\n’;else g<<"DA"<<’\n’;
g<<salturi<<’\n’;
}
else//2)
{
for(i=1;N-i>nrMax;i++)
{
//caut nrMax si pozMin
j=i;
while(j<=N && e[j]!=0)
{
if(c[e[j]]==0)j+=2*e[j];
else j+=e[j];
}
if(j>N)salturi=N-i+1;
else salturi=j-i+1;
if(salturi>nrMax) {nrMax=salturi;pozMin=i;}
}
g<<’\n’;
}
f.close();
g.close();
return 0;
}
23.2 inventie
Problema 2 - inventie 100 de puncte
Lui Mihai ı̂i place matematica distractivă, sau poate mai mult distracţia decât matematica.
Pentru a scăpa de teme, el a inventat operaţia ”smile” notată cu semnul , operaţie care se aplică
numerelor naturale nenule conform exemplelor de mai jos:
6 4=210 8 5=313 6 6=12 43 1500=1457 1543
9 2=711 7 6=113 6 10=416 23 23=46
Profesorul de matematică i-a promis nota 10 pentru invenţie, numai dacă ştie să determine
corect numărul divizorilor pari pentru rezultatul obţinut prin operaţia ”smile”. Astfel, Mihai
a primit N perechi de numere a, b pentru care trebuie să calculeze a b şi să determine dacă
rezultatul obţinut are divizori pari.
Cerinţe
Scrieţi un program care citeşte un număr natural N şi N perechi de numere naturale a, b şi
afişează:
a) pentru fiecare pereche de numere a, b, rezultatul a b;
b) cel mai mic şi cel mai mare rezultat a b care nu are divizori pari.
Date de intrare
Fişierul de intrare inventie.in conţine pe prima linie un număr natural N . Fiecare din
următoarele N linii conţine câte două numere naturale a, b despărţite printr-un spaţiu.
Date de ieşire
a 1 & N & 20
a a şi b sunt numere naturale nenule de maxim 18 cifre fiecare
Exemple
inventie.in inventie.out Explicaţii
8 210 Prin operaţia ”smile” se obţin, ı̂n ordine, valorile 210, 711,
64 711 313, 113, 12, 416, 14571543, 46.
92 313 Dintre acestea nu au divizori pari numerele 711, 313, 113,
85 113 14571543, cel mai mic fiind 113 şi cel mai mare 14571543.
76 12
66 416
6 10 14571543
43 1500 46
23 23 113
14571543
2 26 Prin operaţia ”smile” se obţin, ı̂n ordine, valorile 26,
13 13 9761512 9761512, ambele numere având divizori pari.
268 1244 0
int main()
{
int gasit=0,n,v[60],vmin[60],vmax[60],maimic,maimare,i,k;
ifstream f("inventie.in");
ofstream g("inventie.out");
f>>n;
if (a%2!=b%2)
{
k=0; // numarul cifrelor
gasit=1;
s=a+b;
while (s)
{
k++;
vmin[k]=vmax[k]=s%10;
s=s/10;
}
while (dif)
{
k++;
vmin[k]=vmax[k]=dif%10;
dif=dif/10;
}
vmin[0]=vmax[0]=k;
break;
}
}
i++;
while (i<=n)
{
f>>a>>b; //g<<" am citit "<<a<<’ ’<<b<<"la pasul "<<i<<’\n’;
if (a==b) g<<a+b<<’\n’;
else
CAPITOLUL 23. ONI 2015 23.2. INVENTIE 287
{
if (a>b) dif=a-b;
else dif=b-a;
g<<dif<<a+b<<’\n’;
}
if (a%2!=b%2)
{
k=0; // numarul cifrelor
s=a+b;
while (s)
{
k++;
v[k]=s%10;
s=s/10;
}
while (dif)
{
k++;
v[k]=dif%10;
dif=dif/10;
}
v[0]=k;
// verific daca noul rezultat este mai mic decat vmin,
// sau mai mare decat vmax
if (v[0]<vmin[0])
for (int j=0; j<=v[0]; j++) vmin[j]=v[j];
else if (v[0]>vmax[0])
for (int j=0; j<=v[0]; j++) vmax[j]=v[j];
else
{
if (v[0]==vmin[0])
{
maimic=1;// pres ca v<vmin
for (int j=v[0]; j>=1; j--)
if (v[j]>vmin[j])
{
maimic=0;
break;
}
else if (v[j]<vmin[j]) break;
if (maimic){
for (int j=0; j<=v[0]; j++) vmin[j]=v[j];
}
}
if (v[0]==vmax[0])
{
maimare=1; // pres ca v>vmax
for (int j=v[0]; j>=1; j--)
if (v[j]<vmax[j])
{
maimare=0;
break;
}
else if (v[j]>vmax[j]) break;
if (maimare)
for (int j=0; j<=v[0]; j++) vmax[j]=v[j];
}
}
}
i++;
}
if (gasit==0) g<<0<<’\n’;
else
{
for (int j=vmin[0]; j>=1; j--) g<<vmin[j];
g<<’\n’;
for (int j=vmax[0]; j>=1; j--) g<<vmax[j];
g<<’\n’;
}
return 0;
}
CAPITOLUL 23. ONI 2015 23.2. INVENTIE 288
ifstream fin("inventie.in");
ofstream fout("inventie.out");
unsigned ct,ad[40],i,k,maxx[40],minn[40];
int j;
int main()
{
unsigned n,ok=0;
unsigned long long a,b,z;
maxx[0]=0;
minn[0]=39;
for(j=1;j<=39;j++) minn[j]=9;
fin>>n;
for(k=1;k<=n;k++)
{
memset(ad,0,sizeof(ad));
fin>>a>>b;
aduna(a,b);
if(a==b);
else
if(a>b) fout<<a-b;
else fout<<b-a;
for(j=ad[0];j>=1;j--) fout<<ad[j];
fout<<’\n’;
if(a%2!=b%2)
{
ok=1;
z = a>b ? a-b : b-a;
j=ad[0];
while(z)
{
ad[++j]=z%10;
z/=10;
}
CAPITOLUL 23. ONI 2015 23.2. INVENTIE 289
ad[0]=j;
if(comp(ad,minn)<0)
{
for(j=ad[0];j>=0;j--) minn[j]=ad[j];
}
if(comp(ad,maxx)>0)
for(j=ad[0];j>=0;j--){ maxx[j]=ad[j]; }
}
}
if(ok)
{
for(k=minn[0];k>=1;k--) fout<<minn[k];
fout<<’\n’;
for(k=maxx[0];k>=1;k--)fout<<maxx[k];
fout<<’\n’;
}
else fout<<0<<’\n’;
return 0;
}
int main()
{
freopen("inventie.in", "r",stdin);
freopen("inventie.out","w",stdout);
scanf("%d\n",&N);
Min[0]=50;
for(int i= 1; i<=N; i++)
{
scanf("%lld %lld\n",&x, &y);
Y= x + y;
if(x!=y) printf("%llu",X);
printf("%llu\n",Y);
if(x%2!=y%2)
{
m=0;
while(Y)
{
b[++m]=Y%10;
Y/=10;
}
while(X)
{
b[++m]=X%10;
X/=10;
}
b[0]=m;
if(b[0] > Max[0])
for(int i=0; i<=b[0]; i++) Max[i]=b[i];
if(b[0]==Max[0])
{
for(int i=b[0]; i>=1 && b[i]==Max[i]; i--);
if(b[0]==Min[0])
{
for(int i=b[0]; i>=1 && b[i]==Min[i]; i--);
if(i>0 && b[i]<Min[i])
for(int i=0; i<=b[0]; i++) Min[i]=b[i];
}
}
}
return 0;
int main()
{
int n,i,gasit=0;
unsigned int s,dif,a,b,vmin,vmax,p,nr;
ifstream f("inventie.in");
ofstream g("inventie.out");
f>>n;
for (i=1; i<=n; i++)
{
f>>a>>b;
if (a==b) nr=a+b;
else
{
if (a>b) dif=a-b;
else dif=b-a;
s=a+b;
p=1;
while (s)
{
s=s/10;
p=p*10;
}
nr=dif*p+a+b;
}
g<<nr<<’\n’;
if (a%2!=b%2)
{
gasit=1;
vmin=vmax=nr;
break;
}
}
i++;
while (i<=n)
{
f>>a>>b; //g<<" am citit "<<a<<’ ’<<b<<"la pasul "<<i<<’\n’;
CAPITOLUL 23. ONI 2015 23.2. INVENTIE 291
if (a==b) nr=a+b;
else
{
if (a>b) dif=a-b;
else dif=b-a;
s=a+b;
p=1;
while (s)
{
s=s/10;
p=p*10;
}
nr=dif*p+a+b;
}
g<<nr<<’\n’;
if (a%2!=b%2)
{
if (vmin>nr) vmin=nr;
if (vmax<nr) vmax=nr;
}
i++;
}
if (gasit==0) g<<0<<’\n’;
else
g<<vmin<<’\n’<<vmax<<’\n’;
return 0;
}
int main()
{
int n,i,gasit=0;
unsigned long long s,dif,a,b,vmin,vmax,p,nr;
ifstream f("inventie.in");
ofstream g("inventie.out");
f>>n;
for (i=1; i<=n; i++)
{
f>>a>>b;
if (a==b) nr=a+b;
else
{
if (a>b) dif=a-b;
else dif=b-a;
s=a+b;
p=1;
while (s)
{
s=s/10;
p=p*10;
}
nr=dif*p+a+b;
}
g<<nr<<’\n’;
if (a%2!=b%2)
{
gasit=1;
vmin=vmax=nr;
break;
}
}
i++;
while (i<=n)
{
f>>a>>b; //g<<" am citit "<<a<<’ ’<<b<<"la pasul "<<i<<’\n’;
if (a==b) nr=a+b;
else
{
CAPITOLUL 23. ONI 2015 23.2. INVENTIE 292
if (a>b) dif=a-b;
else dif=b-a;
s=a+b;
p=1;
while (s)
{
s=s/10;
p=p*10;
}
nr=dif*p+a+b;
}
g<<nr<<’\n’;
if (a%2!=b%2)
{
if (vmin>nr) vmin=nr;
if (vmax<nr) vmax=nr;
}
i++;
}
if (gasit==0) g<<0<<’\n’;
else
g<<vmin<<’\n’<<vmax<<’\n’;
return 0;
}
ifstream f("inventie.in");
ofstream g("inventie.out");
int main()
{
f>>N;
nrmin[0]=40;
int i;
for(i=1;i<=N;i++)
{
f>>a>>b;
if(a>=b)c=a-b;
else c=b-a;
d=a+b;
if(c!=0)g<<c;
g<<d;
g<<’\n’;
if(a%2!=b%2)
{
int v[40]={0};
//adaug c in vector
CAPITOLUL 23. ONI 2015 23.2. INVENTIE 293
if(c!=0)
{
int nrc=0;
unsigned long long c1=c;
while(c1>0){nrc++;c1/=10;}
v[0]=nrc;
for(int ii=nrc;ii>=1;ii--)
{
v[ii]=c%10;
c/=10;
}
}
//completez cu d=a+b
int nrc=0;
unsigned long long d1=d;
while(d1>0){nrc++;d1/=10;}
v[0]+=nrc;
for(int ii=v[0];d>0;ii--){v[ii]=d%10;d/=10;}
if(compar(v,nrmin)==2)copie(nrmin,v);
if(compar(v,nrmax)==1)copie(nrmax,v);
}
}
if(nrmax[0]!=0)
{
int i;
for(i=1;i<=nrmin[0];i++)g<<nrmin[i];
g<<’\n’;
for(i=1;i<=nrmax[0];i++)g<<nrmax[i];
g<<’\n’;
}
else g<<0<<’\n’;
f.close();
g.close();
return 0;
}
ifstream f("inventie.in");
ofstream g("inventie.out");
char nrmin[40]="999999999999999999999999999999999999999",nrmax[40],v[40];
int main()
{
f>>N;
int i;
for(i=1;i<=N;i++)
{
f>>a>>b;
if(a>=b)c=a-b;
else c=b-a;
d=a+b;
if(c!=0)g<<c;
g<<d;
g<<’\n’;
if(a%2!=b%2)
{
//pun d in v oglindit
int nrc=0;
while(d>0){v[nrc++]=’0’+d%10;d/=10;}
CAPITOLUL 23. ONI 2015 23.2. INVENTIE 294
//pun c in v oglindit
if(c!=0)
{
while(c>0){v[nrc++]=’0’+c%10;c/=10;}
}
v[nrc]=0;
for(int j=0;j<strlen(v)/2;j++)
{
char aux=v[j];
v[j]=v[strlen(v)-j-1];
v[strlen(v)-j-1]=aux;
}
if(strlen(v)<strlen(nrmin)) strcpy(nrmin,v);
else
if(strlen(v)==strlen(nrmin) && strcmp(v,nrmin)<0)strcpy(nrmin,v);
if(strlen(v)>strlen(nrmax))strcpy(nrmax,v);
else
if(strlen(v)==strlen(nrmax) && strcmp(v,nrmax)>0)strcpy(nrmax,v);
}
}
if(nrmax[0]!=0) g<<nrmin<<’\n’<<nrmax<<’\n’;
else g<<0<<’\n’;
f.close();
g.close();
return 0;
}
int main()
{
int n,i,gasit=0;
long long s,dif,a,b,vmin,vmax,p,nr;
ifstream f("inventie.in");
ofstream g("inventie.out");
f>>n;
for (i=1; i<=n; i++)
{
f>>a>>b;
if (a==b) nr=a+b;
else
{
if (a>b) dif=a-b;
else dif=b-a;
s=a+b;
p=1;
while (s)
{
s=s/10;
p=p*10;
}
nr=dif*p+a+b;
}
g<<nr<<’\n’;
if (a%2!=b%2)
{
gasit=1;
vmin=vmax=nr;
break;
}
}
i++;
while (i<=n)
CAPITOLUL 23. ONI 2015 23.3. MESAJ 295
{
f>>a>>b; //g<<" am citit "<<a<<’ ’<<b<<"la pasul "<<i<<’\n’;
if (a==b) nr=a+b;
else
{
if (a>b) dif=a-b;
else dif=b-a;
s=a+b;
p=1;
while (s)
{
s=s/10;
p=p*10;
}
nr=dif*p+a+b;
}
g<<nr<<’\n’;
if (a%2!=b%2)
{
if (vmin>nr) vmin=nr;
if (vmax<nr) vmax=nr;
}
i++;
}
if (gasit==0) g<<0<<’\n’;
else
g<<vmin<<’\n’<<vmax<<’\n’;
return 0;
}
23.3 mesaj
Problema 3 - mesaj 100 de puncte
În ţara lui Piticot cuvintele au doar două litere, prima fiind o majusculă (literă mare) iar a
doua o minusculă (literă mică). Piticii Mi şi Gi se distrează şi ı̂şi trimit mesaje ascunzând cuvintele
ı̂n cadrul unor secvenţe transmise sub forma unor şiruri de litere.
Piticul Mi scrie şi trimite un mesaj piticului Gi respectând
următoarele reguli:
a un mesaj conţine una sau mai multe secvenţe;
a orice literă care apare ı̂n mesaj, de cel puţin două ori, pe poziţii
alăturate, este numită terminator;
a o secvenţă se ı̂ncheie când s-a ı̂ntâlnit o succesiune de litere ter-
minator;
a cuvântul este format din prima majusculă şi ultima minusculă din
secvenţă, fără a lua ı̂n seamă litera terminator a secvenţei; Figura 23.1: mesaj
a o secvenţă ascunde un cuvânt dacă terminatorul său se repetă de exact două ori şi dacă
conţine cel puţin o literă mare şi o literă mică, ignorând terminatorul de secvenţă;
a costul unui cuvânt este egal cu numărul total de apariţii al celor două litere din care este
format, ı̂n cadrul secvenţei ı̂n care a fost ascuns, luând ı̂n considerare inclusiv literele terminator.
De exemplu secvenţa s f u E e t R u E E ascunde un cuvânt deoarece conţine şi majuscule
şi minuscule, iar litera terminator de secvenţă, E, se repetă de exact două ori. Secvenţa ascunde
cuvântul Eu, iar costul cuvântului este 5 (3 litere E + 2 două litere u).
La primirea mesajului, piticul Gi determină, pentru fiecare majusculă, costul maxim al cuvin-
telor care ı̂ncep cu aceasta.
Cerinţe
Date de intrare
Fişierul de intrare mesaj.in conţine pe prima linie un număr natural P . Pentru toate testele
de intrare, numărul P poate avea numai una dintre valorile 1, 2 sau 3.
Pe a doua linie a fişierului de intrare se găseşte numărul natural N reprezentând numărul de
litere folosite de Mi pentru scrierea mesajului.
Pe a treia linie se găsesc N litere mari şi mici ale alfabetului englez, separate prin câte un
spaţiu, reprezentând literele mesajului, ı̂n ordinea ı̂n care au fost trimise.
Date de ieşire
Dacă valoarea lui P este 1, se va rezolva numai punctul 1) din cerinţe. În acest caz, fişierul de
ieşire mesaj.out va conţine pe prima linie un număr natural reprezentând răspunsul la cerinţa
1).
Dacă valoarea lui P este 2, se va rezolva numai punctul 2) din cerinţe. În acest caz, fişierul de
ieşire mesaj.out va conţine cuvintele din mesaj, fiecare cuvânt scris pe câte o linie, ı̂n ordinea ı̂n
care au fost trimise.
Dacă valoarea lui P este 3, se va rezolva numai punctul 3) din cerinţe. În acest caz, fişierul de
ieşire mesaj.out va conţine pe fiecare linie câte o majusculă urmată de un număr natural nenul,
separate printr-un spaţiu. Majusculele vor fi afişate ı̂n ordine de la A la Z, ı̂nsă doar cele pentru
care au existat ı̂n mesaj cuvinte care au ı̂nceput cu ele.
Exemple:
mesaj.in mesaj.out
1 4
34
wwwweDorFDorrtRneReyyjjiMoeitttjww
Explicaţie:
Textul conţine şase secvenţe: Sunt 4 secvenţe care nu ascund cuvinte:
1) w w w w a prima secvenţă şi a patra deoarece conţin numai
2) e D o r F D o r r terminatorul;
3) t R n e R e y y a secvenţa a cincea nu se decodifică deoarece termi-
4) j j natorul se repetă de mai mult de două ori;
5) i M o e i t t t a secvenţa a şasea nu conţine majuscule.
6) j w w
mesaj.in mesaj.out
2 Nu
34 Do
uNaaeDorFDorrtRneReyyjjiMoeitttjww Re
Explicaţie:
Textul conţine şase secvenţe: Prima secvenţă are terminatorul a care se repetă de
1) u N a a două ori şi ascunde cuvântul Nu
2) e D o r F D o r r A doua secvenţă are terminatorul r şi ascunde
3) t R n e R e y y cuvântul Do.
4) j j A treia are terminatorul y şi ascunde cuvântul Re.
5) i M o e i t t t Ultimele trei secvenţe nu ascund cuvinte.
6) j w w
CAPITOLUL 23. ONI 2015 23.3. MESAJ 297
mesaj.in mesaj.out
3 A2
24 B1
AattBbBtteAeannBwIIFieFF F1
Explicaţie:
Textul conţine cinci secvenţe: Cuvintele transmise ı̂n mesaj sunt
1) A a t t Aa (cost 2)
2) B b B t t Bb (cost 3)
3) e A e a n n Aa (cost 2)
4) B w I I Bw (cost 2)
5) F i e F F Fe (cost 4)
Costul maxim al cuvintelor care ı̂ncep cu A este 2 şi
au fost 2 cuvinte transmise.
Pentru litera B s-a transmis un singur cuvânt de cost
maxim 3.
Pentru litera F s-a transmis un singur cuvânt de cost
maxim 4.
La finalul unei secvenţe se actualizează dacă este cazul, costul maxim al unui cuvânt care
ı̂ncepe cu majuscula din cuvântului determinat la pasul curent.
Dacă se optează pentru preluarea literelor ı̂ntr-un vector de 1 milion de caractere, se vor obţine
50 de puncte.
22 if(islower(y)) fL[y-’a’]++;
23
24 while (x!=y && s!=’\n’)
25 {
26 if(islower(x)) last=x;
27 else
28 if(first==’#’) {first=x; nM=1;}
29 else
30 if(first==x) nM++;
31
32 x=y;
33 scanf("%c%c", &y, &s);
34 if(islower(y)) fL[y-’a’]++;
35 if(s==’\n’) break;
36 }
37
38 if (x==y) l=2;
39 while (x==y && s!=’\n’)
40 {
41 scanf("%c%c", &y, &s);
42 if(islower(y)) fL[y-’a’]++;
43 if(x==y) l++;
44 if(s==’\n’) break;
45 }
46
47 if(first==x) nM+=l;
48 if(l==2 && first!=’#’ && last!=’#’)
49 {
50 if(P==2) printf("%c%c\n",first,last);
51 Cost=nM + fL[last-’a’];
52 if(last==y)Cost--;
53 if(Cost==CostMax[first-’A’]) fC[first-’A’]++;
54 if(Cost>CostMax[first-’A’])
55 {
56 fC[first-’A’]=1;
57 CostMax[first-’A’]=Cost;
58 }
59 }
60 else Nrsecv++;
61
62 x=y;
63 l=1;
64 first=last=’#’;
65 nM=0;
66 for(i=0;i<27;i++) fL[i]=0;
67 Cost=0;
68 if(islower(x)) fL[x-’a’]++;
69 }
70
71 if(P==1)printf("%d\n", Nrsecv);
72 if(P==3)
73 for(i=0;i<26;i++)
74 if(fC[i]) printf("%c %d\n", (char)(’A’+i), fC[i]);
75
76 return 0;
77 }
int main()
{
freopen("mesaj.in", "r",stdin);
freopen("mesaj.out","w",stdout);
scanf("%d\n",&P);
scanf("%d\n%c%c",&N, &x, &s);
CAPITOLUL 23. ONI 2015 23.3. MESAJ 299
if(islower(x)) fL[x-’a’]++;
l=1;
first=last=’#’;
while(s!=’\n’)
{
scanf("%c%c", &y, &s);
if(islower(y)) fL[y-’a’]++;
while (x!=y && s!=’\n’)
{
if(islower(x)) last=x;
else
if(first==’#’) {first=x; nM=1;}
else if(first==x) nM++;
x=y;
scanf("%c%c", &y, &s);
if(islower(y)) fL[y-’a’]++;
if(s==’\n’) break;
}
if (x==y) l=2;
while (x==y && s!=’\n’)
{
scanf("%c%c", &y, &s);
if(islower(y)) fL[y-’a’]++;
if(x==y) l++;
if(s==’\n’) break;
}
if(first==x) nM+=l;
if(l==2 && first!=’#’ && last!=’#’)
{
if(P==2) printf("%c%c\n",first,last);
Cost=nM + fL[last-’a’];
if(last==y)Cost--;
if(Cost==CostMax[first-’A’]) fC[first-’A’]++;
if(Cost>CostMax[first-’A’])
{
fC[first-’A’]=1;
CostMax[first-’A’]=Cost;
}
}
else Nrsecv++;
x=y;
l=1;
first=last=’#’;
nM=0;
for(int i=0;i<27;i++)fL[i]=0;
Cost=0;
if(islower(x)) fL[x-’a’]++;
}
if(P==1)printf("%d\n", Nrsecv);
if(P==3)
for(i=0;i<26;i++)
if(fC[i]) printf("%c %d\n", (char)(’A’+i), fC[i]);
return 0;
}
ifstream in("mesaj.in");
ofstream out("mesaj.out");
int majCounts[256];
int minCounts[256];
int maxCost[256];
int maxCostCounts[256];
CAPITOLUL 23. ONI 2015 23.3. MESAJ 300
int main()
{
int P;
in >> P;
int N;
in >> N;
int numSecvente = 0;
int numSecventeCuCuvinte = 0;
char ch = ’#’;
int countCh = 1;
if (ch == peekCh)
{
countCh ++;
}
else
{
switch (countCh)
{
case 1:
switch (P)
{
case 1:
if (isupper(ch) && majCh == ’#’) majCh = ch;
if (islower(ch)) minCh = ch;
break;
case 2:
if (isupper(ch) && majCh == ’#’) majCh = ch;
if (islower(ch)) minCh = ch;
break;
case 3:
if (isupper(ch) && majCh == ’#’) majCh = ch;
if (islower(ch)) minCh = ch;
case 2:
switch(P)
{
case 1:
numSecvente ++;
if (majCh != ’#’ && minCh != ’#’)
numSecventeCuCuvinte ++;
break;
case 3:
if (isupper(ch)) majCounts[ch] += 2;
if (islower(ch)) minCounts[ch] += 2;
default:
switch (P)
{
case 1:
numSecvente ++;
countCh = 1;
ch = peekCh;
}
}
switch(P)
{
case 1:
out << numSecvente - numSecventeCuCuvinte << ’\n’;
break;
case 3:
for (char ch = ’A’; ch != ’Z’; ++ ch)
{
if (maxCost[ch])
{
out << ch << ’ ’ << maxCostCounts[ch] << ’\n’;
}
}
break;
}
return 0;
}
char pr[500000];
char ul[500000];
int main()
{
ifstream f("mesaj.in");
ofstream g("mesaj.out");
f>>p>>n;
f>>c;
while (i<=n-1)
{
for (j=0; j<=27; j++) nrmici[j]=nrmari[j]=0;
u=c;
if (u>=’a’ && u<=’z’) nrmici[u-’a’]++;
else nrmari[u-’A’]++;
f>>c;
i++;
while (c!=u&&i<=n)
{
if (c>=’a’ && c<=’z’) nrmici[c-’a’]++;
else nrmari[c-’A’]++;
if (u>=’a’&&u<=’z’)
{
nrlitmici++;
ultima=u;
}
else
{
nrlitmari++;
if (nrlitmari==1) prima=u;
}
if (i==n)
{
i++;
break;
}
u=c;
f>>c;
i++;
}
while (c==u&&i<=n)
{
if (c>=’a’ && c<=’z’) nrmici[c-’a’]++;
else nrmari[c-’A’]++;
nr++;
if (i==n)
{
i++;
break;
}
f>>c;
i++;
}
costmax[prima-’A’]=nrmari[prima-’A’]+nrmici[ultima-’a’];
cate[prima-’A’]=1;
}
else
if (costmax[prima-’A’]==nrmari[prima-’A’]+nrmici[ultima-’a’])
cate[prima-’A’]++;
}
else { ns++;}
nr=0;
nrlitmici=0;
nrlitmari=0;
}
if (p==2)
for(i=0; i<kp; i++) g<<pr[i]<<ul[i]<<’\n’;
else
if (p==1)
g<<ns<<’\n’;
else
for (c=’A’; c<=’Z’; c++)
if (costmax[c-’A’]>0) g<<c<<’ ’<<cate[c-’A’]<<’\n’;
return 0;
}
ifstream in("mesaj.in");
ofstream out("mesaj.out");
char prim[100000],ultim[100000];
int lmici[28],lmari[28],cost[28]={0};
int main()
{
char x,y;
int i,j,P,N,nrsv=0,sw=1,nrt=0,nrs=0,cost=0,cost_max[28]={0},nrc[28]={0};
char prima_M=’*’,ultima_m=’*’;
in>>P;
in>>N;
in>>x;
i=1;
while(i<=N)
{
for(j=0;j<=28;j++)
lmari[j]=lmici[j]=0;
in>>y;
i++;
while(x!=y && i<=N)
{
if(’a’<=x && x<=’z’)
ultima_m=x;
else
if(sw)
prima_M=x,sw=0;
x=y;
in>>y; i++;
}
nrt=1;
while(x==y && i<=N)
{
nrt++;
if(’a’<=y && y<=’z’)
lmici[y-’a’]++;
else
lmari[x-’A’]++;
x=y;
in>>y;
i++;
}
in.close();
out.close();
return 0;
}
ifstream in("mesaj.in");
ofstream out("mesaj.out");
int majCounts[256];
int minCounts[256];
int maxCost[256];
int maxCostCounts[256];
int main()
{
int P;
in >> P;
CAPITOLUL 23. ONI 2015 23.3. MESAJ 305
int N;
in >> N;
int numSecvente = 0;
int numSecventeCuCuvinte = 0;
char ch = ’#’;
int countCh = 1;
if (ch == peekCh)
{
countCh ++;
}
else
{
switch (countCh)
{
case 1:
switch (P)
{
case 1:
if (isupper(ch) && majCh == ’#’) majCh = ch;
if (islower(ch)) minCh = ch;
break;
case 2:
if (isupper(ch) && majCh == ’#’) majCh = ch;
if (islower(ch)) minCh = ch;
break;
case 3:
if (isupper(ch) && majCh == ’#’) majCh = ch;
if (islower(ch)) minCh = ch;
case 2:
switch(P)
{
case 1:
numSecvente ++;
if (majCh != ’#’ && minCh != ’#’)
numSecventeCuCuvinte ++;
{
int cost = majCounts[majCh]+minCounts[minCh];
if (cost > maxCost[majCh])
{
maxCost[majCh] = cost;
maxCostCounts[majCh] = 1;
}
else
if (cost == maxCost[majCh])
{
maxCostCounts[majCh] ++;
}
}
default:
switch (P)
{
case 1:
numSecvente ++;
countCh = 1;
ch = peekCh;
}
}
switch(P)
{
case 1:
out << numSecvente - numSecventeCuCuvinte << ’\n’;
break;
case 3:
for (char ch = ’A’; ch != ’Z’; ++ ch)
{
if (maxCost[ch])
{
out << ch << ’ ’ << maxCostCounts[ch] << ’\n’;
}
}
break;
}
return 0;
}
ifstream f("mesaj.in");
ofstream g("mesaj.out");
char s[1000001],minu,maju;
int N,P,nr;//nr=nr de repetari ale unei litere
CAPITOLUL 23. ONI 2015 23.3. MESAJ 307
int main()
{
//citire
int i;
f>>P>>N;
for(i=1;i<=N;i++)f>>s[i];
for(i=2;i<=N;)
{
if(s[i]!=s[i-1])
{
if(s[i]>=’A’ && s[i]<=’Z’ && s[i]!=s[i+1] && maju==’ ’)
maju=s[i];
else
if(s[i]>=’a’ && s[i]<=’z’ && s[i]!=s[i+1])
minu=s[i];
i++;
}
else
{
//se termina o secventa
nrs++;
nr=0;
while(s[i]==s[i-1] && i<=N)
{
i++;
nr++;
}
if(maju!=’ ’ && minu!=’ ’ && nr==1)
nrsl++;
maju=minu=’ ’;
}
}
g<<nrs-nrsl<<’\n’;
}
//2)afisare cuvinte
if(P==2)
{
maju=minu=’ ’;
if(s[1]>=’A’ && s[1]<=’Z’ && s[1]!=s[2] && maju==’ ’)
maju=s[1];
else
if(s[1]>=’a’ && s[1]<=’z’ && s[1]!=s[2])
minu=s[1];
for(i=2;i<=N;)
{
if(s[i]!=s[i-1])
{
if(s[i]>=’A’ && s[i]<=’Z’ && s[i]!=s[i+1] && maju==’ ’)
maju=s[i];
else
if(s[i]>=’a’ && s[i]<=’z’ && s[i]!=s[i+1])
minu=s[i];
i++;
}
else
{
//se termina o secventa
nrs++;nr=0;while(s[i]==s[i-1] && i<=N){i++;nr++;}
if(maju!=’ ’ && minu!=’ ’ && nr==1)g<<maju<<minu<<’\n’;
maju=minu=’ ’;
}
}
CAPITOLUL 23. ONI 2015 23.3. MESAJ 308
//3)afisare cuvinte
if(P==3)
{
int j=1,k;
maju=minu=’ ’;
if(s[1]>=’A’ && s[1]<=’Z’ && s[1]!=s[2] && maju==’ ’)
maju=s[1];
else
if(s[1]>=’a’ && s[1]<=’z’ && s[1]!=s[2])
minu=s[1];
for(i=2;i<=N;)
{
if(s[i]!=s[i-1])
{
if(s[i]>=’A’ && s[i]<=’Z’ && s[i]!=s[i+1] && maju==’ ’)
maju=s[i];
else
if(s[i]>=’a’ && s[i]<=’z’ && s[i]!=s[i+1])
minu=s[i];
i++;
}
else
{
//se termina o secventa
nrs++;
cost=0;
nr=0;
while(s[i]==s[i-1] && i<=N){i++; nr++;}
if(maju!=’ ’ && minu!=’ ’ && nr==1)
{
for(k=j;k<=i-1;k++)
if(s[k]==maju)cost++;
else
if(s[k]==minu)cost++;
if(cost>cmax[maju-’A’])
{
cmax[maju-’A’]=cost;
nrap[maju-’A’]=1;
}
else
if(cost==cmax[maju-’A’])
{
nrap[maju-’A’]++;
}
}
maju=minu=’ ’;j=i;
}
}
for(i=0;i<26;i++)
if(cmax[i]>0) g<<(char)(i+’A’)<<’ ’<<nrap[i]<<’\n’;
}
f.close();g.close();return 0;
}
ONI 2014
24.1 2048
Problema 1 - 2048 100 de puncte
Ada şi Ben sunt pasionaţi de jocurile pe calculator şi tocmai au descoperit cea mai recentă
versiune a jocului 2048.
Regulile jocului sunt foarte simple:
a se porneşte de la un şir de N piese pe care sunt
ı̂nscrise numere din mulţimea { 2, 4, 8, 16, 32, 64, 128,
256, 512, 1024, 2048 };
a piesele sunt aşezate ı̂n locaţii numerotate consecu-
tiv cu numerele 1, 2, ..., N ;
a la fiecare pas, poate avea loc o MUTARE la
STÂNGA sau o MUTARE la DREAPTA;
a pentru fiecare joc este stabilit un număr maxim de
mutări M ;
a dacă are loc o MUTARE la DREAPTA, atunci:
- piesele pot fuziona la dreapta, ı̂ncepând cu penul-
tima piesă din şir: dacă o piesă se află pe o poziţie i şi
are ı̂nscrisă valoarea k, iar pe poziţia i 1 se află o piesă
cu aceeaşi valoare k, atunci aceste piese vor ”fuziona”, Figura 24.1: 2048
pe poziţia i 1 se va obţine o piesă cu valoarea 2k, iar pe poziţia i rămâne o locaţie liberă;
- după efectuarea fuzionărilor, piesele se aliniază la dreapta, astfel ı̂ncât ultima piesă să se afle
pe poziţia n;
a dacă are loc o MUTARE la STâNGA, atunci:
- piesele pot fuziona la stânga, ı̂ncepând cu a doua piesă din şir: dacă o piesă se află pe o
poziţie i şi are ı̂nscrisă valoarea k, iar pe poziţia i 1 se află o piesă cu aceeaşi valoare k, atunci
aceste piese vor ”fuziona”, pe poziţia i 1 se va obţine o piesă cu valoarea 2k, iar pe poziţia i
rămâne o locaţie liberă;
- după efectuarea fuzionărilor, piesele se aliniază la stânga, astfel ı̂ncât prima piesă să se afle
pe poziţia 1;
a jocul se ı̂ncheie atunci când se ajunge ı̂n una dintre următoarele situaţii:
- pe cel puţin una dintre piese se află ı̂nscrisă valoarea 2048;
- valorile ı̂nscrise nu se mai pot modifica prin mutarea pieselor;
- s-au efectuat toate cele M mutări.
Cerinţe
Scrieţi un program care să citească numerele naturale N (numărul iniţial de piese) şi M
(numărul maxim de mutări), un şir de N numere reprezentând, ı̂n ordine, numerele ı̂nscrise pe
cele N piese şi cel mult M caractere din mulţimea rS, Dx ce reprezintă mutările fixate de către
Ada şi Ben, şi care determină:
309
CAPITOLUL 24. ONI 2014 24.1. 2048 310
Date de intrare
Fişierul de intrare 2048.in conţine pe prima linie, separate prin câte un spaţiu, numerele N
şi M . A doua linie a fişierului conţine cele N numere inscrise, ı̂n ordine, pe piese, separate prin
câte un spaţiu. A treia linie a fişierului conţine cele M caractere, separate prin câte un spaţiu, ce
reprezintă cele M direcţii de mutare.
Date de ieşire
Fişierul de ieşire 2048.out va conţine pe prima linie numărul X, pe a doua linie numărul Y
şi pe a treia linie numărul Z.
Exemple
2048.in 2048.out Explicaţii
7 10 4 Succesiunea de mutări este reprezentată ı̂n figura 1.
16 4 4 2 2 4 8 32 Au fost efectuate 4 mutări până la ı̂ncheierea jocului, cea
DDSDSDSSDD 2 mai mare valoare inscrisă pe una dintre piese fiind 32.
Numărul maxim de fuzionări, două, a fost obţinut la prima
mutare.
ifstream f("2048.in");
ofstream g("2048.out");
int v[10001],n,m,i,j,k,st,dr,p,X,Y,Z,z,s;
char d;
int main()
{
f>>n>>m;
for(i=1;i<=n;++i){f>>v[i]; if(v[i]==2048) s=1;}
CAPITOLUL 24. ONI 2014 24.1. 2048 311
st=1;dr=n;
for(i=1;i<=m && !s;i++)
{ f>>d;
z=0;
if(d==’D’)
{for(j=dr;j>st;j--)
if(v[j]==v[j-1]) {v[j]*=2;
if(v[j]==2048) s=1;
for(k=j-1;k>st;k--)v[k]=v[k-1];
st++;
z++;
}
}
else
{ for(j=st;j<dr;j++)
if(v[j]==v[j+1]){ v[j]*=2;
if(v[j]==2048) s=1;
for(k=j+1;k<dr;k++)v[k]=v[k+1];
dr--;
z++;
}
}
X=i;
if(z==0) X=i-1,i=m;
Z=max(Z,z);
if(s)i=m;
}
Y=v[st];
for(i=st+1;i<=dr;i++) Y=max(Y,v[i]);
g<<X<<’\n’<<Y<<’\n’<<Z<<’\n’;
f.close();g.close();
return 0;
}
ifstream f("2048.in");
ofstream g("2048.out");
int p[10001],n,m,k,i,ii,nrfuz,x,y,z,j,in,sf,mutat,gata,P;
char d,ud;
int main()
{
//citire
f>>n>>m;
for(i=1;i<=n;i++){f>>p[i];if(p[i]==2048){gata=1;y=2048;}}
in=1;sf=n;
for(i=1;i<=m && !gata;i++)
{
f>>d;nrfuz=0;mutat=0;
if(d==’D’)
{for(j=sf;j>in;j--)
if(p[j]==p[j-1])
{
nrfuz++;mutat=1;if(P>=in && P<=j-1)P++;
p[j]*=2;
for(k=j-1;k>in;k--)p[k]=p[k-1];
in++;
}
}
else
{for(j=in;j<sf;j++)
if(p[j]==p[j+1])
{
nrfuz++;mutat=1;if(P<=sf && P>=j+1)P--;
CAPITOLUL 24. ONI 2014 24.1. 2048 312
p[j]*=2;
for(k=j+1;k<sf;k++)p[k]=p[k+1];
sf--;
}
}
if(nrfuz>z)z=nrfuz;
if(!mutat)gata=1;else ud=d,x++;
for(ii=in;ii<=sf;ii++)
if(p[ii]>y)y=p[ii];
if(y==2048)gata=1;
}
if(ud==’D’)P=P+n-sf;
else P=P-(in-1);
g<<x<<endl<<y<<endl<<z<<endl;
f.close();g.close();return 0;
return 0;
}
int n,i,j,v[10010],p[12],x,y,z,m,k,f=1;
char c;
int main()
{
x=y=z=0;
ifstream fin("2048.in");
ofstream fout("2048.out");
fin>>n>>m;
for(i=1;i<=n;i++)
{fin>>v[i];
k=0;x=v[i];
while(x>1) x>>=1,k++;
p[k]++;
}
x=0;
while(x<m&&!p[11]&&f)
{ x++;
fin>>c;
if(c==’S’)
{
f=0;
for(i=2;i<=n;)
if(v[i]==v[i-1])
{v[i-1]*=2;
k=0;f++;
while(v[i]>1) v[i]>>=1,k++;
p[k]-=2;p[k+1]++;
for(j=i;j<n;j++)
v[j]=v[j+1];
n--;i++;
}
else i++;
if(f>z)z=f;
}
else
{
f=0;
for(i=n-1;i>=1;i--)
if(v[i]==v[i+1])
{v[i]*=2;
k=0;f++;
CAPITOLUL 24. ONI 2014 24.1. 2048 313
while(v[i+1]>1) v[i+1]>>=1,k++;
p[k]-=2;p[k+1]++;
for(j=i+1;j<n;j++)
v[j]=v[j+1];
n--;i--;
}
if(f>z)z=f;
}
if(p[11]) y=2048;
else
{
for(i=11;!p[i];i--);
y=1<<i;
}
if(!f)x--;
fout<<x<<’\n’<<y<<’\n’<<z<<’\n’;
fin.close();
fout.close();
return 0;
}
int main()
{
ifstream f("2048.in");
ofstream g("2048.out");
f>>N>>M;f>>a[1];
f>>c;
x++;Z=0;
if(c==’D’)
{ int q=N;
for(j=N;j>1;j--)
if(a[j]==a[j-1])
{ a[j]=2*a[j];if(a[j]==2048) gata=1;
for(k=j-1;k<N;k++) a[k]=a[k+1];
q--;Z++;j--; }
if(q==N) {gata=1;x--;} else N=q;
}
else
{ int q=N;
for(j=1;j<N;j++)
if(a[j]==a[j+1])
{ a[j]=2*a[j];if(a[j]==2048)gata=1;
for(k=j+1;k<N;k++) a[k]=a[k+1];
N--;Z++;
}
if(q==N) {x--;gata=1;}
CAPITOLUL 24. ONI 2014 24.1. 2048 314
if(z<Z) z=Z;
}
Y=a[1];N++;
for(i=1;i<=N;i++)
{
if(a[i]>Y) Y=a[i];
}
g<<x<<endl<<Y<<endl<<z<<endl;
f.close();
g.close();
return 0;
}
ifstream fin("2048.in");
ofstream fout("2048.out");
int n,m,a[10001],i,x,y,z,st,dr,nr,k,j,p,sch;
char c,uc,uuc;
int main()
{
fin>>n>>m;
for(i=1;i<=n;i++)
fin>>a[i];
x=y=z=0;
for(j=1;j<=n;j++)
y=max(y,a[j]);
if(y!=2048)
{x=y=z=0;
st=1;dr=n;
for(i=1;i<=m;i++)
{
fin>>c;
nr=0;
x++;
if(c==’S’)
{
for(j=st;j<dr;j++)
if(a[j]==a[j+1])
{
a[j]=2*a[j];nr++;
if(j+1==p)p--,sch=1;
else sch=0;
for(k=j+1;k<dr;k++)
{
a[k]=a[k+1];
if(k+1==p&&!sch){p--;sch=1;}
}
dr--;
}
z=max(z,nr);
}
else
{
for(j=dr;j>st;j--)
if(a[j]==a[j-1])
{
a[j]=2*a[j];nr++;
if(j-1==p)p++,sch=1;
CAPITOLUL 24. ONI 2014 24.1. 2048 315
else sch=0;
for(k=j-1;k>=st;k--)
{
a[k]=a[k-1];
if(k-1==p&&sch==0){p++;sch=1;}
}
st++;
}
z=max(z,nr);
}
if(nr==0)x--;
for(j=1;j<=n;j++)
y=max(y,a[j]);
if(nr==0)uuc=uc;
else uuc=c;
if(y==2048||nr==0)break;
uc=c;
}
}
fout<<x<<’\n’<<y<<’\n’<<z<<’\n’;
fout.close();
return 0;
}
int a[10001], n, m;
char d;
ifstream f("2048.in");
ofstream g("2048.out");
int main()
{
int i, nr=0, p, u, k, max=0, nrf, nrm=0;
bool ok=1, e2048=0;
f>>n>>m;
for(i=1;i<=n;i++){f>>a[i];if(a[i]>nrm)nrm=a[i];}
if(nrm==2048)e2048=1,ok=0;
p=1; u=n;
while(ok)
{
f>>d; nr++;
nrf=0;
if(d==’S’)
{
k=p;
for(i=p;i<u;i++)
if(a[i]==a[i+1]) {a[k++]=2*a[i]; i++; nrf++; if(a[k-1]>nrm)nrm=a[k-1];}
else a[k++]=a[i];
if(i==u)a[k++]=a[i];
u=k-1;
}
else
{
k=u;
for(i=u;i>p;i--)
if(a[i]==a[i-1]) {a[k--]=2*a[i]; i--; nrf++;if(a[k+1]>nrm)nrm=a[k+1];}
else a[k--]=a[i];
CAPITOLUL 24. ONI 2014 24.2. BABILON 316
if(i==p) a[k--]=a[i];
p=k+1;
}
if(nrm==2048)e2048=1;
if(nrf==0)ok=0;
else if(nrf>max)max=nrf;
if(nr==m)ok=0;
if(e2048==1)ok=0;
//for(i=p;i<=u;i++)g<<a[i]<<’ ’;g<<’\n’;
}
if(nr==m or e2048==1)
g<<nr<<’\n’;
else
g<<nr-1<<’\n’;
g<<nrm<<’\n’<<max<<’\n’;
f.close();
g.close();
return 0;
}
24.2 babilon
Problema 2 - babilon 100 de puncte
Babilonienii au dezvoltat un sistem poziţional de scriere a numerelor, ı̂n care orice număr
natural se poate reprezenta utilizând semnele (unu), (zece) şi spaţii.
Valorile k " r2, 3, ..., 9x se obţin scriind semnul de k ori (scrierea babiloniană a lui 3 este
).
Numerele 11, 12, ..., 59 se obţin ca succesiuni de semne urmate de semne (43 se reprezintă
ca ).
Sistemul foloseşte gruparea unităţilor câte şaizeci. Astfel, pentru a scrie umărul şaizeci se
foloseşte acelaşi semn ca pentru unu, dar valoarea sa este dată de poziţia ı̂n care se găseşte semnul
.
Babilonienii nu foloseau cifra 0. Pentru poziţionarea corectă a semnelor se utiliza spaţiu
(60 se reprezintă ca , 3600 se reprezintă ca etc.).
Se codifică scrierea babiloniană a unui număr utilizând cifra 1 ı̂n locul semnului , cifra 2 ı̂n
locul semnului şi cifra 3 ı̂n loc de spaţiu, ca ı̂n exemplele de mai jos:
Scrierea
babiloniană
Codificarea 1311 12 1221111 123111
scrierii
babiloniene
Valoarea 1*60+2=62 1*60+10=70 1*60+20+4=84 1*60*60+10*60+3=4203
zecimală
a numărului
Cerinţe
Dându-se un număr natural n şi un şir de n cifre din mulţimea r1, 2, 3x, reprezentând codificarea
scrierii babiloniene a unui număr natural, să se determine:
CAPITOLUL 24. ONI 2014 24.2. BABILON 317
a) numărul maxim de cifre 1 aflate pe poziţii consecutive ı̂n codificarea scrierii babiloniene
date;
b) numărul natural din sistemul zecimal corespunzător scrierii babiloniene date.
Date de intrare
Date de ieşire
Dacă valoarea lui p este 1, atunci se va rezolva numai punctul a) din cerinţă. În acest caz,
fişierul de ieşire babilon.out va conţine pe prima linie un număr natural reprezentând numărul
maxim de cifre 1 aflate pe poziţii consecutive ı̂n codificarea scrierii babiloniene date.
Dacă valoarea lui p este 2, atunci se va rezolva numai punctul b) din cerinţă. În acest caz,
fişierul de ieşire babilon.out va conţine pe prima linie numărul natural corespunzător scrierii
babiloniene date.
2 & n & 10 ;
9
a
a se garantează faptul că numărul de cifre al rezultatului de la punctul b) (numărul zecimal)
este mai mic decât 20;
a 30% din teste vor avea pe prima linie valoarea 1, iar restul de 70% din teste vor avea pe
prima linie valoarea 2.
Exemple
Punctul a):
Se citesc pe rând valorile din fişier, se determină lungimea fiecărei secvenţe de cifre 1 şi se
reţine lungimea maximă.
Punctul b):
Se citeşte prima cifră şi se iniţializează o variabilă z cu 1 dacă cifra este 1 (corespunzător
semnului ), respectiv cu 10 dacă este egală cu 2 (corespunzător semnului ). Se continuă
citirea câte unei cifre şi la ı̂ntâlnirea cifrei 3 (corespunzătoare unui spaţiu ı̂n scrierea babiloniană)
sau a cifrei 2 precedată de o cifră 1 (ignorând eventualele cifre 3 corespunzătoare spaţiilor) valoarea
z se ı̂nmulţeşte cu 60. Pentru fiecare cifră 1 ı̂ntâlnită, z se incrementează cu 1, iar pentru fiecare
cifră 2, se incrementează cu 10.
ifstream f("babilon.in");
ofstream g("babilon.out");
int main()
{
long long z=0;
unsigned i, fr, fmax;
f>>v>>n;
if(v==1)
{
f>>a;
fmax=fr=a==1;
for(i=2;i<=n;i++)
{
f>>b;
if(a*b==1) fr++;
else
{
if (fr>fmax) fmax=fr;
fr=b==1;
}
a=b;
}
if (fr>fmax) fmax=fr;
g<<fmax<<’\n’;
}
else
{
f>>a;
if(a==1)z=1;
else
if(a==2)z=10;
else z=0;
for(i=2;i<=n;i++)
{
f>>b;
if (b>a) z=z*60;
if(b==1)z++;
else if(b==2)z+=10;
if (b!=3) a=b;
}
CAPITOLUL 24. ONI 2014 24.2. BABILON 319
g<<z<<’\n’;
}
f.close();
g.close();
return 0;
}
ifstream f("babilon.in");
ofstream g("babilon.out");
int var,n,i,c[121],l,lmax,prec;
long long nrb;
int main()
{
//citire-prelucare
f>>var>>n;
for(i=1;i<=n;i++) f>>c[i];
if(var==1)
{
for(i=1;i<=n;i++)
{
if(c[i]==1) l++;
else {if(l>lmax) lmax=l;
l=0;
}
}
{if(l>lmax) lmax=l;l=0;} g<<lmax<<endl;
}
else
{
for(i=1;i<=n;i++)
if(c[i]==1) nrb++,prec=c[i];
else if(c[i]==3) nrb*=60;
else {
if(prec==1)nrb*=60;
nrb+=10;prec=c[i];
}
g<<nrb<<endl;
}
return 0;
}
ifstream f("babilon.in");
ofstream g("babilon.out");
long long r;
int v,n,i,c,a,k1,k;
int main()
{ f>>v>>n;
for(i=1;i<=n;++i)
{ f>>c;
switch(c)
{case 1: r++,a=c,k++,k1=max(k,k1);break;
case 2: if(a==1) r*=60;r+=10,a=c,k=0;break;
default:r*=60,k=0;
}
}
CAPITOLUL 24. ONI 2014 24.2. BABILON 320
if(v==1)g<<k1<<’\n’;
else g<<r<<’\n’;
f.close();
g.close();
return 0;
}
ifstream fin("babilon.in");
ofstream fout("babilon.out");
int n, c1,c2,i,x,caz,nr1,nrmax;
long long nr;
char c;
int main()
{
fin>>caz;
if(caz==1)
{
fin>>n;nr1=0;
for(i=1;i<=n;i++)
{
fin>>c;c1=c-’0’;
if(c1==1)nr1++;
else
{
if(nr1>nrmax)nrmax=nr1;
nr1=0;
}
}
if(nr1>nrmax)nrmax=nr1;
fout<<nrmax<<’\n’;
}
else
{
fin>>n>>c;
nr=nr1=0;
c1=c-’0’;
if(c1==1){nr1++;x=1;}
else x=10;
for(i=2;i<=n;i++)
{
fin>>c;
c2=c-’0’;
if(c2==1)
{x++;nr1++;}
else
if(c2==2)
{
if(c1==2)x=x+10;
else
if(nr1)
{
nr=nr*60+x;//fout<<x<<’ ’<<nr<<’\n’;
x=10;
nr1=0;
}
else x=10;
}
else
{
nr=nr*60+x;//fout<<x<<’ ’;
x=0;
}
c1=c2;
}
nr=nr*60+x;
fout<<nr<<’\n’;
CAPITOLUL 24. ONI 2014 24.3. IEPURASI 321
}
fout.close();
return 0;
}
24.3 iepurasi
Problema 3 - iepurasi 100 de puncte
Se construieşte un şir de numere naturale care
respectă restricţiile:
- primul număr din şir este 9;
- numerele se generează ı̂n ordine strict
crescătoare;
- şirul conţine toate numerele formate doar cu
cifrele 7, 8 şi 9 cu proprietatea că numărul cifrelor
9 este mai mare sau egal decât numărul cifrelor 8
şi numărul cifrelor 8 este mai mare sau egal decât
numărul cifrelor 7.
Primii 14 termeni ai şirului, ı̂n ordine, sunt: 9,
89, 98, 99, 789, 798, 879, 897, 899, 978, 987, 989, Figura 24.2: iepurasi
998, 999.
Pornind de la aceste numere, Liv a inventat un joc interactiv: N iepuraşi sunt aşezaţi ı̂n şir,
fiecare având câte un cartonaş. Fiecare cartonaş are două feţe, o faţă albă pe care este inscripţionat
un număr din acest şir şi o faţă gri, pe care este inscripţionată poziţia acelui număr ı̂n şir, poziţii
numerotate ı̂n ordine, ı̂ncepând cu valoarea 14.
Exemple. Cartonaşul care are pe faţa gri inscripţionat numărul 1 va avea pe faţa albă
inscripţionat numărul 9, iar cartonaşul care are pe faţa gri inscripţionat numărul 5 va avea pe faţa
albă inscripţionat numărul 789.
Iepuraşii sunt aşezaţi ı̂ntr-o ordine oarecare şi ţin cartonaşele astfel ı̂ncât să se vadă faţa
gri. Jocul constă ı̂n a rearanja iepuraşii de la stânga la dreapta, descrescător după numerele
inscripţionate pe feţele gri, având la dispoziţie doar operaţia T AP pe un iepuraş. Când se aplică
operaţia T AP unui iepuraş atunci secvenţa de iepuraşi, ı̂ncepând de la cel pe care s-a făcut T AP şi
până la sfârşitul şirului (spre dreapta), este oglindită (ca ı̂n imaginea de mai sus). După oglindire,
toţi iepuraşii din acea secvenţă ţin cartonaşele astfel ı̂ncât să se vadă faţa albă. Se doreşte aplicarea
unui număr cât mai mic de operaţii T AP pentru rearanjarea iepuraşilor.
Cerinţe
Scrieţi un program care să citească numerele naturale N (reprezentând numărul de iepuraşi) şi
a1 , a2 , ..., aN (reprezentând, ı̂n ordine, numerele inscripţionate pe feţele gri) şi care să determine:
a) Numărul minim de operaţii T AP necesare rearanjării iepuraşilor;
b) Cel mai mic număr aflat pe o faţă albă care nu se vede, ı̂n cazul ı̂n care au rămas cartonaşe
neı̂ntoarse. Dacă toate cartonaşele au fost ı̂ntoarse (la toate fiind vizibilă faţa albă) se va afişa cel
mai mare număr aflat pe o faţă albă a unui cartonaş.
Date de intrare
Fişierul de intrare iepurasi.in conţine pe prima linie numărul natural N reprezentând numărul
de iepuraşi. A doua linie a fişierului conţine, ı̂n ordine, cele N numere: a1 , a2 , ...,aN , separate
prin câte un spaţiu, reprezentând ı̂n ordine, numerele inscripţionate pe feţele gri ale cartonaşelor.
Date de ieşire
Fişierul de ieşire iepurasi.out va conţine pe prima linie un număr reprezentând numărul
minim de operaţii T AP necesare rearanjării iepuraşilor.
A doua linie va conţine un număr reprezentând cel mai mic număr aflat pe o faţă albă care nu
se vede (ı̂n cazul ı̂n care au rămas cartonaşe neı̂ntoarse), respectiv cel mai mare număr aflat pe o
faţă albă a unui cartonaş, ı̂n cazul ı̂n care toate cartonaşele au fost ı̂ntoarse (la toate fiind vizibilă
faţa albă).
CAPITOLUL 24. ONI 2014 24.3. IEPURASI 322
Exemple
iepurasi.in iepurasi.out Explicaţii
5 1 Se aplică o singură operaţie TAP pe iepuraşul cu numărul
14 5 8 9 10 999 de ordine 5.
Cartonaşul neı̂ntors are numărul de ordine 14 (999).
ifstream f("iepurasi.in");
CAPITOLUL 24. ONI 2014 24.3. IEPURASI 323
ofstream g("iepurasi.out");
int main()
{
int i,j,k,maxi,imax,aux,c7,c8,c9;;
//citire
f>>N;
for(i=1;i<=N;i++)f>>a[i];
//sortare descrescatoare
for(i=1;i<=N;i++)
{
imax=i;maxi=a[i];
for(j=i+1;j<=N;j++)
if(a[j]>maxi)maxi=a[j],imax=j;
if(imax!=i)
{
if(a[N]!=maxi)
{
TAP++;
//TAP pe iepurasul imax
for(j=imax,k=N;j<k;j++,k--)
aux=a[j],a[j]=a[k],a[k]=aux,viz[j]=true,viz[k]=true;
}
//TAP pe iepurasul i
if(a[i]!=maxi)
{
TAP++;
for(j=i,k=N;j<k;j++,k--)
aux=a[j],a[j]=a[k],a[k]=aux,viz[j]=true,viz[k]=true;
}
}
}
fr7[nr1+nr2]=c7+1;fr8[nr1+nr2]=c8;fr9[nr1+nr2]=c9;
toate[nr1+nr2]=10*ncurent+7;nr2++;
fr7[nr1+nr2]=c7;fr8[nr1+nr2]=c8+1;fr9[nr1+nr2]=c9;
toate[nr1+nr2]=10*ncurent+8;nr2++;
fr7[nr1+nr2]=c7;fr8[nr1+nr2]=c8;fr9[nr1+nr2]=c9+1;
toate[nr1+nr2]=10*ncurent+9;nr2++;
}
//afisare
g<<TAP<<endl<<ncurent<<endl;
f.close();g.close();return 0;
return 0;
}
//Cristina Sichim
#include <fstream>
#include <algorithm>
ifstream f("iepurasi.in");
ofstream g("iepurasi.out");
int v1[10001],v2[10001],c[4],n,i,j,k,t,tap;
long long z,x,y;
int main()
{ f>>n;
for(i=1;i<=n;i++){f>>v1[i];v2[i]=v1[i];}
sort(v2+1,v2+n+1,cand);
for(;i<n;i++)
if(v1[i]!=v2[i])
{ j=i;
while(v1[j]!=v2[i])j++;
if(j!=n) tap++,reverse(v1+j,v1+n+1);
tap++;reverse(v1+i,v1+n+1);
}
//c[1]->7,c[2]->8,c[3]->9
x=1;
while(k)
{ c[0]=c[1]=c[2]=c[3]=0;t=1;
y=x++;
z=0;
while(y)z+=(y%4+6)*t,c[y%4]++,y=y/4,t=t*10;
if(c[0]==0 && c[3]>=c[2] && c[2]>=c[1]) k--;
}
g<<tap<<’\n’<<z<<’\n’;
f.close();g.close();
return 0;
}
if(i1==0)i1=i;
else
if(i2==0)i2=i;
else
break;
//if(i1*i2)
// {g<<i1<<" "<<i2<<endl;}
//else
// {g<<a[2]<<" "<<a[1]<<endl;}
//g<<tap<<endl;
//for(i=1;i<=n;i++)
//g<<a[i]<<’ ’;
long long P,x,i=1,n4,n7=0;
i=1;
for(n7=0;n7<=a[1];i++)
if(i%4)
{ int c[4],ok=1;
for(int j=0;j<=3;j++)c[j]=0;
P=1;x=i;n4=0;
while(x)
{n4=n4+(x%4+6)*P;
c[x%4]++;x=x/4; P=P*10;
}
if(c[0]!=0 || c[1]>c[2] || c[1]>c[3] || c[2]>c[3])ok=0;
if(ok)
{
//g<<i<<’ ’<<n4<<endl;
I[++n7]=n4;
}
}
g<<tap<<endl;
if(i1*i2)
{//g<<I[i1]<<" "<<I[i2]<<endl;
g<<I[i2]<<endl;
}
else
{//g<<I[a[2]]<<" "<<I[a[1]]<<endl;
g<<I[a[1]]<<endl;
}
f.close();
g.close();
return 0;
}
ifstream fin("iepurasi.in");
ofstream fout("iepurasi.out");
nt--;
break;
}
pp=pp*10;
nv++;
// if(nt>=m)return;
}
nrnou=cm*pp+x;;
nt++;
s[nt]=nrnou;
for(i=nt-1; i>=nr+1; i--)
if(s[nt]==s[i])
{
nt--;
break;
}
// if(nt>=m)return;
}
void construieste(int m)
{
long long i,k,c7,c8,c9,nv;
long long x;
s[1]=9;
k=1;
nr=1;
nt=nr;
//m=7000;
while(nt<m)
{
for(poz=k; poz<=nr; poz++)
{
x=s[poz];
c7=c8=c9=0;
nv=0;
while(x)
{
if(x%10==7)c7++;
if(x%10==8)c8++;
if(x%10==9)c9++;
x=x/10;
nv++;
}
if(c8<c9)adauga(8,poz,m);
if(c7<c8&&c8<=c9)adauga(7,poz,m);
adauga(9,poz,m);
}
//if(nt>=m)break;
x=0;
for(i=1; i<=nv+1; i++)
x=x*10+9;
s[++nt]=x;
for(i=nt-1; i>=nr+1; i--)
if(s[nt]==s[i])
{
nt--;
break;
}
k=nr+1;
nr=nt;
}
sort(s+1,s+nt+1);
}
j--;
}
}
int main()
{
fin>>n;
for(i=1; i<=n; i++)
{
fin>>a[i];
ao[i]=a[i];
}
sort(ao+1,ao+n+1);
construieste(m1);
fout<<nro<<’\n’<<s[m1]<<’\n’;
fout.close();
return 0;
}
ifstream f("iepurasi.in");
ofstream g("iepurasi.out");
int main()
CAPITOLUL 24. ONI 2014 24.3. IEPURASI 328
{f>>n;
for(i=1;i<=n;i++)
{
f>>a[i];
if(a[i]>vmax) vmax=a[i];
}
f.close();
{ if(x%10<7){ok=0;x=0;}
cif[x%10]++;x=x/10;
}
if (cif[7]>cif[8]|| cif[8]>cif[9])ok=0;
if(ok){nr++;sir[nr]=i;}
}
*/
for(i=1;i<=n;i++)
{k=0;
for(j=1;j<=n;j++)if(a[j]<a[i])k++;
b[i]=k+1;y[k+1]=i;
}
vmin=a[1];p=0;
ok=1;
for(j=1;j<=n;j++)
{
if(b[j]!=n-j+1) {;p=j;break;}
if(vmin>a[j])vmin=a[j];
for(i=1;i<=n; i++)
if(b[i]!=n-i+1)
{
p1=i;p2=y[n-i+1];
if(p2==n)
{rez++;k=0; for(j=p2;j>=p1; j--) {k++;d[k]=b[j];} }
else
{ rez=rez+2;k=0;
for(j=p2;j<=n; j++){k++;d[k]=b[j];}
for(j=p2-1;j>=p1; j--){k++;d[k]=b[j];}
}
for(ii=1;ii<=k; ii++) {b[p1+ii-1]=d[ii];y[d[ii]]=p1+ii-1;}
}
g<<rez<<endl;
if(p==1)g<<sir[vmax]<<endl;
else
g<<sir[vmin]<<endl;
CAPITOLUL 24. ONI 2014 24.3. IEPURASI 329
g.close();
}
ONI 2013
25.1 greieri
Problema 1 - greieri 100 de puncte
Pe o linie orizontală se găsesc n
greieri. Ei ı̂ncep să stea ”capră” ı̂ntr-
o ordine prestabilită ı̂ncepând cu ul-
timul, pe rând, până la primul. Toţi
greierii care ı̂l precedă pe cel care stă
”capră” sar peste acesta, ı̂n ordine.
De exemplu pentru n=4, mai ı̂ntâi
stă ”capră” greierele 4 şi peste el sar,
ı̂n ordine, 3, 2 şi 1. Apoi stă ”capră”
greierele 3 şi sar peste el, ı̂n ordine, 2,
1 şi 4. Apoi stă ”capră” greierele 2 şi
peste el sar, ı̂n ordine, 1, 3 şi 4. Apoi
stă ”capră” greierele 1 şi sar peste el, Figura 25.1: greieri
ı̂n ordine, 4 , 3 şi 2, şi se revine la ordinea iniţială.
Cerinţe
Date de intrare
Fişierul de intrare greieri.in conţine pe prima linie numerele naturale n şi m, separate printr-
un spaţiu, cu semnificaţia din enunţ.
Date de ieşire
330
CAPITOLUL 25. ONI 2013 25.2. ONIGIM 331
Exemple
greieri.in greieri.out Explicaţii
45 12 După cum se vede şi ı̂n imagine pornind de la linia iniţială
4312 1 2 3 4 la primul pas sare greierele 3 peste 4, la pasul 2
sare greierele 2 peste 4, la pasul trei sare greierele 1 peste
4, la pasul patru sare greierele 2 peste 3, iar la pasul cinci
sare greierele 1 peste 3.
25.2 Onigim
Problema 2 - Onigim 1000 de puncte
La ONIGIM 2013 participă N elevi de clasa a V-a având ca id-uri, ı̂n ordine, numerele naturale
de la 1 la N . Anul acesta organizatorii au afişat la clasa a V-a toate punctajele distincte obţinute
de elevi, ı̂n ordine strict crescătoare p1 , p2 , ..., pK , şi un şir de N valori a1 , a2 , ..., aN , unde ai
reprezintă numărul de elevi care au punctaje strict mai mici decât punctajul elevului având id-ul
i (1 & i & N ).
Cerinţe
Date de intrare
Fişierul de intrare onigim.in conţine pe prima linie numerele naturale N şi K reprezentând
numărul de elevi, respectiv numărul de punctaje distincte obţinute de elevi.
Pe a doua linie sunt K numere naturale ı̂n ordine strict crescătoare p1 , p2 , ..., pK reprezentând
punctajele distincte obţinute de elevi, şi pe a treia linie sunt N numere naturale a1 , a2 , ..., aN ,
unde ai reprezintă numărul de elevi care au punctaje strict mai mici decât punctajul elevului cu
ID-ul i.
Date de ieşire
Exemple
onigim.in onigim.out Explicaţii
64 200 150 100 100 175 200 Sunt 4 elevi care au punctajul mai mic decât punc-
100 150 175 200 4 tajul elevului cu id-ul 1, 2 elevi cu punctajul mai
420034 2 mic decât punctajul elevului cu id-ul 2, etc.
Cele mai mari 3 punctaje sunt obţinute de 4 elevi.
Numărul maxim de elevi care au acelaşi punctaj
este 2.
25.3 Extraprime
Problema 3 - Extraprime 100 de puncte
Gigel, mare amator de probleme de matematică şi informatică, a observat că unele numere
prime au o proprietate interesantă: orice cifră ar elimina dintr-un astfel de număr, numărul obţinut
este tot număr prim. A numit astfel de numere numere extraprime. De exemplu, numărul 317
este un număr extraprim: el este număr prim şi, ı̂n plus, dacă eliminăm cifra 3, obţinem 17, care
este prim; dacă eliminăm 1, obţinem 37, care este prim; dacă eliminăm 7, obţinem 31, care este şi
el număr prim.
Cerinţe
Spunem că x este ı̂ntre a şi b dacă x ' a şi x & b. Fiind date două valori naturale a şi b, să
se determine câte numere extraprime există ı̂ntre a şi b, precum şi cel mai mic şi cel mai mare
număr extraprim dintre a şi b.
Date de intrare
Pe prima linie a fişierului de intrare extraprime.in se găsesc cele două valori naturale a şi b,
separate printr-un spaţiu.
Date de ieşire
CAPITOLUL 25. ONI 2013 25.3. EXTRAPRIME 333
a 10 $ a & b $ 10000000
a Numărul 1 nu este prim.
a Pentru datele de test există ı̂ntotdeauna soluţie.
Exemple
extraprime.in extraprime.out Explicaţii
10 100 4 Se află 4 numere extraprime mai mari decât 10 şi mai
23 mici decât 100: 23, 37, 53 şi 73.
73
ONI 2012
26.1 culegere
Problema 1 - culegere 100 de puncte
O culegere de probleme are P pagini, numerotate de la 1 la P .
Problemele din culegere sunt numerotate cu 1, 2, 3, ..., etc, ı̂n or-
dinea apariţiei lor ı̂n culegere.
Pe prima pagină a culegerii este scrisă o singură problemă (cea cu
numărul 1).
Pe a doua pagină sunt scrise exact două probleme (cele cu numerele Figura 26.1: culegere
2 şi 3, ı̂n această ordine).
Pe cea de-a treia pagină sunt scrise exact trei probleme (cele cu numerele 4, 5 şi 6, ı̂n această
ordine), ..., pe cea de a P -a pagină sunt scrise exact P probleme.
Cerinţe
Scrieţi un program care citeşte numerele naturale P şi N şi determină valorile:
a) T , numărul total de cifre care au fost utilizate ı̂n numerotarea tuturor problemelor din
culegere;
b) M , numărul minim de pagini pe care ar trebui să le aibă culegerea, astfel ı̂ncât aceasta să
conţină şi problema numerotată cu N .
Date de intrare
Fişierul culegere.in conţine pe prima linie cele două numere naturale P şi N , separate printr-
un spaţiu, cu semnificaţia din enunţ.
Date de ieşire
Exemple
334
CAPITOLUL 26. ONI 2012 26.1. CULEGERE 335
a 2, 3 (pagina 2)
a 4, 5, 6 (pagina 3)
a 7, 8, 9, 10 (pagina 4)
a 11, 12, 13, 14, 15 (pagina 5).
În scrierea acestor numere s-au folosit 21 de cifre =¿ T 21.
Pentru a conţine şi problema cu numărul 9, culegerea trebuie să
aibă minimum 4 pagini =¿ M 4.
nt P P 1©2
a Se determină numărul T total de cifre utilizate ı̂n scrierea tuturor numerelor naturale nenule
cel mult egale cu nt, observând că:
Cerinţa b)
a Se determină cel mai mic număr natural M cu proprietatea că 1 2 3 ... M ' N. Acesta
va reprezenta numărul minim de pagini cerut.
#include <fstream>
int main()
{ long long nt,p10=1,k=0,M,i,T=0, P,N,x;
ifstream f("culegere.in");
ofstream g("culegere.out");
f>>P>>N;
nt=P*(P+1)/2;
x=nt;
while(x)
{
k++; x/=10;
}
for(i=1;i<k;i++)
{
T=T+i*p10;
p10*=10;
}
T=T*9+(nt-p10+1)*k;
g<<T<<endl;
g<<M<<endl;
return 0;
}
#include <fstream>
#include <cmath>
int main()
{
long long n,p=1,k,i,nrc=0, P,N;
ifstream f("culegere.in");
CAPITOLUL 26. ONI 2012 26.2. CULORI 337
ofstream g("culegere.out");
f>>P>>N;
n=P*(P+1)/2;
k=log10(n*1.0);
k++;
for(i=1;i<k;i++)
{
nrc=nrc+i*p;
p*=10;
}
nrc=nrc*9+(n-p+1)*k;
g<<nrc<<endl;
long long pag=1;
if(N>1)
{
pag=(-1+sqrt(1.+8*N))/2;
if(pag*(pag+1)<2*N)pag++;
}
g<<pag<<endl;
return 0;
}
26.2 culori
Problema 2 - culori 100 de puncte
Fiecare dintre cei N copii, numerotaţi de la 1 la N , primeşte câte un cartonaş colorat. Doamna
dirigintă ı̂i aşează ı̂n cerc, ı̂n ordinea numerotării, ı̂n sens orar. Astfel, fiecare copil are doi vecini,
aşezaţi ı̂n stânga, respectiv ı̂n dreapta lui.
Andrei, pasionat de informatică, asociază fiecărei culori distincte un cod, reprezentat printr-un
număr natural nenul, şi inscripţionează fiecare cartonaş cu codul corespunzător culorii acestuia.
Cerinţe
Scrieţi un program care citeşte două numere naturale N şi K şi determină pentru Andrei:
a) numărul copiilor din cerc care au cartonaşe de aceeaşi culoare cu cartonaşele vecinilor;
b) numărul maxim de cartonaşe de aceeaşi culoare ce sunt deţinute de copiii aşezaţi pe K
poziţii consecutive ı̂n cercul format.
Date de intrare
Fişierul de intrare culori.in conţine pe prima linie numerele naturale N şi K, separate printr-
un spaţiu, şi pe fiecare dintre următoarele N linii, câte un număr natural. Cele N numere
reprezintă codurile culorilor cartonaşelor, ı̂n ordinea numerotării copiilor, ı̂ncepând cu copilul
1.
Date de ieşire
Fişierul de ieşire culori.out conţine:
a pe prima linie, numărul natural determinat la cerinţa a);
a pe a doua linie, numărul natural determinat la cerinţa b).
Exemple
culori.in culori.out Explicaţii
85 2
3 4 Sunt doi copii care au, fiecare, car-
1 tonaşe identice cu cei doi vecini
2 (copilul 5 şi copilul 8).
1 Numărul maxim de cartonaşe de
1 aceeaşi culoare deţinute de copiii
1 aşezaţi pe K 5 poziţii consecutive
3 ı̂n cercul format este 4 (dintre copiii
3 2, 3, 4, 5, 6 doar copiii 2, 4, 5 şi 6 au
cartonaşe de culoarea 1). Figura 26.6: culori
Pentru următoarele secvenţe de k (i 2, 3, ..., N ) copii alăturaţi scad din vectorul de apariţii
prezenţa culorii cartonaşului copilului i 1 şi adun prezenţa culorii cartonaşului copilului i K 1.
Pentru fiecare secvenţă se actualizează maximul cu elementele din vectorul de apariţii.
int x[2001],apc[101],N,k,c,nrc,apc1[101],maxck,nrck,nrmax,nrmaxk;
ifstream fin("culori.in");
ofstream fout("culori.out");
void citire()
{int i;
fin>>N>>k;
fin>>x[1];
x[N+1]=x[1];
c=x[1];
fin>>x[2];
x[N+2]=x[2];
if(x[2]>c)c=x[2];
for(i=3;i<=N;i++)
{fin>>x[i];
x[N+i]=x[i];
if(x[i]>c)c=x[i];
if(x[i-1]==x[i-2]&&x[i]==x[i-1])
nrc++;
}
if(x[1]==x[N]&&x[N]==x[N-1])
nrc++;
if(x[1]==x[2]&&x[1]==x[N])
nrc++;
}
int main()
{int i,j;
citire();
maxck=0;
for(i=1;i<=k;i++)
{apc1[x[i]]++;
if(apc1[x[i]]>maxck)
maxck=apc1[x[i]];
CAPITOLUL 26. ONI 2012 26.2. CULORI 340
for(i=2;i<=N;i++)
{apc1[x[i-1]]--;
apc1[x[i+k-1]]++;
for(j=1;j<=c;j++)
if(apc1[j]>maxck)
maxck=apc1[j];
fout<<nrc<<endl<<maxck<<endl;
fin.close();fout.close();
return 0;
}
ifstream f("culori.in");
ofstream g("culori.out");
int n,k,c[2001],a[2001],nrc,maxc,maxcc,c_max;
int main()
{int i,j;
f>>n>>k;
for(i=1;i<=n;i++)
{
f>>c[i];
if(c[i]>c_max)
c_max=c[i];
}
for(i=n+1;i<=n+n;i++)
{
c[i]=c[i-n];
}
for(i=2;i<n;i++)
if(c[i-1]==c[i] && c[i]==c[i+1])nrc++;
if(c[n]==c[n-1] && c[n]==c[1])nrc++;
if(c[1]==c[2] && c[1]==c[n])nrc++;
g<<nrc<<endl;
for(i=1;i<=k;i++)
a[c[i]]++;
maxc=0;
for(i=1;i<=c_max;i++)
if(a[i]>maxc)
maxc=a[i];
for(j=k+1;j<=n+n;j++)
{
a[c[j-k]]--; a[c[j]]++;
if(maxc>maxcc)
maxcc=maxc;
for(i=1;i<=c_max;i++)
if(a[i]>maxc)
maxc=a[i];
}
g<<maxcc;
f.close();g.close();
return 0;
}
26.3 stele
Problema 3 - stele 100 de puncte
Ţara Numerelor Fermecate era un ţinut minunat!
Până şi stelele de pe cer erau numerotate cu numere
naturale nenule distincte! Stelele făceau parte din
Constelaţia Numerelor şi erau aranjate ı̂ntr-un roi ı̂n
formă de triunghi, pe coloane şi pe rânduri ı̂n cadrul
fiecărei coloane, ca ı̂n desenul alăturat. Stelele cu nu-
merele 1, 3, 7, 13, 21, 31, ..., situate pe rândul marcat
cu ı̂n desen, formau centrul roiului de stele.
Coloanele din roi erau numerotate de la stânga la
dreapta, ı̂ncepând cu numărul 1, iar rândurile din cadrul
fiecărei coloane erau numerotate de jos ı̂n sus, ı̂ncepând
cu numărul 1 (ca ı̂n desen).
Legenda spune că, pe vremuri, trăia ı̂n ţara Nu-
merelor Fermecate o vrăjitoare deosebit de rea şi de put-
ernică. Tot ceea ce atingea această vrăjitoare cu bagheta
Figura 26.10: stele
magică se prefăcea ı̂n stană de piatră. Ea ı̂şi propusese
să-i preschimbe ı̂n statui pe toţi copiii din ţinut.
În acea vreme ı̂nvăţa la şcoală Numerel, un băieţel vrednic şi curajos. Îl iubea toată lumea!
Zâna Cea Bună s-a hotărât să ı̂l ajute pe Numerel. Aceasta i-a promis inimosului băiat o baghetă
magică, pe care Numerel să o folosească ı̂mpotriva vrăjitoarei. Pentru a primi bagheta, Numerel
a cules pulberea celei de a K-a stele situată ı̂n centrul roiului pentru a i-o da Zânei.
Dar aventura a continuat! Zâna locuia pe steaua cu numărul N , iar Numerel a trebuit să
găsească adresa acesteia, respectiv numărul coloanei, precum şi numărul rândului din coloană, pe
care se găsea această stea.
Aventura voastră abia acum ı̂ncepe!
Cerinţe
Scrieţi un program care citeşte două numere naturale K şi N şi determină pentru Numerel:
a) numărul celei de a K-a stele situată ı̂n centrul roiului;
b) coloana şi rândul (din această coloană) corespunzătoare adresei Zânei.
Date de intrare
Fişierul de intrare stele.in conţine pe prima linie cele două numere naturale, K şi N , separate
printr-un spaţiu.
Date de ieşire
Fişierul de ieşire stele.out conţine:
a pe prima linie, numărul natural determinat la punctul a);
a pe a doua linie, coloana şi rândul determinate la punctul b), ı̂n această ordine, separate
printr-un spaţiu.
Restricţii şi precizări
a 0 $ K & 60000;
a 0 $ N & 60000;
a se acordă 20% din punctaj pentru rezolvarea corectă a cerinţei a);
a se acordă 80% din punctaj pentru rezolvarea corectă a cerinţei b).
Exemple
stele.in stele.out Explicaţii
53 21 Primele K 5 stele din centrul roiului au numerele: 1, 3, 7, 13, 21 .
22 Steaua cu numărul N 3 se află pe coloana 2 , rândul 2 .
25 335 Primele K 2 stele din centru roiului au numerele: 1, 3 .
Steaua cu numărul N 5 se află pe coloana 3 , rândul 5 .
Timp maxim de executare/test: 0.5 secunde
Memorie: total 2 MB din care pentru stivă 2 MB
Dimensiune maximă a sursei: 10 KB
CAPITOLUL 26. ONI 2012 26.3. STELE 342
a Se observă că numărul de jos al fiecărei coloane i (nr. stelei de pe rândul 1, coloana i) este
2
pătratul perfect al numărului coloanei = i .
2
a Toate numerele de pe linia din mijloc se obţin cu formula i i 1, unde i este numărul
2 2 2
coloanei: 3 2 2 1; 7 3 3 1; 13 4 4 1. Prin urmare, al K-lea element se determină
2
cu formula K K 1.
a Dat fiind un număr N , se poate găsi numărul rândului şi al coloanei din triunghi, după cum
urmează:
Coloana = cel mai mic număr natural al cărui pătrat perfect este mai mare sau egal ca N .
2
Rândul = Coloana N 1.
De exemplu, pentru N 6, avem : 2 $ 6 & 3 . Prin urmare coloana este 3 iar rândul este
2 2
2
3 31 7
a Nu este necesar ca datele să fie memorate ı̂ntr-un tabel.
int main()
{FILE *f,*g;
f=fopen("stele.in","r");
g=fopen("stele.out","w");
fscanf(f,"%I64d %I64d",&K,&n);
fprintf(g,"%I64d\n",K*K-K+1);
N=1;
while(N*N<n) N++;
fprintf(g,"%I64d %I64d\n",N,N*N-n+1);
fclose(f);
fclose(g);
return 0;
}
CAPITOLUL 26. ONI 2012 26.3. STELE 343
freopen("stele.in","r",stdin);
freopen("stele.out","w",stdout);
scanf("%I64d%I64d",&K,&N);
printf("%I64d\n",K*K-K+1);
p=(int)sqrt(N);
if(N==p*p)
c=p;
else c=p+1;
l=c*c-N+1;
printf("%I64d %I64d\n",c,l);
printf("\n");
return 0;
}
ifstream f("stele.in");
ofstream g("stele.out");
int k,n;
int main()
{
int i;
unsigned long long x;
f>>k>>n;
x=(unsigned long long)(k-1)*(k-1)+(k*k-(k-1)*(k-1)+1)/2;
g<<x<<endl;
i=1;
while(i*i<n)i++;
if(i*i==n)
g<<i<<" "<<1<<endl;
else
g<<i<<" "<<(i*i-n+1);
return 0;
}
ONI 2011
27.1 Fagure
Problema 1 - Fagure 100 de puncte
Bunicul lui Ionel este apicultor şi din acest motiv Ionel a vrut să combine pasiunea lui pentru
numere cu meseria bunicului. El a aşezat n numere sub forma unui şir de nr faguri, numerotaţi
de la 1 la nr. În cadrul unui fagure numerele au fost aşezate ı̂n sensul rotirii acelor de ceasornic.
Pe latura comună a doi faguri el aşează numai două numere.
Mihuţ, fratele lui Ionel, ca să facă o glumă a amestecat numerele din faguri astfel: a luat
cel mai mare număr prim din al doilea fagure şi l-a schimbat cu cel mai mare număr prim din
penultimul fagure (cu numărul de ordine nr 1), apoi a luat cel mai mare număr prim din al
treilea fagure şi l-a schimbat cu cel mai mare număr prim din antepenultimul fagure (cu numărul
de ordine nr 2), continuă aşa până la mijlocul şirului de faguri.
Mihuţ nu s-a atins de numerele care făceau parte din latura comună a doi faguri alăturaţi.
Dacă ı̂n cadrul unui fagure Mihuţ nu a găsit un număr prim ce poate fi mutat, atunci nu a realizat
interschimbarea ı̂n cadrul perechii de faguri corespunzătoare.
Exemplu:
Ionel a plecat de la 18 numere:
2 11 37 14 5 12 17 101 97 26 3 19 13 5 130 7 213 907
şi le-a aşezat conform modelului din figura 1. Modelul din figura 2 a rezultat după ce Mihuţ
a amestecat numerele. Mihuţ nu are voie să amestece numerele: 11, 37, 101, 97, 19, 13.
Cerinţe
Scrieţi un program care să citească informaţiile din fişierul de intrare fagure.in şi care să
determine:
a) numărul fagurilor pe care a reuşit Ionel să ı̂i construiască;
b) cel mai mic număr de ordine al fagurelui pe care Ionel a plasat valoarea x, ı̂nainte de
amestecarea realizată de Mihuţ;
c) pentru un număr natural k, citit din fişier, care este noul număr plasat de Mihuţ pe fagurele
cu numărul de ordine k. Dacă Mihuţ nu s-a atins de numerele de pe fagurele k se va scrie valoarea
0.
Date de intrare
344
CAPITOLUL 27. ONI 2011 27.1. FAGURE 345
- a doua linie conţine cele n numere naturale nenule mai mici decât 32000, separate prin câte
un spaţiu, cu care Ionel a construit fagurii;
- pe ultima linie din fişier se află numărul natural x cu semnificaţia din enunţ. Valoarea x se
regăseşte ı̂n fişier şi pe linia a doua.
Date de ieşire
a Pentru toate testele, ultimul fagure construit de Ionel, este format din 6 numere.
a 10 & n $ 10000
a 2 & k & cu numărul de ordine al fagurelui din mijloc
a 1 & x $ 30000
a Pentru rezolvarea cerinţei a) se acordă 30% din punctaj, pentru rezolvarea cerinţei b) 40%
din punctaj şi pentru rezolvarea cerinţei c) 30% din punctaj.
Exemple
fagure.in fagure.out Explicaţii
18 2 4 4 reprezintă numărul
2 11 37 14 5 12 17 101 97 26 3 19 13 5 130 7 213 907 23 fagurilor construiţi de
101 5 Ionel; 101 aparţine
fagurilor 2 şi 3; 5
reprezintă valoarea
plasată de Mihuţ pe
fagurele 2.
Punctul a): Fiecare fagure conţine două valori comune cu fagurele anterior la care se adaugă
alte patru valori. Numărul fagurilor se obţine cu următoarea formulă:
a nr n 2©4;
Punctul b): Pentru a determina numărul minim de ordine al fagurelui pe care se afla iniţial
valoarea x, se va realiza o căutare secvenţială, determinând poziţia primei apariţii a valorii x.
Dacă valoarea x este găsită pe latura comuna a doi faguri, atunci se afişează numerele de ordine
a celor doi faguri (ı̂n ordinea crescătoare a lor).
Se tratează separat cazul ı̂n care valoarea x apare ı̂n primul fagure sau ı̂n ultimul.
Punctul c): pentru a determina valoarea rezultată după amestecare, se determină:
a numărul de ordine al fagurelui simetric cu fagurele k;
a primalitatea valorilor ce pot fi amestecate;
a cea mai mare dintre valorile prime ce pot fi amestecate.
În cazul ı̂n care fagurele k sau nr k 1 nu conţine valori prime ce pot fi amestecate, se va
scrie ı̂n fişierul de ieşire valoarea 0.
CAPITOLUL 27. ONI 2011 27.1. FAGURE 346
ifstream f("fagure.in");
ofstream g("fagure.out");
int v[10001];
int main()
{ int n,i,nr_fag,k,gasit=0,grupa,nr,poz,fag,x1,x2,x;
f>>n>>k;
for(i=1;i<=n;i++)
f>>v[i];
f>>x;
// verificam si afisam numarul sau numerele fagurilor din care face parte x
if(poz<=6)
if(poz==2 ||poz==3) g<<1<<’ ’<<2<<’\n’;
else g<<1<<’\n’;
else
if(poz==n-1 || poz==n-2) g<<nr_fag<<’\n’;
else
if((poz%4==0 || poz%4==1) && poz/4<nr_fag)
g<<poz/4<<’ ’<<poz/4+1<<’\n’;
else
if(poz%4==3) g<<poz/4+1<<’\n’;
else g<<poz/4<<’\n’;
// cerinta 3
// fagurele pe care s-a gasit initial numarul prim este
fag=nr_fag+1-k;
if(prim(v[x1])&& prim(v[x2]))
if(v[x1]>v[x2]) g<<v[x1]<<’\n’;
else g<<v[x2]<<’\n’;
else
{
if(prim(v[x1])) g<<v[x1]<<’\n’;
if (prim(v[x2])) g<<v[x2]<<’\n’;
}
g<<0<<’\n’;
f.close();
g.close();
return 0;
}
27.2 Goe
Problema 2 - Goe 100 de puncte
Goe este un copil drăgălaş, dar tare leneş.
Nu ı̂i place nici să scrie, nici să numere. Cu
greu a fost convins de mama sa să ı̂nveţe cifrele,
dar de scris tot nu poate să le scrie pe toate. Nu
ı̂i plac cifrele 2, 4, 5 şi 7, iar cifra 6 o ı̂ncurcă cu
9 şi invers. Şi asta nu este tot. Când mama sa ı̂i
dă să copieze numere, pentru a exersa scrierea
cifrelor, el le scrie ı̂n oglindă, adică scrie cifrele
ı̂n ordinea inversă. De exemplu numărul 138
va fi scris de Goe 831.
Mama lui Goe scrie ı̂n fiecare zi, ı̂n ordine
crescătoare, câte 9 numere naturale, sărind Figura 27.2: Goe
ı̂nsă peste orice număr divizibil cu 10, ca ı̂n Figura 1. Goe copiază zilnic aceste numere. Din
păcate, el nu ı̂şi ı̂ndreaptă niciuna dintre greşeli: copiază numerele scriindu-le oglindite, nu scrie
numerele care conţin cifrele 2, 4, 5 şi 7 şi ı̂nlocuieşte, ı̂n continuare cifra 6 cu 9 şi invers (vezi
Figura 2).
Cerinţe
Scrieţi un program care să citească numerele naturale nenule k, p şi n şi care să determine:
a) Numărul de numere scrise de Goe ı̂n primele k zile;
b) Al p-lea palindrom scris corect de Goe; un număr este palindrom dacă este egal cu oglinditul
său;
c) Cel mai mare număr scris de Goe ı̂n primele n zile.
Date de intrare
Fişierul goe.in conţine o singură linie pe care sunt scrise trei numere naturale k, p şi n, separate
prin câte un spaţiu.
Date de ieşire
Exemple
goe.in goe.out Explicaţii
5 15 15 numere a scris Goe ı̂n primele 5 zile.
8 111 Primele 8 palindroame scrise corect de Goe sunt:
3 91 1, 3, 8, 11, 33, 88, 101, 111.
Cel mai mare număr scris de Goe ı̂n primele 3 zile este 91.
Cerinţa a):
Goe scrie ı̂ntr-o zi 5 numere sau niciunul. Este suficient să se numere câte dintre primele k
numere naturale strict pozitive (zile) nu au ı̂n componenţă una dintre cifrele 2, 4, 5 sau 7 şi să se
ı̂nmulţească acest număr cu 5.
Cerinţa b):
Un palindrom scris corect de Goe conţine doar cifrele 0, 1, 3 şi 8. El scrie 3 palindroame cu o
singură cifră, 3 palindroame cu 2 cifre, 9 palindroame cu 3 cifre, 12 palindroame cu 12 cifre etc.
Deci numărul de palindroame se multiplică cu 4 de fiecare dată când se trece de la un palindrom
cu un număr par de cifre la unul cu un număr impar de cifre (2c 2c 1).
Se determină iniţial nrc, numărul de cifre pe care le are cel de-al p-lea palindrom, apoi se con-
struiesc, pe rând, palindroamele de nrc cifre până la cel de-al p-lea palindrom. Pentru construcţie
se poate utiliza scrierea ı̂n baza 4, ı̂nlocuind ulterior cifra 2 cu 3 şi cifra 3 cu 8 (0 0, 1 1,
2 3, 3 8).
Cerinţa c):
Se observă că numărul maxim scris de Goe are prima cifră 9. Pentru a determina celelalte
cifre, se memorează cifrele numărul n ı̂ntr-un vector şi se prelucrează pe rând cifrele sale. Vectorul
se afişează ı̂n mod invers.
ifstream f("goe.in");
ofstream g("goe.out");
long n,k,p,bune,max,nrn,put,x,aux,nrbune,ok,d;
int s[11];
long v[11],sum,power;
long i,j,nr,nrcif,posib,nrc,schimbat,r,l,inv,pn,un,copie,cifra;
int main()
{
f>>k>>p>>n;
//a)**************************
nrn=0;
for(i=1;i<=k;i++)
{
aux=i-1;ok=1;
while(aux>0)
{
if(aux % 10 == 2 || aux % 10 == 4 ||
aux % 10 == 5 || aux % 10 == 7) ok=0;
aux/=10;
}
CAPITOLUL 27. ONI 2011 27.2. GOE 349
if(ok)nrn=nrn+5;
}
g<<nrn<<’\n’;
//b)**************************
nrc=1; d=3; //d reprezinta cate numere palindroame de nrc cifre exista
while(p>d)
{
p=p-d;
nrc++;
if(nrc%2) d=d*4;
}
i=1;
while(d>0)
{
v[i]=v[nrc-i+1]=v[i]+p/d;
p=p%d;
d/=4;
i++;
}
for(i=1;i<=nrc;i++) g<<v[i];
g<<’\n’;
//c)**************************
nrc=log10(n)+1;
i=nrc;
while(n>0)
{
s[i]=n%10;
n=n/10;
i--;
}
i=1;
if(s[1]==1)
{
i++;
while(i<=nrc && s[i]==0)i++;
}
if(i==nrc+1)
{
for(j=1;j<=nrc;j++)g<<’9’;
g<<’\n’;
}
else
{
g<<’9’;
if(s[i]>1 && i<nrc && s[i+1]<6 || s[i]==1 && s[i+1]<6 || s[i]!=9)
{
s[i]--;
if(s[i]==2 || s[i]==4 || s[i]==5 || s[i]==7) s[i]--;
if(s[i]==4) s[i]=3;
}
CAPITOLUL 27. ONI 2011 27.3. PĂPUŞA 350
i++;
for(;i<=nrc;i++) s[i]=9;
for(i=nrc;i>=1;i--)
{
if(s[i]==6) s[i]=9;
g<<s[i];
}
g<<’\n’;
}
f.close();
g.close();
return 0;
}
27.3 Păpuşa
Problema 3 - Păpuşa 100 de puncte
Păpuşa Matrioşka este o jucărie din lemn,
goală pe dinăuntru. De aceea, ı̂n interiorul
său poate fi introdusă oricare altă păpuşă Ma-
trioşka de ı̂nălţime mai mică.
La un magazin de suveniruri se găsesc n Figura 27.3: papusa
păpuşi Matrioşka aşezate ı̂n şir, ı̂n număr egal, pe două rafturi alăturate. Pe raftul din stânga
sunt expuse prima jumătate de păpuşi, situate ı̂n şir pe poziţiile 1, 2, ...., n©2, iar raftul din
dreapta ultima jumătate de păpuşi, situate ı̂n şir pe poziţiile n©2 1, ..., n. Prin notaţia n©2
se ı̂nţelege jumătatea numărului n.
Ana şi Iulia vor să cumpere cât mai multe păpuşi Matrioşka, dar tatăl lor le impune următoarele
reguli:
a Iulia are voie să aleagă păpuşi din raftul din stânga, iar Ana din raftul din dreapta
a Dacă de pe un raft se cumpără mai multe păpuşi, atunci ele se vor afla pe poziţii consecutive
pe raft;
a Prima păpuşă cumpărată de o fetiţă va avea ı̂nălţimea mai mică decât cea de a doua, a
doua decât cea de a treia şi aşa mai departe astfel ı̂ncât fiecare păpuşă să poate fi introdusă ı̂n
următoarea păpuşă cumpărată;
a Ultimele păpuşi cumpărate trebuie să se situeze doar la capetele rafturilor şi ı̂n plus:
- dacă ultima păpuşă cumpărată de Iulia este pe poziţia 1 atunci ultima păpuşă cumpărată de
Ana trebuie să fie pe poziţia n;
- dacă ultima păpuşă cumpărată de Iulia este pe poziţia n©2 atunci ultima păpuşă cumpărată
de Ana trebuie să fie pe poziţia n©2 1.
Pentru a putea să aleagă cât mai multe păpuşi respectând regulile impuse de tatăl lor, fetiţelor
li se permite să execute ı̂n acelaşi timp următoarea operaţie, până se revine la aşezarea iniţială a
păpuşilor:
a Iulia mută păpuşa de pe poziţia 1 pe poziţia n©2, deplasând cu o poziţie spre stânga toate
celelalte păpuşi din raftul său;
a Ana mută păpuşa de pe poziţia n pe poziţia n©2 1, deplasând cu o poziţie spre dreapta
toate celelalte păpuşi din raftul său;
Cerinţe
Pentru a le ajuta pe Iulia şi Ana să achiziţioneze ı̂mpreună un număr maxim de păpuşi, scrieţi
un program care citeşte un număr natural n şi ı̂nălţimile celor n păpuşi şi determină:
a) numărul M de operaţii efectuate concomitent de fetiţe;
b) numărul maxim P de păpuşi care vor fi cumpărate.
Date de intrare
CAPITOLUL 27. ONI 2011 27.3. PĂPUŞA 351
Fişierul text papusa.in conţine pe prima linie un număr natural par n, reprezentând numărul
de păpuşi. Pe linia a doua sunt n numere naturale separate prin câte un spaţiu, reprezentând
ı̂nălţimile păpuşilor situate pe cele două rafturi, ı̂n ordine de la poziţia 1 la n.
Date de ieşire
Exemple
papusa.in papusa.out Explicaţii
8 2 Raftul Iuliei conţine păpuşile de ı̂nălţimi 5, 7, 2, 4, iar al Anei
5 7 2 4 6 10 14 8 7 păpuşile de ı̂nălţimi 6, 10, 14, 8. Pe această aşezare Iulia şi
Ana pot cumpăra păpuşile de ı̂nălţime 2 4 6 sau 5 8. Se pot
cumpăra cel mult 3 păpuşi.
Configuraţia obţinută după prima operaţie de mutare este: 7
2 4 5 8 6 10 14
Pe această aşezare Iulia şi Ana pot cumpăra păpuşile de
ı̂nălţime 2 4 5 6 8 sau 2 7 6 10 14. Se pot cumpăra cel mult 5
păpuşi.
Configuraţia obţinută după a doua operaţie 2 4 5 7 14 8 6
10. Pe această aşezare Iulia şi Ana pot cumpăra păpuşile cu
ı̂nălţimile 2 4 5 7 6 8 14 sau 2 6 10. Deci se pot cumpăra cel
mult 7 păpuşi.
Configuraţia obţinută după a treia operaţie 4 5 7 2 10 14 8 6.
Pe această aşezare Iulia şi Ana pot cumpăra păpuşile cu
ı̂nălţimile 2 10 sau 4 6. Deci se pot cumpăra cel mult 2 păpuşi.
Numărul maxim de păpuşi cumpărate este 7 şi se obţine după
a doua operaţie de mutare.
Se generează concomitent toate permutările circulare ale primei jumătăţi a şirului, respectiv
ale celei de a doua jumătăţi. Pentru fiecare permutare, se determină următoarele valori:
L1 - lungimea secvenţei descrescătoare care ı̂ncepe la poziţia 1
L2 - lungimea secvenţei crescătoare care se termină pe poziţia n
L3 - lungimea secvenţei crescătoare care se termină pe poziţia n©2
L4 - lungimea secvenţei descrescătoare care ı̂ncepe pe poziţia n©2 1
Numărul maxim de păpuşi cumpărate este maximul dintre sumele L1 L2 şi L3 L4.
Numărul de operaţii cerute este egal cu numărul de ordine a permutării pentru care se obţine
numărul maxim de păpuşi.
CAPITOLUL 27. ONI 2011 27.3. PĂPUŞA 352
int main()
{
ifstream fin("papusa.in");
ofstream fout("papusa.out");
int n, x[1001];
int l11, l22, ok = 1;
fin >> n;
l1 = l2 = 1;
l11 = 1, l22 = 1;
ok = 1;
for(i = n/2-1; i > 0 && ok; i--)
if(x[i+1] > x[i])l1++;
else ok = 0;
ok = 1;
for(i = n/2+2; i <= n&&ok; i++)
if(x[i-1] > x[i])l2++;
else ok = 0;
ok = 1;
for(i = n-1; i >= n/2 && ok; i--)
if(x[i+1] > x[i])l22++;
else ok = 0;
ok = 1;
for(i = 2; i <= n/2 && ok; i++)
if(x[i-1] > x[i])l11++;
else ok = 0;
pas++;
aux1 = x[1];
aux2 = x[n];
for(i = 1; i < n/2; i++)
{
x[i] = x[i+1];
x[n-i + 1] = x[n-i];
}
x[n/2] = aux1;
x[n/2+1] = aux2;
}
ONI 2010
28.1 cluburi
Problema 1 - cluburi 100 de puncte
La şcoala Iuliei, ı̂n clasa a V-a sunt n elevi. Pentru că aşa e moda la această şcoală, fiecare
dintre cei n copii şi-a creat câte un club.
Fiecare club are iniţial un singur membru: copilul care l-a creat. Copiii au hotărât că numărul
membrilor unui club poate să crească prin unificarea cu un alt club după următoarea regulă:
două cluburi se pot unifica dacă au acelaşi număr de membri. Prin unificare, unul dintre cluburi
continuă să existe, iar celălalt se desfiinţează. Clubul care continuă să existe preia toţi membrii
clubului care se desfiinţează.
Deoarece elevii se distrează mai bine atunci când clubul are mai mulţi membri, ei au hotărât
să unifice cluburile după regula de mai sus, cât timp unificarea este posibilă.
Cerinţe
Scrieţi un program care să citească numărul natural n şi care să determine:
a) cel mai mic număr natural k de cluburi care continuă să existe după ce s-au produs toate
unificările;
b) pentru fiecare dintre cluburi, numărul de membri.
Date de intrare
Fişierul de intrare cluburi.in conţine o singură linie pe care este scris un număr natural nenul
n, reprezentând numărul de elevi din clasa a V-a.
Date de ieşire
354
CAPITOLUL 28. ONI 2010 28.1. CLUBURI 355
Exemple:
cluburi.in cluburi.out Explicaţii
7 3 6 elevi formează 3 cluburi având fiecare câte 2 membri, iar elevul
124 rămas formează la rândul lui un club (cu un singur membru).
Apoi 2 dintre cluburile cu câte 2 membri se unesc şi formează un
singur club cu 4 membri, deci sunt 3 cluburi: 1 cu un membru, 1
cu 2 membri şi 1 cu 4 membri.
24 2 Iniţial se formează 12 cluburi cu câte 2 membri, apoi 6 cu câte 4
8 16 membri.
Din cele 6 cluburi se vor forma apoi 3 cu câte 8 membri.
Două dintre cluburile cu 8 membri se unesc formand unul cu 16
membri. ı̂n final rămân 2 cluburi, unul cu 8, iar celălalt cu 16
membri.
Descrierea soluţiei
Numărul de cluburi care se formează este egal cu suma resturilor obţinute prin ı̂mpărţirea
repetată a numărului n la 2, atât timp cât n este diferit de 0.
k1
Numărul de membri ai fiecărui club este egal cu 2 , unde k este egal cu numărul de ı̂mpărţiri
la 2 al lui n şi la acel pas n%2 este egal cu 1.
#include<fstream>
#include <cstring>
int main()
{ int n,k=0,i;
long p=1;
char s[50];
ifstream f("cluburi.in");
ofstream g("cluburi.out");
f>>n;
itoa(n,s,2);
for(i=0;i<strlen(s);i++)
if(s[i]==’1’)k++;
g<<k<<’\n’;
for(i=strlen(s)-1;i>=0;i--)
{
if(s[i]==’1’) g<<p<<’ ’;
p=p*2;
}
g<<’\n’;
f.close();g.close();
return 0;
}
ifstream fin("cluburi.in");
ofstream fout("cluburi.out");
int main()
{
int N;
fin >> N ;
int k = 0, c = N, cant = 1;
int x = N;
while(x)
{
if(x % 2 == 1)k++;
x = x/2;
}
while(c)
{
if(c % 2 == 0)
c = c/2, cant = cant * 2;
else
{
c = c/2;
fout << cant <<" ";
cant = cant * 2;
}
}
fin.close();
fout.close();
return 0;
}
ifstream fin("cluburi.in");
ofstream fout("cluburi.out");
int main()
{
long int N;
fin >> N ;
while(c)
{
if(c % 2 == 0)
c = c/2, cant = cant * 2;
else
{
/* if(gasit == 0)
{
c1 = cant;
gasit = 1;
} */
nr = nr + 1;
c = c/2;
x[nr] = cant;
cant = cant * 2;
}
}
CAPITOLUL 28. ONI 2010 28.2. DOMINO 358
fin.close();
fout.close();
return 0;
}
28.2 domino
Problema 2 - domino 100 de puncte
Ionel are n piese de domino de diverse ı̂nălţimi. În joacă, el aşează piesele vertical ı̂ntr-un şir
(pe o riglă gradată), la distanţe nu neapărat egale una faţă de alta. Ionel atinge prima piesă,
aceasta cade şi poate antrena ı̂n cădere după ea şi alte piese din şir. Dacă mai rămân piese ı̂n
picioare, el merge la prima piesă care nu a căzut şi o atinge. Aceasta cade şi poate antrena ı̂n
cădere după ea şi alte piese. Continuă procedeul până când nu mai rămâne nicio piesă ı̂n picioare.
Cerinţe
Scrieţi un program care să citească numărul natural n de piese, poziţia pe riglă şi ı̂nălţimea
fiecărei piese, ı̂n această ordine, şi care să determine numărul minim necesar de atingeri ale pieselor
astfel ı̂ncât să cadă toate piesele de domino precum şi numărul maxim de piese răsturnate la o
singură atingere.
Date de intrare
Date de ieşire
Fişierul de ieşire domino.out va conţine o singură linie pe care sunt scrise două numere
naturale a şi b, ı̂n această ordine, separate printr-un spaţiu, a reprezentând numărul minim necesar
de atingeri ale pieselor, iar b numărul maxim de piese ce sunt răsturnate la o singură atingere a
unei piese.
Exemple:
domino.in domino.out Explicaţii
5 23 La atingerea primei piese vor cădea primele două piese;
10 10 Atingea piesei de pe poziţia 27 răstoarnă piesa de pe poziţia
14 10 28 iar aceasta o răstoarnă şi pe ultima.
27 2 Numărul de atingeri este 2 iar numărul maxim de piese
28 10 doborâte la o atingere este 3.
37 5
Descrierea soluţiei
Soluţia propusă memorează ı̂n variabila dist poziţia maximă la care acţionează o piesă care a
căzut, ı̂n variabila nd numărul de piese doborâte la o atingere şi ı̂n nmax numărul maxim de piese
doborâte la o atingere.
Pentru fiecare piesă de domino se verifică dacă este doborâtă de o piesă anterioară, se ac-
tualizează numărul de piese doborâte la atingerea curentă şi poziţia până la care se doboară ı̂n
continuare alte piese.
CAPITOLUL 28. ONI 2010 28.2. DOMINO 360
domino d[1001];
int n,nd,dmax,nmax,nr,dist;
ifstream f("domino.in");
ofstream g("domino.out");
int main()
{ int i;
f>>n;
for(i=1;i<=n;i++)
f>>d[i].p>>d[i].h;
f.close();
dist=0;
for(i=1;i<=n;i++)
if(d[i].p>dist||nd==0)
{
nd++;
if(nr>nmax) nmax=nr;
dist=d[i].p+d[i].h;
nr=1;
}
else
{
nr++;
if(dist< d[i].p+d[i].h )
dist=d[i].p+d[i].h;
}
if(nr>nmax) nmax=nr;
CAPITOLUL 28. ONI 2010 28.2. DOMINO 361
g<<nd<<" "<<nmax;
g.close();
return 0;
}
int n,nd,dmax,nmax,nr,dist,h,p;
ifstream f("domino.in");
ofstream g("domino.out");
int main()
{
int i;
f>>n;
dist=0;
nd=0;
for(i=1;i<=n;i++)
{
f>>p>>h;
if(p>dist)
{
nd++;
if(nr>nmax) nmax=nr;
dist=p+h;
nr=1;
}
else
{
nr++;
if(dist< p+h )
dist=p+h;
}
}
if(nr>nmax) nmax=nr;
g<<nd<<" "<<nmax;
g.close();
return 0;
}
ifstream fi("domino.in");
ofstream fo("domino.out");
struct interval
{
int a, b, nr;
}
v[5000];
{ e=a;
if(e>c) e=c;
f=b;
if(f<d) f=d;
}
int main()
{
int N,p,h,i,k=0,j,max=1,ok;
fi>>N;
fi>>p>>h;
k++;
v[k].a=p;
v[k].b=p+h;
v[k].nr=1;
for(i=2;i<=N;i++)
{
fi>>p>>h;ok=0;
for(j=1;(j<=k)&&(ok==0);j++)
if(comun(v[j].a,v[j].b,p,p+h))
{
rez(v[j].a, v[j].b,p,p+h,v[j].a,v[j].b);
v[j].nr++;
if(max<v[j].nr)max=v[j].nr;
ok=1;
}
if(ok==0)
{ k++;
v[k].a=p; v[k].b=p+h;
v[k].nr=1;
}
}
fo<<k<<’ ’<<max;
fi.close();
fo.close();
return 0;
}
int main()
{
ifstream f("domino.in");
ofstream g("domino.out");
int N,p,h,a=1,b=1,nrb=1,i,unde;
f>>N;
f>>p>>h;
unde=p+h;
for(i=2;i<=N;i++)
{
f>>p>>h;
if(p<=unde)
{
nrb++;
if(p+h>unde) unde=p+h;
}
else
{
if (nrb>b) b=nrb;
nrb=1;a++;
unde=p+h;
}
CAPITOLUL 28. ONI 2010 28.3. MAX 363
if(nrb>b) b=nrb;
g<<a<<’ ’<<b;
f.close();
g.close();
return 0;
}
ifstream fin("domino.in");
ofstream fout("domino.out");
int main()
{
int x[1000];
int p, h, smax = 1, pf, i, sfin = 1, buf = 1;
int n;
fin >> n;
fin >> p >> h;
pf = p + h;
return 0;
}
28.3 max
Problema 3 - max 100 de puncte
Fie n un număr natural nenul şi un şir de n numere naturale nenule, fiecare număr din şir
având cel mult 3 cifre. Şirul dat se ”maximizează” prin aplicarea următoarelor transformări:
T1: Fiecare număr y din şir este ı̂nlocuit cu cel mai mare număr care se poate obţine prin
aranjarea tuturor cifrelor lui y. De exemplu, pentru y 102, prin aranjarea cifrelor, se obţin
numerele: 12, 21, 102, 120, 201, 210, cel mai mare număr fiind 210. Astfel, y se va ı̂nlocui ı̂n şir
cu numărul 210.
CAPITOLUL 28. ONI 2010 28.3. MAX 364
T2: Se schimbă ordinea numerelor din şirul obţinut după aplicarea transformării T 1 astfel
ı̂ncât numărul x obţinut prin alipirea tuturor numerelor din şir, ı̂n ordinea ı̂n care apar după
schimbare, să fie cel mai mare posibil.
De exemplu, pentru n 3 şi şirul: 12, 132, 102, după aplicarea transformării T 1 noul şir este
format din numerele: 21, 321, 210. Din acest şir, se pot obţine, prin schimbarea ordinii numerelor,
următoarele 6 şiruri: 1) 21, 321, 210; 2) 21, 210, 321; 3) 321, 21, 210; 4) 321, 210, 21; 5) 210, 21,
321; 6) 210, 321, 21.
Numerele care rezultă prin alipirea numerelor din fiecare şir obţinut sunt:
1) 21321210; 2) 21210321; 3) 32121210; 4) 32121021; 5) 21021321; 6) 21032121.
După aplicarea transformării T 2, şirul ”maximizat” este: 321, 21, 210 deoarece cel mai mare
număr dintre cele 6 obţinute este x 32121210.
Cerinţe
Scrieţi un program care să citească numărul natural nenul n şi cele n numere naturale nenule
din şir şi care să determine:
a) cel mai mare număr m din şirul de numere obţinut ı̂n urma aplicării transformării T 1;
b) numărul x obţinut prin alipirea numerele din şirul ”maximizat” rezultat ı̂n urma aplicării
transformării T 2.
Date de intrare
Fişierul de intrare max.in conţine două linii. Pe prima linie este scris numărul natural nenul
n, iar pe a doua linie sunt scrise cele n numere naturale nenule din şir, separate prin câte un
spaţiu.
Date de ieşire
Exemple
max.in max.out Explicaţii
9 321 După aplicarea transformării T1, şirul
34 23 9 43 21 67 121 79 213 9977643433232121211 devine: 43, 32, 9, 43, 21, 76, 211, 97,
321. Cel mai mare număr din acest
şir este m=321. După aplicarea trans-
formării T2, şirul maximizat este: 9, 97,
76, 43, 43, 32, 321, 21, 211 iar numărul
x 9977643433232121211
Descriere soluţie
O soluţie posibilă se poate obţine prin utilizarea a doi vectori v şi p, fiecare având maxim 3500
de componente ı̂ntregi.
În vectorul v se vor memora numerele din şirul obţinut ı̂n urma transformării T 1, rezultate
din numerele din fişierul de intrare. Acestea pot fi citite succesiv ı̂ntr-o variabilă x.
Pentru fiecare număr memorat ı̂n x se separă cifrele, se ordonează descrescător aceste cifre
iar numărul obţinut se memorează ı̂n v i. În acelaşi timp se memorează ı̂n componenta pi
k
valoarea pi 10 , unde k reprezintă numărul de cifre ale lui v i, pi fiind utilă ı̂n construirea
numerelor rezultate prin alipirea a două valori din vectorul v.
În timp ce se aplică T 1, se determină şi valoarea maximă din şirul obţinut.
Pentru a obţine şirul maximizat rezultat din T 2, se poate utiliza un algoritm de sortare, de
exemplu sortarea prin selectarea maximului.
Pentru fiecare i 1, .., n 1 şi j i 1.., n se construiesc cele două numere rezultate prin prin
alipirea, ı̂n această ordine, a numerelor v i şi v j , respectiv v j şi v i, adică v i pj v j
şi v j pi v i. Se selectează maximul dintre aceste valori.
Numărul x cerut se obţine prin alipirea tuturor numerelor din şirul maximizat. Acest lucru se
realizează prin scrierea ı̂n fişierul de ieşire a tuturor numerelor din şirul maximizat, ı̂n ordinea din
acest şir, fără spaţii ı̂ntre numere.
int main()
{
int n, v[3505], p[3505];
long d,e;
int i, max=0,x,a,b,c,j;
CAPITOLUL 28. ONI 2010 28.3. MAX 367
ifstream f("max.in");
ofstream g("max.out");
f>>n;
for(i=1;i<=n;i++)
{ f>>x; v[i]=x;
if(x<10) p[i]=10;
else
if(x<100)
{ a=x/10; b=x%10; p[i]=100;
if (a<b)v[i]=b*10+a;
}
else
{ a=x/100; x=x%100; b=x/10; c=x%10;p[i]=1000;
if(a<b) { x=a; a=b; b=x;}
if(a<c) { x=a; a=c; c=x;}
if(b<c) { x=b; b=c; c=x;}
v[i]=100*a+10*b+c;
}
if(max<v[i])max=v[i];
}
g<<max<<endl;
for(i=1;i<n;i++)
for(j=i+1;j<=n;j++)
{ d=v[i];d=d*p[j]+v[j];
e=v[j]; e=e*p[i]+v[i];
if (d<e)
{
x=v[i]; v[i]=v[j]; v[j]=x;
x=p[i]; p[i]=p[j]; p[j]=x;
}
}
for(i=1;i<=n;i++) g<<v[i];
g.close();
return 0;
}
#include<fstream>
int n,v[1001],i,x,aux,maxx,y,z,a,b,c;
int main()
{
ifstream f("max.in");
ofstream g("max.out");
f>>n;
for(i=1;i<=n;i++)
{
f>>x;
if(x>9 && x<100 && x/10<x%10) x=x%10*10+x/10;
if(x>99)
{
a=x%10;b=x/10%10;c=x/100;
if(a<b) {aux=a;a=b;b=aux;}
if(a<c) {aux=a;a=c;c=aux;}
if(b<c) {aux=b;b=c;c=aux;}
x=a*100+b*10+c;
}
v[x]++;
if(maxx<x) maxx=x;
}
g<<maxx<<’\n’;
CAPITOLUL 28. ONI 2010 28.3. MAX 368
for(x=9;x>0;x--)
{
//toate care incep cu cifra x
while(v[x]--) g<<x; //cele de o cifra
for(y=x*10+9;y>=x*10;y--)
{
while(v[y]--)g<<y;
for(z=y*10+x;z>=y*10;z--)
while(v[z]--)g<<z;
}
}
g<<’\n’;
f.close();
g.close();
return 0;
}
void Sorteaza();
int maxim(int nr);
void Afiseaza();
int n, max2, m;
int c[1001];
int main()
{
int nr, m = 0, max2 = 0;
fin >> n;
for(int i = 1; i <= n; i++)
{
fin >> nr;
nr = maxim(nr);
c[nr]++;
if(nr > m) m = nr;
if(nr < 100 && nr > 9)
{
if(max2 < nr) max2 = nr;
}
}
fout << m;
fout << "\n";
// Sorteaza();
Afiseaza();
fin.close();
fout.close();
return 0;
}
a[i]--;
}
return nr;
}
void Afiseaza()
{
int i = 9, j, k;
/* for(i = 999; i >= 0; i--)
while(c[i])
{fout<< i<< " ";
c[i]--;
}*/
while(c[j])
if(j >= k/10)
{
fout << j;
c[j]--;
}
while(c[k])
{
fout << k;
c[k]--;
}
}
}
371
APPENDIX A. PROGRAMA OLIMPIADEI - GIMNAZIU A.3. CLASA A VII-A 372
6. Tablouri bidimensionale
– Prelucrări elementare ale tablourilor bidimensionale (de exemplu, parcurgeri pe linii/-
coloane/diagonale/ı̂n spirală, generări, transpunere, bordare)
– Prelucrări specifice tablourilor bidimensionale pătratice (de exemplu, diagonale şi zone
determinate de diagonale)
– Căutări secvenţiale ı̂n tablouri bidimensionale (de exemplu, a unui element, a unei
secvenţe de valori, a unei submatrice)
– Utilizarea vectorilor de direcţie
7. Simulări
– reprezentarea sistemului de simulat, starea sistemului
– bucla de evenimente ce modifică starea sistemului
– Permutări
– Combinări
– Aranjamente
– Utilizarea funcţiilor din biblioteca STL pentru permutări
A.6 Note
Exceptând clasa a V-a, programa fiecărei clase include şi programele pentru toate clasele
precedente.
Barajul de selecţie a lotului naţional lărgit include programele pentru clasele V-VIII, precum
şi temele suplimentare specificate.
Pentru barajele de selecţie a echipelor reprezentative ale României vor fi abordate teme
suplimentare.
Appendix B
int main()
{
fin>>c;
fin>>n;
// instructiuni
return 0;
}
Chiar dacă utilizarea funcţiilor definite de utilizator este prevăzută ı̂ncepând cu clasa a VII-a,
este bine să le folosim ı̂ncă din clasa a V-a! Asta pentru că utilizarea lor permite o mai bună
29
lizibilitate a programelor! Şi oricum ... participanţii la olimpiadă citesc mai mult decât este
30
prevăzut ı̂n programa olimpiadei! Vom folosi modelul de la funcţia main().
int calcul()
{
// instructiuni
return 0;
}
28
https://sepi.ro/page/oni2022
29
https://ro.wikipedia.org/wiki/Lizibilitate
30
tot ce nu este interzis, este permis!
374
APPENDIX B. MAIN(), CIN, COUT, FIN, FOUT B.1. FUNCŢIA MAIN() 375
int main()
{
fin>>c;
fin>>n;
calcul();
return 0;
}
Appendix C
”Instalare” C++
Instalarea este foarte uşoară (este de tipul ”next -> next -> ... -> next”) iar pe in-
ternet sunt multe site-uri de ajutor. De exemplu:
https://www.pbinfo.ro/?pagina=intrebari-afisare&id=26
https://www.youtube.com/watch?v=CLkWRvAwLO8
https://infoas.ro/lectie/112/tutorial-instalare-codeblocks-usor-introducere-in-in
https://www.competentedigitale.ro/c/oji2019/Kit_OJI_2017.rar
376
APPENDIX C. ”INSTALARE” C++ C.1. KIT OJI 2017 377
C.1.1 Code::Blocks
Pentru versiuni mai noi, de Code::Blocks şi compilatoare, se poate accesa site-ul
http://www.codeblocks.org/downloads/binaries
de unde se poate descărca, de exemplu, codeblocks-20.03mingw-setup.exe.
Versiuni mai vechi, dar foarte bune, se pot descărca de la adresa
31
Code::Blocks este un IDE (integrated development environment) pentru C/C++, un fel de Notepad ... mai
sofisticat, cu multe butoane care lansează ı̂n execuţie diverse programe, de exeplu g++.exe
32
g++.exe este compilatorul de C++, programul care va verifica dacă instrucţiunile noastre sunt ok sau nu ...
şi care ne va supăra mereu cu erorile pe care ni le arată ... ... Este “o mică artă” să ı̂nţelegem mesajele de
eroare pe care le vedem pe ecran şi să fim ı̂n stare să “depanăm” programele noastre!
APPENDIX C. ”INSTALARE” C++ C.1. KIT OJI 2017 378
http://www.codeblocks.org/downloads/source/5
Mai precis:
https://sourceforge.net/projects/codeblocks/files/Binaries/20.03/
http://sourceforge.net/projects/codeblocks/files/Binaries/17.12
http://sourceforge.net/projects/codeblocks/files/Binaries/16.01
De preferat este să avem cel puţin două partiţii: C:¯, D:¯, ... şi să “lăsăm ı̂n pace” partiţia C:¯
pentru sistemul de operare şi programele instalate!
În figura de mai sus se poate observa că pe D:¯ există un folder de lucru pentru programele ı̂n
C++, folder care se numeşte Programe C++. Aici vom salva toate programele C++ pe care
le vom scrie, eventual organizate pe mai multe subfoldere.
Click-dreapta cu mouse-ul şi selectăm “New -¿ Text document” ca ı̂n figura următoare.
APPENDIX C. ”INSTALARE” C++ C.1. KIT OJI 2017 379
Dacă vom executa două click-uri pe numele fşierului p01.cpp sau un click pentru a marca
fişierul şi apoi un ¡Enter¿, se va declanşa Code::Blocks cu p01.cpp ı̂n fereastra de editare şi, ce
este şi mai important, cu Programe C++ ca folder curent de lucru pentru Code::Blocks.
Adică, aici vor apărea toate fişiere generate de Code::Blocks pentru p01.cpp.
Figura C.9: Pregătit pentru a scrie cod de program C++ ı̂n Code::Blocks
APPENDIX C. ”INSTALARE” C++ C.1. KIT OJI 2017 381
Dacă avem fişierele p01.cpp, ..., p05.cpp, ı̂n folderul nostru de lucru, şi facem dublu-click pe
fiecare ... vor apărea toate ...
C.2 winlibs
C.2.1 GCC şi MinGW-w64 pentru Windows
Se descarcă de la
http://winlibs.com/#download-release
unul dintre fişierele:
winlibs-x86_64-posix-seh-gcc-10.2.0-llvm-11.0.0-mingw-w64-8.0.0-r
3.7z dimensiune fişier = 148 MB
winlibs-x86_64-posix-seh-gcc-10.2.0-llvm-11.0.0-mingw-w64-8.0.0-r
3.zip dimensiune fişier = 324 MB
winlibs-x86_64-posix-seh-gcc-10.2.0-mingw-w64-8.0.0-r3.7z dimensiune
fişier = 52.1 MB
winlibs-x86_64-posix-seh-gcc-10.2.0-mingw-w64-8.0.0-r3.zip dimensi-
une fişier = 141 MB
C.2.2 PATH
Trebuie pusă ı̂n PATH calea pentru D:\mingw64\bin\. În “Type here to search” scrieţi: path
şi apoi click pe “Edit the system environment variables”, ca ı̂n figura următoare:
APPENDIX C. ”INSTALARE” C++ C.2. WINLIBS 387
Se selecteaza “Path” şi click pe “Edit”. Apare fereastra “Edit Environment Variables”
C:¯path
Dacă totul este OK atunci se trece la instalarea IDE-ului preferat (Integrated Development
33
Environment ), de exemplu Code::Blocks 20.03 (sau Eclipse, Visual Studio Code, Dev C++,
NetBeans, şi altele).
C.2.3 CodeBlocks
CodeBlocks se poate descărca de la http://www.codeblocks.org/downloads/26. Sunt
mai multe variante dar eu am descărcat numai codeblocks-20.03-setup.exe care are 35.7 MB.
La instalare am lăsat totul implicit, deci ... Next, Next, ..., Next până la sfârşit!
La prima lansare ı̂n execuţie este necesară setarea locaţiei compilatorului de C++ (gcc-ul pe
care tocmai l-am instalat!).
33
https://en.wikipedia.org/wiki/Integrated_development_environment
https://ro.wikipedia.org/wiki/Mediu_de_dezvoltare
APPENDIX C. ”INSTALARE” C++ C.2. WINLIBS 390
Exponenţiere rapidă
În figura D.1 este considerat numărul nr 234 care ı̂n baza 2 se scrie sub forma 11101010 (celula
C10).
Pe R3 (rândul 3) este arătat ce se ı̂ntâmplă cu nr atunci când se fac ı̂mpărţiri succesive prin
baza 10: se ”şterge” ulima cifră (care este egală cu nr%10 adică ultima cifră este de fapt restul
ı̂mpărţirii lui nr la baza 10).
Pe R10 (rândul 10) este arătat ce se ı̂ntâmplă cu nr atunci când se fac ı̂mpărţiri succesive prin
baza 2: se ”şterge” ulima cifră (care este egală cu nr%2 adică ultima cifră este de fapt restul
ı̂mpărţirii lui nr la baza 2, la fel cum se ı̂ntâmplă ı̂n baza 10).
Observaţia 1. Cifrele se obţin ı̂n ordine inversă. Prima cifră obţinută ca rest este de fapt ultima
cifră din număr (vezi R4 şi R11).
Pe R6 şi R16 sunt precizate puterile bazei.
Valoarea numărului nr este suma produselor dintre cifre şi puterile corespunzătoare:
ı̂n baza 10: 4*1 + 3*10 + 2*100 = 234 (R3 şi R6)
ı̂n baza 2: 0*1 + 1*2 + 0*4 + 1*8 + 0*16 + 1*32 + 1*64 + 1*128 = 234 (R13 şi R16)
399
APPENDIX D. EXPONENŢIERE RAPIDĂ D.2. NOTAŢII, RELAŢII ŞI FORMULE 400
2 2 2 4 2 8 2 16
a0 a a1 a0 a a2 a1 a a3 a2 a a4 a3 a
2 32 2 64 2 128
a5 a4 a a6 a5 a a7 a6 a
Dacă notăm ek ”exponentul (puterea)” la care apare ak ı̂n produs, atunci putem observa
uşor că şirul e0 , e1 , e2 , e3 , ... se obţine prin ı̂mpărţiri succesive ale lui n prin 2 şi preluı̂nd restul
rezultatului. Pentru a folmaliza acest lucru vom considera şirul n0 , n1 , n2 , n3 , ... definit astfel:
n0 n,
w
nk nk1 ©2 (câtul ı̂mpărţirii!) k '1
Folosind aceste notaţii, putem scrie:
~
n0 n;
a0 a;
e n0 %2 " r0, 1x;
0
1 a0 , dacă e0 1;
p0
e
a00 sau, altfel scris: p0 w
1, dacă e0 0;
(D.2.1)
nk nk1 ©2 k ' 1; nk1 j 0 desigur ! ... dar şi nk1 j 1
ak1 , k ' 1;
2
a k
e k nk %2 " r0, 1x, k ' 0;
pk1 ak , k ' 0, dacă ek 1; ak ak modifică produsul pk1
1
p w
k k ' 0, dacă ek 0; ak 1 nu modifică produsul pk1
0
pk1 ,
D.4 Codul
Codul pentru relaţiile (D.2.1) devine:
Observaţia 2. În acest cod actualizarea lui p se face după actualizările pentru a şi n.
Observaţia 3. În codul următor actualizarea lui p se face ı̂naintea actualizărilor pentru a şi n,
corespunzător relaţiilor (D.4.2).
APPENDIX D. EXPONENŢIERE RAPIDĂ D.4. CODUL 402
~
iniţializări:
p1 1;
n 1 n;
a1 a;
calcul pentru k ' 0:
e
k nk1 %2 " r0, 1x; k ' 0 (D.4.2)
pk1 ak1 , k ' 0, dacă ek 1; ak1
1
ak1 modifică produsul pk1
k w
p
k ' 0, dacă ek 0; ak1
0
pk1 , 1 nu modifică produsul pk1
actualizări k ' 0:
a ak1 , k ' 0;
2
k
nk nk1 ©2 k ' 0; şi nk1 j 0 desigur !
APPENDIX D. EXPONENŢIERE RAPIDĂ D.4. CODUL 403
Observaţia 4. Instrucţiunile care sunt ”ı̂n plus” se pot elimina. Codul următor arată acest lucru:
Observaţia 5. Produsul poate deveni foarte mare şi din cauza asta se cere rezultatul modulo un
număr prim. Codul următor arată acest lucru:
14 a = (a * a)%MOD;
15 n = n / 2;
16 nropr=nropr+6; // n%2, p*a, a*a, (a * a)%MOD si n/2
17 }
18 return p;
19 }
20
21 int main()
22 {
23 int a=1234;
24 int n=1e+9; // 10ˆ9
25 int rezn; // rezultat exponentiere naiva
26
27 rezn=exponentiere_rapida(a,n);
28
29 cout<<"rezr = "<<rezn<<" nropr = "<<nropr<<"\n";
30
31 return 0;
32 }
33 /*
34 rezr = 376 nropr = 180
35
36 Process returned 0 (0x0) execution time : 0.021 s
37 Press any key to continue.
38 */
Numărul de operaţii:
cu metoda naivă acest număr este 2 000 000 000
cu metoda rapidă este 180.
Iar ca număr de operaţii ... una este să faci 2 miliarde de operaţii şi alta este să faci
numai 180 de operaţii de acelaşi tip (de fapt sunt numai 30 de paşi dar la fiecare pas se fac 5
sau 6 operaţii aritmetice)!
34
şi nu mai trebuie ”atâtea formule matematice”!
34
Este o glumă!
Appendix E
Căutare binară
E.1 Mijlocul = ?
Care este poziţia (indicele) ”mijlocului” unei zone dintr-un vector?
În figura E.1 sunt trei formule pentru determinarea mijlocului unei zone [i1, i2] din vector:
mij1 = (i1+i2)/2
mij2 = i1+(i2-i1)/2
mijdr = (i1+i2+1)/2
Toate trei dau rezultat corect dacă secvenţa [i1, ..., i2] are un număr impar de elemente.
Când secvenţa [i1, ..., i2] are un număr par de elemente apar două elemente la mijloc ... şi ...
primele două formule dau ”mijlocul din stânga” iar a treia formulă dă ”mijlocul din dreapta”.
Atunci când căutăm o valoare ı̂ntr-un vector avem la dispoziţie căutarea secvenţială. Dacă
ştim că vectorul este sortat (şir crescător de numere) atunci este bine să folosim căutarea binară
pentru că aceasta ”găseste” numărul căutat (sau ”spune” că acel număr nu este ı̂n şir)
ı̂n 10 paşi dacă şirul are 1000 de elemnte (de fapt 1024 dar ... aproximăm!),
ı̂n 20 de paşi dacă şirul are 1,000,000 de elemente,
ı̂n 30 de paşi dacă şirul are 1,000,000,000 de elemente,
...
Explicaţia simplă este că noi tot ı̂njumătăţim intervalul de căutare până când acest interval
rămâne cu un singur element ... şi vedem dacă acel element este cel căutat (dacă elementul rămas
nu este cel căutat ... ı̂nseamnă că acel element ”căutat” nu există ı̂n şir).
Putem să ne gândim la drumul invers: plecăm de la o secvenţă cu un singur element şi dublăm
secvenţa (invers faţă de cum am făcut ı̂njumătăţind secvenţa) până ajungem la o secvenţă care
are atâtea elemente câte a avut şirul iniţial (ne oprim imediat dacă am depăşit acel număr!).
Lungimile secvenţelor sunt: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, ...
Observăm că ı̂n 10 paşi, plecând din 1, ajungem să depăşim 1000.
407
APPENDIX E. CĂUTARE BINARĂ E.2. POZIŢIE OARECARE 408
70
71 int a[]={1, 1, 1, 3, 3, 4, 4, 4, 4, 4, 4, 4, 7, 7, 8, 8, 9, 9, 9, 9};
72
73 int n=sizeof(a)/sizeof(int);
74
75 cout<<"prima pozitie in vector = 0\n";
76 cout<<"ultima pozitie in vector = "<<n-1<<endl<<endl;
77
78 cautareBinaraIter1(x,a,0,n-1); // caut x in vectorul a[] de dimensiune=n
79
80 cout<<endl;
81 cout<<"nr cautari = "<<nrc<<"\n";
82
83 return 0;
84 }
55 int main()
56 {
57 int x; // caut x in vectorul a[]
58
59 //x=1; // secventa pe primele pozitii
60 x=2; // nu exista 2 ... ultima cautare in (dr,st) dr=st-1
61 //x=3; // exista numai un 3
62 //x=4; // exista secventa de 4
63 //x=9; // secventa pe ultimele pozitii
64
65 int a[]={1, 1, 1, 3, 3, 4, 4, 4, 4, 4, 4, 4, 7, 7, 8, 8, 9, 9, 9, 9};
66
67 int n=sizeof(a)/sizeof(int);
68
69 cout<<"prima pozitie in vector = 0\n";
70 cout<<"ultima pozitie in vector = "<<n-1<<endl<<endl;
71
72 cautareBinaraRec1(x,a,0,n-1); // caut x in vectorul a[] de dimensiune=n
73
74 cout<<endl;
75 cout<<"nr cautari = "<<nrc<<"\n";
76
77 return 0;
78 }
43 if(st==dr) // am terminat (gasit cel mai din stanga sau nu exista deloc)
44 {
45 if(v[st]==x)
46 {
47 cout<<"am gasit "<<x<<" pe pozitia "<<st<<"\n";
48
49 return true;
50 }
51
52 else
53 {
54 cout<<x<<" nu exista in vector ...!"<<" st="<<st<<" dr="<<dr
55 <<" v[st]="<<v[st]<<" v[dr]="<<v[dr]<<"\n";
56
57 return false;
58 }
59 }
60
61 return true; // sau return false; ... oricum nu ajunge aici ... !!!
62 }
63
64 // ------------------------------------------------------------------
65
66 int main()
67 {
68 int x; // caut x in vectorul a[]
69
70 //x=1; // secventa pe primele pozitii
71 x=2; // nu exista 2 ... ultima cautare in (dr,st) dr=st-1
72 //x=3; // exista numai un 3
73 //x=4; // exista secventa de 4
74 //x=9; // secventa pe ultimele pozitii
75
76 int a[]={1, 1, 1, 3, 3, 4, 4, 4, 4, 4, 4, 4, 7, 7, 8, 8, 9, 9, 9, 9};
77
78 int n=sizeof(a)/sizeof(int);
79
80 cout<<"prima pozitie in vector = 0\n";
81 cout<<"ultima pozitie in vector = "<<n-1<<endl<<endl;
82
83 cautareBinaraIter1(x,a,0,n-1); // caut x in vectorul a[] de dimensiune=n
84
85 cout<<endl;
86 cout<<"nr cautari = "<<nrc<<"\n";
87
88 return 0;
89 }
11 void afisv(int v[], int st, int dr) // afisez v[] intre st si dr
12 {
13 int i;
14 for(i=st; i<=dr; i++)
15 {
16 cout<<v[i]<<" ";
17 }
18 }
19
20 // ------------------------------------------------------------------
21
22 bool cautareBinaraIter1(int x, int v[], int st, int dr)
23 {
24 int mij;
25
26 while(st != dr)
27 {
28 nrc++;
29 mij=(st+dr+1)/2; // actualizez zona de cautare
30
31 cout<<"caut "<<x<<" in ";
32 afisv(v,st,dr);
33 cout<<"\n\n";
34
35 if(x >= v[mij])
36 st=mij; // caut in dreapta
37 else
38 dr=mij-1; // caut in stanga
39
40 cout<<"v["<<st<<"] = "<<v[st]<<" v["<<dr<<"] = "<<v[dr]<<endl;
41 //getchar();
42 }
43
44 if(st==dr) // am terminat (gasit cel mai din stanga sau nu exista deloc)
45 {
46 if(v[st]==x)
47 {
48 cout<<"am gasit "<<x<<" pe pozitia "<<st<<"\n";
49 return true;
50 }
51 else
52 {
53 cout<<x<<" nu exista in vector ...!"<<" st="<<st<<" dr="<<dr
54 <<" v[st]="<<v[st]<<" v[dr]="<<v[dr]<<"\n";
55 return false;
56 }
57 }
58
59 return true; // sau return false; ... oricum nu ajunge aici ... !!!
60 }
61 // ------------------------------------------------------------------
62
63 int main()
64 {
65 int x; // caut x in vectorul a[]
66
67 //x=1; // secventa pe primele pozitii
68 x=2; // nu exista 2 ... ultima cautare in (dr,st) dr=st-1
69 //x=3; // exista numai un 3
70 //x=4; // exista secventa de 4
71 //x=9; // secventa pe ultimele pozitii
72
73 int a[]={1, 1, 1, 3, 3, 4, 4, 4, 4, 4, 4, 4, 7, 7, 8, 8, 9, 9, 9, 9};
74 int n=sizeof(a)/sizeof(int);
75
76 cout<<"prima pozitie in vector = 0\n";
77 cout<<"ultima pozitie in vector = "<<n-1<<endl<<endl;
78
79 cautareBinaraIter1(x,a,0,n-1); // caut x in vectorul a[] de dimensiune=n
80
81 cout<<endl;
82 cout<<"nr cautari = "<<nrc<<"\n";
83
84 return 0;
85 }
APPENDIX E. CĂUTARE BINARĂ E.4. POZIŢIA DIN DREAPTA 414
”Vecini” ...
F.1 Direcţiile N, E, S, V
În figura F.1 sunt două modele (notaţii) utile ı̂n probleme ı̂n care se folosesc directiile N, E, S şi
V (NE, NV, SE şi SV se deduc uşor!).
415
APPENDIX F. ”VECINI” ... F.1. DIRECŢIILE N, E, S, V 416
417
INDEX INDEX 418
[1] Aho, A., Hopcroft, J., Ullman, J.D.; Data strutures and algorithms, Addison Wesley, 1983
[2] Andreica M.I.; Elemente de algoritmică - probleme şi soluţii, Cibernetica MC, 2011
[3] Andonie R., Gârbacea I.; Algoritmi fundamentali, o perspectivă C++, Ed. Libris, 1995
[4] Atanasiu, A.; Concursuri de informatică. Editura Petrion, 1995
[5] Bell D., Perr M.; Java for Students, Second Edition, Prentice Hall, 1999
[21] Knuth, D.E.; The art of computer programming, vol. 4A: Combinatorial algorithms, Part 1,
Addison Wesley, 2011.
[22] Lambert,K. A., Osborne,M.; Java. A Framework for Programming and Problem Solving,
PWS Publishing, 1999
[23] Laaksonen A.; Guide to competitive programming, Springer, 2017
[24] Livovschi, L.; Georgescu H.; Analiza şi sinteza algoritmilor. Ed. Enciclopedică, Bucureşti,
1986.
[25] Niemeyer, P., Peck J.; Exploring Java, O’Reilly, 1997.
419
BIBLIOGRAFIE BIBLIOGRAFIE 420
[26] Odăgescu, I., Smeureanu, I., Ştefănescu, I.; Programarea avansată a calculatoarelor personale,
Ed. Militară, Bucureşti 1993
[27] Odăgescu, I.; Metode şi tehnici de programare, Ed. Computer Lobris Agora, Cluj, 1998
[28] Popescu Anastasiu, D.; Puncte de articulaţie şi punţi ı̂n grafuri, Gazeta de Informatică nr.
5/1993
[29] Răbâea, A.; https://math.univ-ovidius.ro/Doc/Admitere/CentruPregatire
/2007/Info/Lista_probleme_2000-2007.pdf
[30] Răbâea, A.; https://math.univ-ovidius.ro/Doc/Admitere/CentruPregatire
/2007/Info/Rezolvari_C09.pdf
422
What’s the next?
ORNL’s Frontier First to Break the Exaflop Ceiling
Over time
the following steps
will lead you to the value
you seek for yourself
now!