Anda di halaman 1dari 59

Ana Intuneric

Manual de pregtire pentru facultatea de informatic


Ana ntuneric

Ana ntuneric

Ana Intuneric

Cuprins
Algoritmi de baz i idee................................................................................................................ 4
Covor ...............................................................................................................................................................................4
Numerus. ........................................................................................................................................................................5

Ciurul lui Eratostene....................................................................................................................... 6


descompunere ................................................................................................................................................................7
numarare ........................................................................................................................................................................7
extraprime ......................................................................................................................................................................7
secvene ..........................................................................................................................................................................8
factorial .........................................................................................................................................................................10
nrprime .........................................................................................................................................................................11
Descompunere n factori primi .....................................................................................................................................11
Vectori-teorie................................................................................................................................................................12
Cautare binara ..............................................................................................................................................................13
Numarare triunghiuri ....................................................................................................................................................14
Factorial ........................................................................................................................................................................15
Transport ......................................................................................................................................................................16
secventa ........................................................................................................................................................................17
Generare submultimi utilizand vectorul caracteristic ..................................................................................................18
235 ................................................................................................................................................................................18
maxD .............................................................................................................................................................................20
Reuniune de intervale...................................................................................................................................................21
tabara ............................................................................................................................................................................22
moretime ......................................................................................................................................................................23
sport ..............................................................................................................................................................................25
bal .................................................................................................................................................................................26
Carti...............................................................................................................................................................................27
baze ...............................................................................................................................................................................28
Panglica .........................................................................................................................................................................29
pluton............................................................................................................................................................................29
buline ............................................................................................................................................................................31

Numere mari.................................................................................................................................. 32
Suma a doua numere mari ...........................................................................................................................................32
Inmultirea unui numar mare cu un numar mic ............................................................................................................33
Inmultirea unui numar mare cu un numar mare ..........................................................................................................33
Scaderea a doua numere mari ......................................................................................................................................33
Impartirea unui numar mare la un numar mic .............................................................................................................33
Restul unui numar mare la un numar mic ....................................................................................................................33

Ana ntuneric

Ana Intuneric
next .............................................................................................................................................................................. 33

Idee ................................................................................................................................................. 34
politic............................................................................................................................................................................ 34
nasturi .......................................................................................................................................................................... 36
Generare tablou ........................................................................................................................................................... 37
Paranteze ..................................................................................................................................................................... 38
Selecie ......................................................................................................................................................................... 38
triunghi ......................................................................................................................................................................... 39
expresie ........................................................................................................................................................................ 40
Urmatoarea permutare lexicografica .......................................................................................................................... 41
Elementul majoritar ..................................................................................................................................................... 42
maxp............................................................................................................................................................................. 42

Matrice ............................................................................................................................................ 44
Pianjen........................................................................................................................................................................ 44
Maximum Sum. ............................................................................................................................................................ 44
cladiri ............................................................................................................................................................................ 45
cartele .......................................................................................................................................................................... 47

Tehnica Greedy ............................................................................................................................. 50


Problema spectacolelor_1 ........................................................................................................................................... 50
Problema programarii spectacolelor_2 ....................................................................................................................... 51
reactivi.......................................................................................................................................................................... 52
Bere .............................................................................................................................................................................. 53
Depozit ......................................................................................................................................................................... 55

iruri de caractere ......................................................................................................................... 55


TEXT.............................................................................................................................................................................. 55
comp ............................................................................................................................................................................ 57

Ana ntuneric

Ana Intuneric

Algoritmi de baz i idee


Covor
Bunica Marei ese un covor. Mara urmrete cu mare
atenie modelul i ncearc s-l reconstituie pe caietul de
matematic. Modelul este format din romburi. Primul romb,
de indice 1, are latura format din dou ptrele, al doilea
romb, de indice 2, are latura format din trei ptrele etc.
Un romb de indice i are latura format din i+1 ptrele.
Romburile sunt unite, consecutiv, ca n exemplul din
imaginea alturat. Sgeile indic sensul n care bunica
ese covorul.
Ca s nu uite modelul, Mara scrie pe caiet, ncepnd cu 1,
numere consecutive care s indice modul n care ese bunica covorul.
n exemplul urmtor este reprezentat modul n care se ese un model format din patru romburi.
Cerine
Cunoscndu-se numerele n i k s se
determine:
1. numrul maxim de romburi complete care
pot forma modelul unui covor, descris cu
ajutorul unui ir format din maximum n
numere naturale consecutive (primul
numr din ir fiind 1);
2. cel mai mic indice al unui romb ce conine
numrul k.
Date de intrare
Fiierul de intrare covor.in conine pe prima linie, separate prin spaiu, dou numere naturale: n
(reprezentnd numrul maxim de numere consecutive utilizate la descrierea unui model) i k (reprezentnd
un numr din irul celor n numere consecutive). Linia a doua conine una dintre valorile 1 sau 2 reprezentnd
cerina 1, dac se cere determinarea numrului maxim de romburi complete care pot forma modelul unui
covor descris cu ajutorul unui ir format din maximum n numere, respectiv cerina 2, dac se cere
determinarea celui mai mic indice al unui romb ce conine numrul k.
Date de ieire
Fiierul de ieire covor.out conine pe prima linie o valoarea natural reprezentnd numrul maxim de
romburi complete care pot forma modelul unui covor, descris cu ajutorul unui ir format din maximum n
numere, dac cerina a fost 1, respectiv un numr natural reprezentnd cel mai mic indice al unui romb ce
conine numrul k, dac cerina a fost 2.
Restricii i precizri
4 n,k 999999999; 1kn
Dac numrul k nu se afl pe niciunul dintre romburile complete ce pot fi construite folosind maximum
n numere, atunci rspunsul de la cerina 2 este 0.
Pentru rezolvarea corect a cerinei 1 se acord 30% din punctaj, iar pentru rezolvarea corect a
cerinei 2 se acord 70% din punctaj.
Exemple
covor.in
covor.out Explicaii
40 32
4
Cel mai mare numr de romburi ce pot forma un model descris cu maximum
1
40 de numere este 4.
40 32
3
Numrul 32 se afl pe cel de-al treilea romb.
2
37 7
2
Numrul 7 se afl pe cel de-al doilea i pe cel de-al treilea romb. Cel mai mic
2
indice al unui romb ce conine numrul 7 este 2.
Numrul 12 nu se afl pe niciunul dintre cele dou romburi ce pot forma un
14 12
0
2
model descris cu maximum 14 de numere.
Se observ c primul romb este format din 4 ptrtele, al doilea este format din 8 ptrele, rombul cu
indicele i este format din 4i ptrele.
Atunci cnd formez un covor, romburile se suprapun =>un model format din r romburi va fi descris printr-un
ir format din 4x1+4x2+....+4xr-(r-1) = 4r(r+1)/2-(r-1)=2r(r+1)-(r-1) numere.
Pentru determinarea numrului maxim de romburi complete care pot forma modelul unui covor, descris cu

Ana ntuneric

Ana Intuneric
ajutorul unui ir format din maximum nnumere, se calculeaz cel mai mare numr r cu proprietatea
2r(r+1)-(r-1)<=n.
Pentru determinarea celui mai mic indice al unui romb ce conine numrul k, se calculeaz numrul de
numere necesare pentru completarea romburilor la o trecere dus, respectiv ntors, de la rombul 1 la rombul r,
respectiv de la rombul r la rombul 1, i se calculeaz poziia lui k n raport cu aceast valoare.
Se observ c atunci cnd k este o valoare ce se afl pe dou romburi, primul romb pe care se gseste este
cel care se completeaz la prima trecere (dus).
int n,k,r,p,m,c;
int main()
{ f>>n>>k>>c;
r=1;
while(2*(r+1)*(r+2)-r<=n) r++;
if(c==1)
g<<r<<'\n';
else
{
if(k> 2*r*(r+1)-(r-1)) g<<0<<'\n';
else
{ p=1;
m=1+r*(r+1);
if(k<=m) { while(k>1+p*(p+1))p++;
g<<p<<'\n';
}
else
{ p=r;
while(k>(m+2*p-1))
{ m=m+2*p-1;
p--;
}
g<<p<<'\n';
}
}
}
f.close();g.close();return 0;
}

Numerus.
La ora de matematic distractiv, domnul profesor Numerus propune
elevilor si s completeze cu numere naturale o gril cu 6 coloane
numerotate cu literele mari A, B, C, D, E i F i cu un numr infinit de
linii. Grila va fi completat cu numere naturale, ncepnd cu numrul 1.
Pe liniile impare completarea se va face de la stnga la dreapta, iar pe
cele pare de la dreapta la stnga. Ultimul numr de pe o linie va fi
identic cu penultimul numr (n sensul completrii) de pe aceeai linie.
n figura alturat avei completate primele 7 linii ale grilei.
Deoarece pe tabl sau pe o foaie de hrtie numrul de linii este limitat,
deci grila poate fi efectiv completat doar pentru un numr mic de linii,
domnul profesor Numerus dorete ca elevii si s determine, cu
ajutorul calculatorului, coninutul unei anumite linii a grilei i locul sau
locurile pe care se poate afla un numr natural, suficient de mare.
Cerine:
Deducei regula dup care se completeaz linia k a grilei i scriei un
program care s citeasc numerele naturale k i n i care s determine:
a) Numerele naturale de pe linia k, vizualizate de la stnga la dreapta;
b) Linia pe care se afl n gril numrul natural n;
c) Coloana sau coloanele pe care se afl n gril numrul natural n.
Date de intrare
Fiierul numerus.in conine o singur linie pe care sunt scrise dou numere naturale k i n, separate printrun singur spaiu.
Date de ieire
Fiierul de ieire numerus.out va conine 3 linii:
a) pe prima linie, se vor scrie numerele de pe linia k a grilei, separate prin cte un spaiu, n ordinea

Ana ntuneric

Ana Intuneric
vizualizrii de la stnga la dreapta;
b) pe a doua linie, se va scrie un numr natural reprezentnd linia pe care se afl n gril numrul natural n;
c) pe a treia linie, se va scrie litera sau literele care reprezint coloana, respectiv coloanele pe care se afl n
gril numrul natural n.
Restricii i precizri:
Numerele k i n sunt naturale nenule
5 k 200000000
1 n 999999999
dac numrul n se afl pe mai multe coloane din gril, atunci pe a treia linie a fiierului numerus.out se
vor scrie literele corespunztoare acestor coloane, separate prin cte un spaiu.
Pentru rezolvarea cerinei a) se acord 40% din punctaj, pentru cerina b) 30% din punctaj i pentru
cerina c) 30% din punctaj.
Exemplu:
numerus.in
numerus.out
Explicaii
10 40

50 50 49 48 47 46
8
AB

int n,i,k,a,b,l,c;
int main()
{
f>>k>>n;
//a)
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';
//b)
l=n/5;
if(n%5!=0)l++;
g<<l<<'\n';
//c)
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;
}

Ciurul lui Eratostene


for(i=2; i*i<=n; i++)
if (ciur[i]==0)
// elimin toti multiplii lui i<=n
for(j=i*i; j<=n; j+=i) ciur[j]=1;

Ana ntuneric

Ana Intuneric
descompunere
S se descompun un numar natural n n toate modurile ca suma de dou numere prime. Dac nu exist
nicio descompunere, atunci s se afieze 0.
bool v[1001];int n,i,j,nrs;
int main()
{
f>>n;
nrs=0;
//ciurul lui Eratostene
for(i=2;i<=n;i++)
if(v[i]==0)
for(j=i*i;j<=n;j=j+i) v[j]=1;
if(n%2==1)
{
if(v[n-2]==0) g<<2<<'+'<<n-2<<'\n';
else g<<0<<'\n';
}
else
{
for(i=1;i<=n/2;i++)
if(v[i]==0 && v[n-i]==0)
{
nrs++;
g<<i<<'+'<<n-i<<' ';
}
if(nrs==0) g<<0<<'\n';
}
f.close();g.close();return 0;
}

numarare
Dandu-se un numar natural n, sa se determine numarul numerelor prime mai mici sau egale cu n, unde n se
va citi din fisierul eratostene.in, iar numarul numerelor prime se va afisa in fisierul eratostene.out.
bool prim[2000002];
long long i,j,n,nrprime;
int main()
{
f>>n;
for(i=2;i*i<=n;i++)
if(prim[i]==0){ nrprime++; for(j=i*i;j<=n;j=j+i) prim[j]=1;}
g<<nrprime<<\n;
f.close();g.close();return 0;
}

extraprime
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 numr, numrul obinut este tot numr prim. A
numit astfel de numere numere extraprime. De exemplu, numrul 317 este un numr extraprim: el este
numr prim i, n plus, dac eliminm cifra 3, obinem 17, care este prim; dac eliminm 1, obinem 37, care
este prim; dac eliminm 7, obinem 31, care este i el numr prim.
Cerin
Spunem c x este ntre a i b dac xa i xb. Fiind date dou valori naturale a i b, s se determine cte
numere extraprime exist ntre a i b, precum i cel mai mic i cel mai mare numr extraprim dintre a i b.
Date de intrare
Pe prima linie a fiierului de intrare extraprime.in se gsesc cele dou valori naturale a i b, separate printrun spaiu.
Date de ieire
Fiierul de ieire extraprime.out va avea 3 linii. Pe prima linie se va scrie un numr natural nr reprezentnd
numrul de numere extraprime dintre a i b. Pe linia a doua a fiierului de ieire se va scrie cel mai mic
numr extraprim dintre a i b, iar pe linia a treia a fiierului de ieire se va scrie cel mai mare numr
extraprim dintre a i b.
Restricii i precizri
10 < a b < 10000000;

Ana ntuneric

Ana Intuneric
Numrul 1 nu este prim;
Pentru datele de test exist ntotdeauna soluie;
Rspunsurile la cele trei cerine vor fi scrise exact pe linia indicat; n cazul n care nu cunoatei
rezolvarea la una dintre cerine, pe linia respectiv se va scrie valoarea -1;
Pentru numrul de numere extraprime scris corect se va acorda 40% din punctaj; pentru determinarea i
afiarea corect a celui mai mic numr extraprim se va acorda 30% din punctaj; pentru determinarea i
afiarea corect a celui mai mare numr extraprim se va acorda 30% din punctaj;
fiecare linie din fiierul de intrare se termin cu caracterul sfrit de linie.
Exemplu
extraprime.in

extraprime.out

Observaii

10 100

4
23
73

Se afl 4 numere extraprime mai mari dect 10 i mai mici


dect 100: 23, 37, 53 i 73.

O rezolvare posibil
bool v[10000002];
int q,p,x,y,c,i,j,a,b,max1,min1;
int main()
{
f>>a>>b;
//ciurul lui Eratostene cu inversarea valorilor 0 si 1
v[1]=1; v[2]=0;
for (i=2;i<=10000;i++)
if (v[i]==0) for (j=i*i;j<=10000000;j=j+i) v[j]=1;
c=0;
for (i=a;i<=b;i++)
if (v[i]==0) //daca este prim
{
y=i; p=1; q=0;
while (y>0)
{
x=i/p/10*p+i%p; //eliminam cifra de pe pozitia p (unitati sau zeci sau sute )
if (v[x]==1)//daca x nu este prim
{
q=1;break;
}
p=p*10;y=y/10;
}
if (q==0)
{
c++;
if (c==1) {min1=i;max1=i;}
else max1=i;
}
}
g<<c<<\n<<min1<<\n<<max1<<\n;
f.close();g.close();return 0;
}

secvene
Mariei i plac numerele prime i puterile numerelor prime. Pornind de la un numr prim p, ea
construiete noi numere, fiecare numr construit fiind un produs de forma p y (yN, y0) sau qpm, mN i q
un numr prim, numindu-le numere p-prime. De exemplu, numerele 2, 3, 4, 5, 6, 7, 8, 10, 12, 13, 14, 16, 17
sunt primele 13 numere 2-prime deoarece 2=21, 3=320, 4=22, 5=520, 6=321, 7=720, 8=23, 10=521, 12=322,
13=1320, 14=721, 16=24, 17=1720.
ntr-o zi Maria a gsit o foaie de hrtie, pe care era scris un ir format din n numere naturale nenule.
Cum pe lng numerele p-prime ea este pasionat i de secvene, i-a pus urmtoarea ntrebare:
cte secvene sunt pe foaie cu urmtoarele proprieti:
conin exact k numere p-prime;
ncep i se termin cu un numr p-prim.
n plus, Maria dorete s tie care este poziia de nceput i cea de final, pentru fiecare secven
descoperit, relative la irul scris pe foaia de hrtie.

Ana ntuneric

Ana Intuneric
Cerin
Scriei un program care s citeasc mai multe seturi de date, fiecare set fiind format din numerele n, p, k, cu
semnificaiile din enun, i irul cu n elemente a1, a2, a3, ... an, numerele Mariei. Programul va determina
pentru fiecare set de date numrul secvenelor ce conin exact k numere p-prime, precum i poziiile de
nceput i de final ale acestor secvene n irul din set.
Date de intrare
Pe prima linie a fiierului secvente.in se afl numrul D reprezentnd numrul de seturi de date din fiier.
Seturile de date sunt scrise n fiier pe linii succesive. Pentru fiecare set de date, prima linie conine cte trei
numere naturale: n (numrul de elemente de pe foaie), p i k (cu semnificaia din enun), separate prin cte
un spaiu, iar fiecare dintre urmtoarele n linii conine cte un numr natural al irului a 1, a2, a3, ... an,
numerele din irul Mariei.
Date de ieire
Fiierul secvente.out va conine D soluii corespunztoare celor D seturi de date. Pentru fiecare soluie
prima linie va conine un numr x reprezentnd numrul de secvene ce ndeplinesc proprietile cerute, iar
fiecare dintre urmtoarele x linii vor conine cte 2 numere naturale, separate printr-un spaiu, reprezentnd
poziia de nceput, respectiv de final a fiecrei secvene, linii ordonate cresctor dup poziia de nceput.
Dac n ir nu exist o astfel de secven, prima linie a setului va conine valoarea 0.
Restricii i precizri
1 D 15;
1 k n 15000;
2 p 30000; p este un numr natural prim
1 a1, a2, a3,...,an 30000; a1,a2,a3,...anN*(poziiile din ir sunt numerotate de la 1)
numrul 1 nu este p-prim.
o secven dintr-un ir este format din elemente aflate pe poziii consecutive n irul dat.
Exemplu:
secvente.in
secvente.out
Explicaii
2
2
Cum D=2, fiierul de intrare conine dou seturi de date.
532
12
Primul set de date: n=5, p=3, k=2 i a=(7, 27, 4, 45, 1). irul din acest
7
24
set conine urmtoarele numere 3-prime: a1=7 (numr prim), a2=27=33
27
0
(putere a lui 3) i a4=45=5*32 (numr prim nmulit cu o putere a lui 3).
4
n ir sunt dou secvene cu cte 2 numere 3-prime: a1, a2 respectiv a2,
45
a3, a4. Pe prima linie a fiierului de ieire se va scrie valoarea 2, iar pe
1
urmtoarele dou linii, poziiile de nceput i de final ale celor dou
357
secvene determinate.
3
irul a din al doilea set de date, n=3, p=5, k=7,a=(3, 4, 5), nu conine
4
nici o secven cu proprietatea cerut. Astfel, n fiierul de ieire, pe
5
cea de-a patra linie, se va scrie valoarea 0.
Timp de rulare/test: 1 secund
1. Pana la 90 puncte
La citire se verific pentru fiecare numr daca este p-prim. Mai nti se mparte numrul n mod repetat la p
att timp ct este posibil, iar apoi verific dac valoarea rmas este numr prim.
Pozitiile numerelor prime se memoreaza ntr-un vector V. S notm cu m dimensiunea lui V. Daca avem k>m
se afiseaza 0. In caz contrar sunt m-k+1 perechi care indeplinesc conditia, acestea determinndu-se afind
perechi de valori din V cu proprietatea c se afla la distana k-1 una de cealalt.
n prima etapa, verificarea primalitii unui numr se face parcurgand divizorii acestuia pn la radicalul su,
adic n O( ). Complexitate O(n )
2. Alte doua variante de 100 puncte
a. Se pot determina toate numerele prime pn la n folosind ciurul lui Eratostene cu o complexitate O(nlgn)
sau
b. se pot memora numerele prime ntr-un vector de constante (rmne ns O(lgp n) gasirea puterii lui p
pentru fiecare numar). Cautarea n vectorul de numere prime se rezolv folosind cautarea binar.
int poz[15001],x,n,p,k,m;
bool ciur[30001];
int main()
{
int i,j,D;
//ciur
for(i=2;i*i<=30000;i++)
if(ciur[i]==0)
for(j=i*i;j<=30000;j=j+i)ciur[j]=1;

Ana ntuneric

Ana Intuneric
f>>D;
for(j=1;j<=D;j++)
{
f>>n>>p>>k;m=0;int gasit=0;
for(i=1;i<=n;i++)
{
f>>x;
if(x!=1)
{
while(x%p==0) x/=p;
if(ciur[x]==0) poz[++m]=i;
if(m>1 && poz[m]-poz[m-1]==k-1) gasit=1;
}
}
if(gasit)
{
g<<m-1<<'\n';
for(i=1;i<=m-k+1;i++)
g<<poz[i]<<' '<<poz[i+k-1]<<'\n';
}
else g<<0<<'\n';
}
f.close();g.close();return 0;
}

factorial
Factorialul unui numr natural nenul n, notat n!, se definete ca fiind produsul numerelor naturale de la 1 la
n. Una dintre modalitile de reprezentare a factorialului este prin enumerarea factorilor primi pe care i
conine i a exponenilor acestora.
Cerin
Fiind dat un numr natural n, scriei un program care determin suma exponenilor factorilor primi
corespunztori descompunerii n factori primi a lui n factorial.
Date de intrare
Fiierul de intrare factorial.in conine pe prima linie numrul natural n.
Date de ieire
Fiierul de ieire factorial.out va conine pe prima linie un numr reprezentnd suma exponenilor numerelor
prime din descompunerea n factori primi a lui n!.
Restricii i precizri
2 n 100000
factorial.in

factorial.out

Explicaii

5! = 1*2*3*4*5 = 23 * 31 * 51
3+1+1=5
Se genereaz toate numerele prime mai mici sau egale cu n utiliznd ciurul lui Eratostene.
Matematic putem afla puterea la care apare numrul prim P n N! folosind formula
[N/P] + [N/P2] + [N/P3] + ...
Aplicnd aceast formul pentru toate numerele prime mai mici sau egale cu n i nsumnd rezultatele,
obinem soluia problemei.
5

int n,i,j,ciur[100001],s,np,x;
int main()
{
f>>n;
for (i=2;i*i<=n;i++)
if (!ciur[i])
for (j=i*i;j<=n;j+=i) ciur[j]=1;
for (i=2;i<=n;i++)
{
if (!ciur[i])
{
x=i;
while (n/x!=0)
{
s+=n/x; x*=i;
}

Ana ntuneric

10

Ana Intuneric
}
}
g<<s<<'\n';f.close();g.close(); return 0;
}

nrprime
Gheorghe a nvat la coal despre numere prime. A nvat c un numr este prim, dac se divide doar
cu 1 i cu el nsui(1 nu este considerat numr prim). A aflat c exist algoritimi foarte eficieni care pot
determina dac un numr este prim sau nu, n timp chiar sub polinomial. Din pcate aceti algoritmi sunt
foarte complicai, i Gheorghe s-a gndit la o aproximare. Ideea lui este s consideri un numr prim dac nu
se divide la primele K numere prime.
Cerin
Demonstreaz c ideea lui Gheorghe este doar o aproximare. Dndu-se un numr K (1 K 100.000), afl
cel mai mic numar N care nu este divizibil cu primele K numere prime, dar nu este prim.
Date de intrare
Pe prima linie din fiierul prim.in se va afla numrul K.
Date de ieire
Pe prima linie a fiierului prim.out se va gasi numarul N cutat.
Exemplu
Pentru valoarea 3 ca dat de intrare se va afia 49, pentru c primele 3 numere prime sunt 2, 3, 5. Numerele
care nu sunt divizibile cu 2, 3 sau 5 sunt : 7, 11, 13, 17, 19, 23, 31, 37, 41, 47, 49, .. 49 este cel mai mic
numar care nu este prim.
Soluie
Deoarece nu tim de cte numere vom avea nevoie, am declarat vectorul ciur cu 1000000 elemente. Pn
acolo vom face parcurgerea vectorului, aplicnd Ciurul lui Eratostene. Variabila nrp desemneaz numrul de
parcurgeri, astfel, cnd se ajunge la k+1 parcurgeri n va lua valoarea ptratului lui i, pn atunci multiplii
lui i fiind eliminai, valoarea lor din vector devenind 0. Condiia de la nceput if(prim[i]) se asigur c se vor
verifica doar numerele prime. Datorit faptului c ptratul unui numr prim nu se poate divide la numrul prim
anterior, ne dm seama c soluia i*i dup k+1 parcurgeri este cea corect.
bool ciur[1000001];
int k,nrp,gasit,i,j;
long long n;
int main()
{
f>>k;f.close();
for(i=2;i<dim;i++) ciur[i]=1;
for(i=2;i<=dim && !gasit;i++)
if(ciur[i])
{
nrp++;
if(nrp==k+1)
{
n=i*i;g<<n<<endl;gasit=1;
}
for(j=i+i;j+i<=dim;j=j+i) ciur[j]=0;
}
g.close();return 0;
}

Descompunere n factori primi


d=2;
while(n>1)
{
puterea=0;
while(n%d==0) puterea++,n=n/d;
if(puterea>0) g<<d<<" la puterea "<<puterea<<endl;
d=d+1;
}

Observaie: dac n=f1p1*f2p2**fkpk, atunci numrul su de divizori este (p1+1)*(p2+1)**(pk+1)


dac n=f1p1*f2p2**fkpk, atunci numrul de numere mai mici dect n i prime cu n
este: n*(1-1/f1)*(1-1/f2)*...*(1-1/fk)

Ana ntuneric

11

Ana Intuneric
Vectori-teorie
Inserarea elementului x pe poziia i n
vectorul v de dimensiune n

tergerea elementului de pe poziia i


din vectorul v cu n componente
for(k=i;k<n;k++) v[k]=v[k+1];
n--;

n++;
for(k=n;k>i;k--) v[k]=v[k-1];
v[i]=x;
Permutarea circular a vectorului vMn(R) cu o poziie spre stnga
aux=v[1];
for(i=1;i<=n-1;i++) v[i]=v[i+1];
v[n]=aux;
Interclasarea a doi vectori a[m] i b[n]
Cutarea binar( cutarea lui nr se
sortai cresctor
face ntr-un vector a[n] sortat
cresctor)
i=1;j=1;k=0;
st=1;dr=n;gasit=0;
while(i<=m && j<=n)
while(!gasit && st<=dr)
if(a[i]<b[j])
{k++;c[k]=a[i];i++;}
{
else
{k++;c[k]=b[j];j++;}
mijloc=(st+dr)/2;
while(i<=m)//s-a terminat vectorul b
if(nr==a[mijloc]) gasit=1;
{k++;c[k]=a[i];i++;}
else if(nr<a[mijloc]) dr=mijloc-1;
while(j<=n)// s-a terminat vectorul a
else st=mijloc+1;
{k++;c[k]=b[j];j++;}
}
O solutie cu aceeasi complexitate teoretica dar mai rapida in practica foloseste cautarea binara pe biti:

int N, A[N];
int cautare_binara_biti(int val)
{
inti, step;
for(step = 1; step < N; step <<= 1);
for(i = 0; step; step >>= 1)
if(i + step < N && A[i + step] <= val)
i += step;
return i;
}

int n, v[51];//qsort-----------O(n )
void QS(int st, int dr)
{
int i=st,j=dr,aux;
int pivot=v[(st+dr)/2];
// cautam pivotul a.i. toate elem. aflate la stanga sa sa fie mai mici si toate elem. aflate la dreapta sa sa fie mai mari
while (i <= j)
{
while (v[i]<pivot) i++;
while (v[j]>pivot) j--;
if (i <= j)
{
aux=v[i];v[i]= v[j];v[j]=aux;
i++;j--;
}
}
//apelul recursiv
if(st<j) QS(st,j);
if(i<dr) QS(i,dr);
}

Ana ntuneric

12

Ana Intuneric
void interc(int st, int m, intdr)
{
//a[st---i---m];a[m+1---j---dr]
int b[11],k,i,j;
i=st;j=m+1;k=0;
while(i<=m && j<=dr)
if(a[i]<=a[j]){b[++k]=a[i];i++;}
else {b[++k]=a[j];j++;}
while(i<=m)
{b[++k]=a[i];i++;}
while(j<=dr)
{b[++k]=a[j];j++;}
//refacere a[st]..i.a[dr]
j=1;
for(i=st;i<=dr;i++)a[i]=b[j++];
}
void DEI(intst,intdr)
{
if(st<dr)
{
int m=(st+dr)/2;
DEI(st,m);
DEI(m+1,dr);
interc(st,m,dr);
}
}

Cautare binara
Se da un sir de numere ordonat crescator cu N elemente, si se cere sa se raspunda la M intrebari de tipul:
0 x - cea mai mare pozitie pe care se afla un element cu valoarea x sau -1 daca aceasta valoare nu se
gaseste in sir
1 x - cea mai mare pozitie pe care se afla un element cu valoarea mai mica sau egala cu x in sir. Se
garanteaza ca cel mai mic numar al sirului este mai mic sau egal decat x
2 x - cea mai mica pozitie pe care se afla un element cu valoarea mai mare sau egala cu x in sir. Se
garanteaza ca cel mai mare numar din sir este mai mare sau egal decat x
Date de intrare
Pe prima linie a fisierului de intrare cautbin.in se afla numarul N reprezentandnumarul de elemente ale
sirului. Pe urmatoarea linie se gasesc N numere reprezentand elementele sirului. Linia a treia contine
numarul M reprezentand numarul de intrebari. Apoi urmeaza M linii, fiecare cu unul dintre cele 3 tipuri de
intrebari.
Date de iesire
In fisierul de iesire cautbin.out se vor afisa M linii reprezentand raspunsul la cele M intrebari.
Restrictii
1 N 100 000
1 M 100 000
Elementele sirului vor fi numere strict pozitive si se vor incadra pe 31 de biti
Exemplu
cautbin.in
cautbin.out
5
4
13335
4
3
2
03
13
23

Ana ntuneric

13

Ana Intuneric
int n,m,v[100010];
int cb0(int s, int d, int val)
{
int m;
while(s <= d)
{
m = (s + d) / 2;
if (v[m] <= val) s = m + 1;
else d = m - 1;
}
m = (s + d) / 2;
if (v[m] > val) m--;
if (v[m] == val) return m;
return -1;
}
int cb1(int s, int d, int val)
{
int m, n = d;
while(s < d)
{
m = (s + d) / 2;
if (v[m] <= val) s = m + 1;
else d = m;
}
m = (s + d) / 2;
if (v[m] > val) m--;
return m;
}
int cb2(int s, int d, int val)
{
int m;
while (s < d)
{
m = (s + d) / 2;
if (v[m] < val) s = m + 1;
else d = m;
}
m = (s + d) / 2;
if (v[m] < val) m++;
return m;
}
int main()
{
int i, tip, val;
f>>n;
for (i = 1; i <= n; i++) f>>v[i];
f>>m;
for (i = 1; i <= m; i++)
{
f>>tip>>val;
if (tip == 0) g<<cb0(1, n, val)<<'\n';
if (tip == 1) g<<cb1(1, n, val)<<'\n';
if (tip == 2) g<<cb2(1, n, val)<<'\n';
}
f.close();g.close();return 0;
}

Recomandri pentru implementare


n cazul utilizrii instructiunii m=(st+dr)/2 pot aprea erori nedorite. st+dr poate depasi tipul de data al
variabilelor st si dr. De asemenea pot aparea erori in cazul in care capetele intervalului pot lua si valori
negative. De aceea se recomanda scrierea instructiunii mid = lo + (hi-lo)/2 in loc de mid = (st+dr)/2.
Numarare triunghiuri

Ana ntuneric

14

Ana Intuneric
Andrei are N betisoare de lungimi nu neaparat diferite. El vrea sa afle in cate moduri poate alege trei
betisoare astfel incat sa poata forma cu ele un triunghi.
Cerinta
Dandu-se lungimile betisoarelor aflati in cate moduri se pot alege trei dintre ele astfel incat sa se poata forma
un triunghi cu ele.
Date de Intrare
Pe prima linie a fisierului nrtri.in se afla N, numarul de betisoare. Pe urmatoarea linie se afla N numere
separate prin spatii ce reprezinta lungimile betisoarelor.
Date de Iesire
Fisierul nrtri.out contine un singur numar ce reprezintanumarul cerut de problema.
Restrictii si precizari
1 N 800
1 lungimea unui betisor 30000
se considera triunghiuri si cele care au un unghi de 180 de grade si celelalte doua de 0 grade
(2 segmente coliniare se confunda cu al 3-lea)
pentru 75 de puncte se garanteaza 1 N 150
Exemplu
nrtri.in
nrtri.out
4
2374

Explicatii
Singurele triunghiuri care se pot forma sunt alcatuite din urmatoarele betisoare (date prin numarul de
ordine):
1, 2, 4
2, 3, 4
#include <fstream>
#include <algorithm>
using namespace std;
ifstream f("nrtri.in");
ofstream g("nrtri.out");
int v[801],s,S,i,j,dr,st,mij,n,p;
int main()
{
f>>n;
for(i=1;i<=n;i++)
f>>v[i];
sort(v+1,v+n+1);
for(i=1;i<=n;i++)
for(j=i+1;j<=n;j++)
{
p=0;
s=v[i]+v[j];
st=j;dr=n;
while(st<=dr)
{
mij=(st+dr)/2;
if(s<v[mij]){dr=mij-1;}
else{st=mij+1;p=mij;}
}
if(p!=0)S+=p-j;
}
g<<S;
return 0;
}

Factorial
Se da un numar intreg P. Sa se gaseasca cel mai mic numar natural strict pozitiv N pentru care N! are
exact P cifre de 0 la sfarsit. Se stie ca N! = 1 * 2 * 3 * .... * (N - 1) * N.
Date de intrare
Fisierul fact.in va contine pe prima linie numarulintreg P.

Ana ntuneric

15

Ana Intuneric
Date de iesire
Pe prima linie a fisierului fact.out se va scrie acel numar N care indeplinestecondiitle impuse sau -1 daca nu
exista un astfel de N.
Restrictii
8
0 P 10
Exemple
fact.in
fact.out
0
1
2
10
10
45
int main()
{
Int n , c ;
long long st , dr , m , x ;
st=1 ;dr=1000000000 ;
f>>n ;
while(st<=dr)
{
m=(st+dr)/2 ;
x=m; c=0;
while(m!=0)
{
c=c+m/5 ;
m=m/5;
}
if(c==n)
{
if(x-x%5==0) g<<"1";
else g<<x-x%5 ;
dr=-1 ;
}
else if(c>n) dr=(st+dr)/2-1 ;
else st=(st+dr)/2+1 ;
}
if(dr!=-1) g<< "-1";
return 0;
}

Transport
O firma ce produce saltele cu apa are N astfel de saltele intr-un depozit, asezate una peste alta (intr-o stiva).
Fiecare saltea este caracterizata prin volumul sau (un numarintreg, exprimat in decimetri cubi). Pentru a le
transporta la magazin, in vederea comercializarii, firma va inchiria un camion care va avea o capacitate
egala cu C decimetri cubi. Acest camion va trebuie sa efectueze cel mult K transporturi (s-a estimat durata
fiecarui transport si s-a ajuns la concluzia ca daca s-ar efectua mai mult de Ktransporturi, camionul ar ajunge
la magazin in afara orelor de aprovizionare, astfel ca saltelele nu ar putea fi comercializate). La fiecare
transport, camionul poate fi incarcat cu saltele, cu conditia ca suma volumelor saltelelor incarcate in camion
sa nu depaseasca capacitatea camionului. Deoarece saltele sunt asezateintr-o stiva, nu este posibil sa se
incarce in camion o saltea decatdupa ce au fost incarcate (si eventual transportate) toate saltelele de
deasupra ei. Intrucat costul inchirierii camionului depinde de capacitatea acestuia, firma doreste sa inchirieze
un camion cu capacitatea cat mai mica care sa poata transporta toate cele N saltele, efectuand
maxim K transporturi.
Date de intrare
Pe prima linie a fisierului transport.in se afla numerele intregi N si K (separate printr-un spatiu). Pe fiecare din
urmatoarele N linii se afla un numarintreg, reprezentand volumul unei saltele. Prima din aceste N linii contine
volumul saltelei din varful stivei, a doua linie contine volumul celei de-a doua saltele, etc.
Date de iesire
In fisierul transport.out vetiafisa un singur numarintreg, reprezentand capacitatea minima pe care trebuie sa
o aiba camionul pentru a putea transporta cele N saltele efectuand maxim K transporturi.

Ana ntuneric

16

Ana Intuneric
Restrictii si precizari
1 N 16 000
1 K 16 000
1 volumul oricarei saltele 16 000
Exemplu
transport.in
transport.out
63
8
7
3
2
3
1
4
Explicatie: la primul transport este incarcata prima saltea (care are volumul 7). La cel de-al doilea transport
sunt incarcate saltele 2 si 3 (volumul total este 3 + 2 = 5). La cel de-al treilea transport sunt incarcate saltele
4, 5 si 6 (volumul total este 3 + 1 + 4 = 8).
int n, li, ls, m, s, sol, a[16010], i, Max, nr, k;
int main()
{
f>>n>>k;
for(i=1;i<=n;i++)
{
f>>a[i];
if(a[i]>Max) Max=a[i];
s+=a[i];
}
li=Max;
ls=s;
m=(li+ls)/2;
while(li<=ls)
{
s=0;
nr=0;
for(i=1;i<=n;i++)
{
s+=a[i];
if(s>m && i!=n) nr++, s=a[i];
else if(i==n) nr++;
}
if(s-m>0) nr++;
if(nr<=k)
{
sol=m;ls=m-1;
}
else li=m+1;
m=(li+ls)/2;
}
g<<sol;
return0;
}

secventa
Din fisierul lungime.in se citeste un numar n mai mic decat 2000000000 si apoi se citesc n numere naturale.
Afisati in fisierul lungime.out lungimea celei mai lungi secvente din numerele citite care are proprietatea ca
incepe si se termina cu aceeasi valoare si nu mai contine acea valoare (inafara de primul si ultimul element
al secventei).
Exemplu:
lungime.in
lungime.out
14
7
32434234567255
int main()
{

Ana ntuneric

17

Ana Intuneric
int n,x,ap1[100]={0}, ap2[100]={0};
f>>n;
for(int i=1;i<=n;i++)
{
f>>x;
if(ap1[x]==0) ap1[x]=i;//prima aparitie
else if(ap2[x]==0) ap2[x]=i;
else if(i-ap2[x]>ap2[x]-ap1[x])
{
ap1[x]=ap2[x];ap2[x]=i;//refac prima si ultima aparitie
}
}
int maxx=0;
for(int i=0;i<100;i++)
if(ap2[i]-ap1[i]>maxx) maxx=ap2[i]-ap1[i];
g<<maxx+1<<endl;
f.close();g.close();return 0;
}

Generare submultimi utilizand vectorul caracteristic


Se citeste o multime a cu n elemente numere naturale. Sa se afiseze toate submultimile multimii a.
Indicatie: Se contruiesc intr-un vector caracteristic toate modalitatile de a pune valorile 0 si 1 pe n pozitii si
corespunzator fiecarei variante se asociaza o submultime astfel: pozitiile pe care este valoarea 1 corespund
elementelor alese in submultime, iar cele cu valoarea 0 celor care nu sunt alese in submultime.
Exemplu: Pentru n=5 si elementele 1 3 5 7 9 se genereaza:
0 0 0 0 0 - multimea vida
1 0 0 0 0 - submultimea {1}
0 1 0 0 0 - submultimea {3}
1 1 0 0 0 - submultimea {1, 3}
0 0 1 0 0 - submultimea {5}
...
1 1 0 1 1 - submultimea {1, 3, 7, 9}
etc
while(p[n+1]!=1)
{
for(i=1;i<=n;i++)
if(p[i]==1) g<<a[i]<<" ";
g<<endl;
i=1;
while(p[i]==1 && i<=n) //caut primul 0 de la stanga la dreapta
{
p[i]=0;i++;
}
p[i]=1;
}

235
Definim o putere a lui 3 un numr de forma 3k, (k numr natural strict pozitiv), o putere a lui 5 un numr de
forma 5k (k numr natural strict pozitiv) iar o putere a lui 2 un numr de forma 2k (k numr natural strict
pozitiv).
Se d un ir de n numere naturale. Plecnd de la acest ir, formm un nou ir prin eliminarea tuturor
numerele care nu sunt puteri ale lui 3 i nici puteri ale lui 5. Ordinea relativ ntre numerele care nu sunt
eliminate se pstreaz.
Cerine
S se determine cte numere conine irul nou format.
S se determine deasemenea numrul de secvene avnd lungimea egal cu o putere a lui 2 existente n
irul nou format n care numrul de puteri ale lui 3 este egal cu numrul de puteri ale lui 5. O secven este
format din elemente aflate pe poziii consecutive n acest ir nou format iar lungimea unei secvene este
egal cu numrul de elemente pe care aceasta l conine.
Date de intrare
Pe prima linie in fiierul 235.in se afla un numr natural n. Pe fiecare dintre urmtoarele n linii cte un numr
natural mai mare decat 1 reprezentnd numerele irului iniial.
Date de ieire

Ana ntuneric

18

Ana Intuneric

Pe prima linie a fiierului 235.out se va afla o valoare natural m care va reprezenta numrul de elemente
rmase n ir dup eliminare. Pe a doua linie se va afla o valoare natural s reprezentnd numrul de
secvene din irul nou format care au proprietile cerute.
Restricii i precizri
2 n 500000
Numerele din irul iniial sunt numere naturale din intervalul [2,2000000000].
Se garanteaz c m 40000 pentru fiecare set de date de intrare.
Pentru determinarea corect a valorii numrului m se acord 30% din punctaj iar pentru determinarea
corect a ambelor valori (m i s) se acord 100% din punctaj.
Exemplu:
235.in
8
625
125
5
9
15
81
100
125

235.out
6
4

Explicaii
irul rmas dup eliminarea numerelor care nu sunt puteri
ale lui 5 sau ale lui 3 are 6 elemente:
625, 125, 5, 9, 81, 125.
n acest ir sunt:
- dou secvene formate din dou valori care conin un
numr egal de puteri ale lui 3 i ale lui 5: 5,9 i 81,125;
- dou secvene de patru numere care conin un numr egal
de puteri ale lui 3 i ale lui 5: 125, 5, 9, 81 i 5, 9, 81, 125

Timp de rulare/test: 1 secund


Ineficient timp, 50 puncte
int n,k,i,x,m,L,p,nr3,nr5,nrs;
unsigned int v[40001];
int main()
{
f>>n;//mai eficient timp ar fi sa constr
//un vector cu puterile lui 3 si sa cautam binar in el pe x
for(i=1;i<=n;i++)
{
f>>x; nr3=nr5=0;
while(x%3==0){x=x/3; nr3++;}
if(x==1 && nr3>0) v[++m]=-1;
while(x%5==0){x=x/5;nr5++;}
if(x==1 && nr5>0 && nr3==0) v[++m]=1;
}
g<<m<<'\n';
//verificam secventele de lungime putere a lui 2
for(L=2;L<=m;L*=2)
{
int s=0;
for(i=1;i<=L;i++)s+=v[i];
if(s==0) nrs++;
for(i=2;i<=m-L+1;i++)
{
s=s-v[i-1]+v[i+L-1];//actualizare suma de puteri
if(s==0)nrs++;
}
}
g<<nrs<<'\n';
return 0;
}

Rezolvare de 100 de puncte


int n,k,i,x,m,L,nr3,nr5,nrs,gasit,mij,st,dr;
int v[40001],p[33]={3,5,9,25, 27, 81, 125, 243, 625, 729, 2187, 3125, 6561, 15625,
19683, 59049, 78125, 177147, 390625, 531441, 1594323, 1953125, 4782969, 9765625,
14348907, 43046721, 48828125, 129140163, 244140625, 387420489, 1162261467, 1220703125} ;
int main()
{

Ana ntuneric

19

Ana Intuneric
f>>n;//mai eficient timp ar fi sa constr
//un vector cu puterile lui 3 si sa cautam binar in el pe x
for(i=1;i<=n;i++)
{
f>>x;
//caut binar x in vectorul p[]
st=1;dr=32; gasit=0;
while(st<=dr && !gasit)
{
mij=(st+dr)/2;
if(x==p[mij]) gasit=1;
else if(x<p[mij]) dr=mij-1;
else st=mij+1;
}
if(gasit)
if(x%3==0) v[++m]=-1;
else v[++m]=1;
}
g<<m<<'\n';
//verificam secventele de lungime putere a lui 2
for(L=2;L<=m;L*=2)
{
int s=0;
for(i=1;i<=L;i++)s+=v[i];
if(s==0) nrs++;
for(i=2;i<=m-L+1;i++)
{
s=s-v[i-1]+v[i+L-1];//actualizare suma de puteri
if(s==0)nrs++;
}
}
g<<nrs<<'\n';
return 0;
}

maxD
Fiind elev n clasa a IX-a, George, i propune s studieze capitolul divizibilitate ct mai bine. Ajungnd la
numrul de divizori asociat unui numr natural, constat c sunt numere ntr-un interval dat, cu acelai
numr de divizori.
De exemplu, n intervalul [1, 10], 6, 8 i 10 au acelai numr de divizori, egal cu 4. De asemenea, 4 i 9 au
acelai numr de divizori, egal cu 3 etc.
Cerin
Scriei un program care pentru un interval dat determin care este cel mai mic numr din interval ce are
numr maxim de divizori. Dac sunt mai multe numere cu aceast proprietate se cere s se numere cte
sunt.
Date de intrare
Fiierul de intrare maxd.in conine pe prima linie dou numere a i b separate prin spaiu (ab) reprezentnd
extremitile intervalului.
Date de ieire
Fiierul de ieire maxd.out va conine pe prima linie trei numere separate prin cte un spaiu min nrdiv contor
cu semnificaia:
min = cea mai mic valoare din interval care are numr maxim de divizori
nrdiv = numrul de divizori ai lui min
contor = cte numere din intervalul citit mai au acelai numr de divizori egal cu nrdiv
Restricii i precizri
1 a b 1000000000
0 b-a 10000
Exemplu

Explicaie

Ana ntuneric

20

Ana Intuneric
n primul exemplu, 6 este cel mai mic numar din interval care are maxim de divizori egal cu 4 i unt 3 astfel
de numere (6, 8, 10).
n cel de-al doilea exemplu, 200 are 12 divizori, iar n intervalul [200,200] exist un singur numr cu aceast
proprietate.
int a,b,d,m,i,j,nrd=1,k=0;
int min=a,nrdiv=1,contor=0;
int v[10001];

[a,b]
a+k

v[0],v[b-a+1]
v[k]

int main()
{
f>>a>>b;
for(i=a;i<=b;i++)
{
j=i;nrd=1;d=2;
while(j>1)
//fac descompunerea in factori primi
{
m=0;
while(j%d==0) m++,j=j/d;
//daca multiplicitatea lui d in n este diferita de 0
if(m!=0)
nrd=nrd*(1+m); //atunci inmultesc numarul de divizori de pana acum cu 1+m
d++; //trec la urmatorul divizor posibil
}
v[k]=nrd; //al catelea numar din interval este
k++; // primeste numarul de divizori pentru numarul a+k
if(nrd>nrdiv) nrdiv=nrd; //daca numarul de divizori este mai mare ca cel gasit pana acum atunci el este noul nrdiv
}
for(i=0;i<(b-a+2);i++) //parcurg vectorul v
{
if(v[i]==nrdiv) contor++;
//daca contine numarul nrdiv atunci il numar
if(v[i]==nrdiv && contor==1) min=a+i;
//si retin care a fost primul numar cu nrdiv divizori
}
g<<min<<' '<<nrdiv<<' '<<contor<<\n;
f.close(); g.close();return 0;
}

Reuniune de intervale
Se citeste un numar natural n si apoi n intervale deschise cu
extremitatile numere intregi. Afisati reuniunea celor n intervale citite.
struct interval{int a,b;}X[100];
int n;

date.in
4
16
3 4.5
79
56

date.out
(1,6) U (7,9)

int main()
{
int i,j,xr,yr;
interval aux;
f>>n;
for(i=1;i<=n;i++) f>>X[i].a>>X[i].b;//citim capetele fiecarui interval
for(i=1;i<n;i++)//sortam intervalele dupa capatul din dreapta
for(j=i+1;j<=n;j++)
if(X[i].b>X[j].b)
{
aux=X[i]; X[i]=X[j]; X[j]=aux;
}
xr=X[1].a; yr=X[1].b;
for(i=2;i<=n;i++)
if(X[i].a<yr)
{
if(X[i].a<xr) xr=X[i].a;
yr=X[i].b;
}
else
{
g<<"("<<xr<<","<<yr<<") U ";

Ana ntuneric

21

Ana Intuneric
xr=X[i].a; yr=X[i].b;
}
g<<"("<<xr<<","<<yr<<") ";
f.close();g.close();return 0;
}

tabara
ntr-o tabar la munte s-au ntlnit copii venii din n regiuni diferite ale rii. Tabara are n dotare suficiente
cabane identice cu cte n paturi. Directorul taberei a stabilit, pentru o ct mai bun socializare, urmtoarele
reguli:
n fiecare caban trebuie s fie cazate exact n persoane, dintre care cel puin n-1 trebuie s fie copii i cel
mult un profesor;
copiii cazai n fiecare caban trebuie sa provin din regiuni diferite ale rii;
nici un copil sau profesor nu poate fi cazat n mai multe cabane.
Cerin

S se gseasc numrul maxim M de cabane care pot fi completate respectnd restriciile de mai sus.
Date de intrare
Fiierul de intrare tabara.in conine pe prima linie dou numere naturale n i p, unde n este numrul de
regiuni, iar p este numrul de profesori. Pe linia a doua, se gsesc n numere naturale, c1, c2, ... cn separate
prin cte un spaiu. Valoarea ci reprezint numrul copiilor venii din regiunea i.
Date de ieire
n fiierul de ieire tabara.out se va scrie pe prima linie numrul natural M.
Restricii i precizri
2 <= n, p<= 50000 ;1 <= c1, c2, ... cn<= 50000
Este posibil ca dup completarea celor M cabane, nu toi elevii i/sau profesorii s fie cazai
Numrul total de persoane care trebuie cazate nu va depi pe nici un test 2.000.000.000
Exemple
tabara.in
tabara.out
Explicaie
22
3
Codificnd cele dou regiuni cu x i y, se pot completa maxim 3 cabane n
13
felul urmtor: [x1,y1], [p1,y2], [p2,y3] .
x1 reprezint singurul copil din regiunea 1, y1,y2,y3 reprezint cei trei copii din
regiunea 2, iar p1,p2 sunt cei doi profesori.
tabara.in
tabara.out
Explicaie
34
4
Dac cele 3 regiuni sunt x, y, z, atunci se pot completa 4 cabane n felul
234
urmtor:[x1,y1,z1], [x2,p1,z2], [p2,y2,z3], [p3,y3,z4]
x1,x2 identific cei doi copii din regiunea 1, etc. Profesorul p4 nu va fi cazat.
S observm c rolul unui profesor nu difer de cel al oricrui copil, deci putem s considerm c avem un
ir a cu n+1 elemente, pe care l vom sorta n ordine cresctoare.
Conform principiului cutiei lui Dirichlet, dac dintr-o regiune avem r elevi, atunci ei vor ncpea ntr-un numr
de c cabane numai cu condiia cr. ntr-adevr, dac c<r, exist o cutie (caban) n care ar fi mai muli copii
din regiunea r, ceea ce nu ne convine. Deci n acest caz putem caza c elevi, iar r-c elevi nu mai au loc n
nicio caban, n concluzie i putem elimina.
Pentru a obine numrul maxim de cabane, vom calcula suma total s de elevi cazai (profesorul e elev!), i
mprind la n, obinemprintr-o prim aproximare numrul de cabane care se pot umple cu elevi. S notm
acest prag cu p=[s/n]. Acest prag se va recalcula n mod repetat innd cont de principul lui Dirichlet, conform
cruia vom nlocui n irul a toate elementele a[i] mai mari dect p cu p, i recalculnd suma elementelor,
pn cnd toate elementele irului vor respecta condiia a[i]p.
Rezultatul final va fi p=[s/n]=max(a[i]).
int profi,copii[50000], L,R,M,p,n,i;
int main()
{
//citire
f >> n >> profi;
for (i = 1; i<=n; i++) f >> copii[i];
m=n;
//sortam crescator
do
{
sortat=1;
for(i=1;i<m;i++)

Ana ntuneric

22

Ana Intuneric
if(copii[i]>copii[i+1])
{
aux=copii[i];copii[i]=copii[i+1];
copii[i+1]=aux;sortat=0;
}
m--;
}
while(!sortat);
L = 0; R = copii[n] + profi + 1;
while (L + 1 < R)
{
M = (L + R) / 2;
p = 0;
for (i = 1; i <=n; i++)
if (copii[i] < M) p = p+M - copii[i];
if (p <= M && p<= profi) L = M;
else R = M;
}
g << L << '\n';
f.close();
g.close();
return 0;
}

moretime
La banca Moretime, moneda este Time-ul. Cei n clieni ai bncii au conturi identificate prin valori naturale
nenule, distincte dou cte dou. La deschiderea contului, fiecare client a depus un fond de siguran
reprezentat printr-un numr natural nenul (cantitatea de Time aferent contului, ce poate fi folosit de banc,
pentru urgene majore). Un client al bncii este considerat premium dac numrul su de cont ncepe i se
termin cu aceeai cifr nenul.
Lumea este lovit de criza de timp i banca Moretime a hotrt s susin doar clienii premium printr-un
program special. Astfel, banca va colecta fondurile de siguran ale unora dintre clienii premium iar suma
obinut o va folosi integral pentru a finana, cu cantiti egale de Time, pe fiecare client premium, inclusiv
pe cei de la care a colectat fondul.
Cerin
Cunoscnd n, numrul de clieni, conturile i valorile fondurilor de siguran ale acestora, s se determine:
a. numrul clienilor premium
b. numrul clienilor premium ce pot fi alei de banc astfel nct suma fondurilor de siguran colectat de
la acetia s poat fi distribuit n mod egal fiecrui client premium
c. numerelor de cont ale celor selectai la punctul b).
Date de intrare
Fiierul text moretime.in conine pe prima linie n, numrul de clieni ai bncii iar pe urmtoarele n linii
perechi de numere, separate prin cte un spaiu, reprezentnd numrul contului i valoarea fondului de
siguran, pentru fiecare dintre cei n clieni.
Date de ieire
Fiierul de ieire moretime.out va conine, pe prima linie cp, numrul de clieni premium, pe a doua linie p,
numrul de clieni premium ce pot fi alei de banc n condiiile de mai sus iar pe linia a treia, un ir de p
numere separate prin cte un spaiu, reprezentnd conturile acestor clieni. Dac sunt mai multe soluii se va
scrie una dintre acestea.
Restricii i precizri
1 p cp n 10000;
Moneda Time nu este divizibil.
Numerele de cont sunt numere naturale cu cel puin dou i cel mult cinci cifre.
Fondurile de siguran sunt numere naturale nenule mai mici dect 100000.
Pentru rspunsuri corecte se acord punctaje pariale astfel: a) 30%; a)+b)+c) 100%
Exemplu
moretime.in

Ana ntuneric

moretime.out

Explicaii

23

Ana Intuneric
6
112 100
217 50
1231 200
3000 500
2902 200
44 100

3
2
2902 44

sunt 3 clieni premium


pot fi alei 2 clieni premium pentru colectarea fondurilor
de siguran
clienii cu conturile 2902 i 44 pot fi alei pentru c suma
fondurilor lor (200+100=300) poate fi mprit n mod egal
celor 3 clieni premium (fiecare ar primi 100).

Se citesc cele n perechi de numere reprezentand conturile si fondurile celor n clienti.


Se memoreaza in vectorii cont si fond doar valorile corespunzatoare clientilor premium (prima cifra si ultima
cifra a numarului de cont sunt egale).
cp=numarul clientilor premium
Pe vectorul fond se aplica principiul cutiei lui Dirichlet, conform caruia, pentru orice multime de cp numere
naturale exista o submultime de suma divizibila cu cp. Se construiesc pe rand sumele
s1=fond[1];
s2=fond[1]+fond[2];
...
si=fond[1]+...+fond[i];
...
Daca si este divizibila cu cp atunci submltimea cautata este formata din primii i clienti cu cont[1],...cont[i]
Daca nicio suma nu este divizibila cu cp, cum sunt cp resturi distincte posibile la impartirea la cp (0,1,2,..cp1) iar restul 0 nu s-a obtinut, exista cel putin doua sume diferite care dau acelasi rest r la impartirea la cp.
Pentru a memora resturile vom construi vectorul rest cu semnificatia rest[k]=i, unde si % cp = k
Fie sj, si (j<i) doua sume care dau restul r la impartirea la cp (r din multimea 1, 2, ...cp-1).
Conform teoremei impartirii cu rest, sj = c1*cp + r iar si = c2 * cp + r. Atunci, si - sj = (c2-c1) * cp.
Deci, suma elementelor cuprinse intre j+1 si i va fi divizibila cu cp iar valorile cautate sunt i-j si
cont[j+1],....cont[i].
int n, m, cp, p, cont[10001], fond[10001];
int r[10001];
int main()
{
//citirea si construirea vectorilor cu conturi si fonduri ale clientilor premium
int x, a, y, i, rest, s, u;
f>>n;
for (i=1; i<=n; i++)
{
f>>x>>y; a=x; u=a%10;
while (a>9) a/=10;
if(a==u) cont[++cp]=x, fond[cp]=y;
}
g<<cp<<'\n';
//determinarea submultimii de clienti premium pentru care suma fondurilor este
divizibila cu cp, algoritmul bazat pe principiul cutiei lui Dirichlet
s=0;
for (i=1; i<=cp; i++)
{
s=s+fond[i];
if (s%cp==0)
{
x=1; y=i; break;
}
else
{
rest=s%cp;
if (r[rest]==0) r[rest]=i;
else {
x=r[rest]+1; y=i; break;
}
}

Ana ntuneric

24

Ana Intuneric
}
//afisarea conturilor clientilor selectati
g<<y-x+1<<'\n';
for (int i=x; i<=y; i++)
g<<cont[i]<<' ';
f.close();g.close(); return 0;
}

sport
La ora de sport, cei N elevi din clas s-au aliniat pe un singur rnd n faa profesorului. Nu au ncercat s se
ordoneze dup nlime, deoarece tiau c profesorul are propria metod de ordonare, pe care o aplic la
nceputul fiecrei ore. Profesorul alege un elev, pe care-l trimite la unul dintre cele dou capete ale rndului.
Procedeul se repet pn cnd irul de elevi este ordonat cresctor dup nlime. Copiii s-au gndit s-l
ajute pe profesor s-i perfecioneze metoda, astfel nct numrul de elevi care vor fi mutai prin acest
procedeu la un capt sau la cellalt al irului s fie minim.
Cerin

Cunoscnd numrul de elevi, nlimile i poziiile lor iniiale n ir, determinai numrul minim de mutri pe
care profesorul de sport trebuie s le aplice, pentru a ordona irul de elevi, cresctor dup nlime.
Date de intrare
Fiierul de intrare sport.in conine pe prima linie numrul natural N reprezentnd numrul de copii. Pe linia a
doua, se gsesc N numere naturale distincte: H[1], H[2], , H[N], separate prin cte un singur spaiu. Al ilea numr de pe linie reprezint nlimea copilului care se afl pe poziia i nainte de orice operaie de
mutare.
Date de ieire
n fiierul de ieire sport.out se va scrie pe prima linie un numr natural M, reprezentnd numrul minim de
mutri pe care profesorul le poate face pentru a sorta irul de elevi, cresctor dup nlime.
Restricii i precizri

1 <N 1000 1 H[i] 10000


sport.in
sport.out
Explicaie
Profesorul mut elevul de nlime 1 la captul din stnga:
4
1
2135
1235
3
2
Profesorul are la dispoziie mai multe variante cu minimum 2 mutri.
321
Prezentm una dintre acestea:
Mut elevul de nlime 1 la captul din stnga: 1 3 2
Mut elevul de nlime 3 la captul din dreapta: 1 2 3
5
3
Minimum 3 mutri. Una dintre variante este:
37269
Mut elevul de nlime 7 la captul din dreapta: 3 2 6 9 7
Mut elevul de nlime 2 la captul din stnga: 2 3 6 9 7
Mut elevul de nlime 9 la captul din dreapta: 2 3 6 7 9
Fie G este irul obinut din H prin sortare. Vom face urmtoarele observaii:
G se compune din 3 secvene de numere: S1, S2 i S3. Prima secven, S1, este constituit din cele mai
mici N1 elemente. A fost obinut prin N1 operaii de mutare la nceputul irului. A doua secven, S2,
alctuit din cele mai mari N2 elemente, s-a creat la cellalt capt al irului, prin N2 operaii de mutare la
sfrit. A treia secven, S3, este cuprins ntre primele dou i este format din elementele irului care nu
au fost mutate. Cele trei secvene (mulimi ) sunt evident ordonate cresctor i reuniunea lor este ntregul ir
G.
Exemplu:
H = ( 3, 7, 4, 5, 2, 9, 8, 6, 1 )
G = ( 1,2, 3, 4, 5, 6, 7, 8, 9 )
S1 are N1 = 2 elemente: (1, 2).
S2 are N2=3 elemente: (7, 8, 9 ),
S3 are 4 elemente: (3, 4, 5, 6).
Pentru un numr minim de mutri, este nevoie de un numr maxim de elemente n S3, adic n mulimea de
elemente care nu vor fi mutate. Ideea este de a cuta n irul sortat G, cea mai lung secven consecutiv
S3 creia i corespunde un subir al irului H, format din aceleai elemente. n exemplu, este vorba de
elementele marcate cu rou n irul H. Evident, elementele subirului din H sunt ordonate, ns nu sunt
neaparat consecutive. Se pornete de la fiecare poziie din G, ncepnd cu poziia 1 i se caut cea mai
lung secven creia s-i corespund un subir cresctor n H, reinnd maximul max al lungimilor
secvenelor gsite. Se afieaz N max. Complexitatea soluiei este O(N*N).
int H[10000];
// inaltimile copiilor
int G[10000];
int N,aux,poz,max,sortat;

Ana ntuneric

25

Ana Intuneric
int main()
{
fin >> N;
int i, j;
for ( i = 1; i <=N; i++ )
{
f >> H[i]; G[i] = H[i];
}
// se sorteaza G pentru a se obtine configuratia finala a sirului de copii
do{
sortat=1;
for( i = 1; i <=N - 1; i++ )
if ( G[i] > G[i+1])
{
aux = G[i];G[i] = G[i+1];G[i+1]=aux;sortat=0;
}
}while(!sortat);
max = 0;
for (i = 1; i <=N; i++)
{
// Se cauta cel mai lung subsir din H
poz = i;
// care are aceleasi elemente cu ale unei
// secvente consecutive de elemente din G
for (j = 1; j <=N && poz<=N; j++)
if (H[j] == G[poz] ) poz++;
if(poz - i > max ) max = poz - i;// max - numarul de copii care nu se muta
}
g << N - max << '\n';
g.close();f.close();return 0 ;
}

bal
Un grup de fete i biei particip la balul bobocilor. Ca s evite aglomeraia de pe ringul de dans,
organizatorii au realizat o programare n care fiecrui participant i se aloc o perioad de timp n care se va
afla pe ringul de dans.
Cerin
Scriei un program care s determine numrul maxim de perechi, fat-biat, care se pot forma cu persoanele
aflate pe ringul de dans la un moment dat.
Date de intrare
Fiierul de intrare bal.in conine pe prima linie numerele naturale n i m reprezentnd numrul de fete i
numrul de biei participani la bal. Pe urmtoarele n linii se gsesc cte dou numere naturale xi yi,
(1<=i<=n) separate printr-un spaiu reprezentnd intervalul nchis de timp n care se va afla pe ring fiecare
fat. Pe urmtoarele m linii se gsesc cte dou numere naturale xj yj, (1<=j<=m) separate printr-un spaiu
reprezentnd intervalul nchis de timp n care se va afla pe ring fiecare biat.
Date de ieire
Fiierul de ieire bal.out va conine o singura linie pe care va fi scris un singur numr natural reprezentnd
numrul maxim de perechi determinat.
Restricii 1 <= n <= 100 000 1 <= m <= 100 000 1 <= xi <= yi <= 1 000 000 1 <= xj <= yj <= 1 000 000
Exemple
bal.in

bal.out

33
11 16
18
69
4 20
8 17
13 18

Vom crea doi vectori (B baieti si F fete) astfel :


pentru fiecare xi,yi (intervalul in care un copil sta pe scena ) B[xi]++,B[yi], respectiv F[xi]++,F[yi]
Cu ajutorul unei parcurgeri pana la 1000005 vom avea la fiecare moment numarul de baieti si fete de pe
scena (initial fiind 0, adaugam sau scadem in functie de B[pasi]/F[pasi].

Ana ntuneric

26

Ana Intuneric
Avem astfel MAX(pasi) = MAX(MAX(pasi-1),MIN(B[pasi],F[pasi]));
1
2
3
4
5
6
7
8
9
10 11 12 13
b
1
1
-1 -1 1
f
1
1
1
bt
1
2
1
0
1
ft
1
2
3
maxP
2

14

15

16

17
-1

18

19

20

21

-1

-1

-1

#define MAX(a,b) (a) > (b) ? (a) : (b)


#define MIN(a,b) (a) < (b) ? (a) : (b)
int b[1000001],f[1000001];
int n,m;
int i,x,y;
int maxP;
int ft,bt;
int main()
{
f>>n>>m;
for(i = 1; i <=n; i++)
{
f>>x>>y;b[x]++;b[y+1]--;
}
for(i = 1; i<=m; i++)
{
f>>x>>y;f[x]++;f[y+1]--;
}
for(i=1;i<=1000000;i++)
{
if(f[i] || b[i])
{
if(f[i]==1) ft++;
if(b[i]==1) bt++;
maxP = MAX(maxP,MIN(ft,bt));
}
if(f[i]==-1) ft--;
if(b[i]==-1) bt--;
}
g<<maxP<<endl;
f.close(); g.close();return 0;
}

Carti
Vasile se joaca un joc foarte interesant. El are un pachet de N carti de joc (numerotate distinct de la 1 la N).
Cartile din pachet sunt amestecate. Vasile se uita la fiecare carte din pachet incepand cu prima, pana ajunge
la cartea cu numarul 1, pe care o scoate din pachet. Apoi cauta cartea cu numarul 2, cartea cu numarul 3,
s.a.m.d. De fiecare data incepe cautarea de unde a ramas (de la cartea care urmeaza dupa ultima carte
scoasa din pachet). De fiecare data cand ajunge la sfarsitul pachetului, Vasile bate din palme si continua
cautarea de la inceputul pachetului. Cand ultima carte din pachet este eliminata, jocul se termina.
Cerinta Scrieti un program care sa determine de cate ori bate din palme Vasile in timpul unui joc.
Date de intrare Prima linie a fisierului de intrare carti1.in contine un numar natural N, reprezentand numarul
de carti din pachet. Urmatoarele N linii contin numerele cartilor de joc, in ordinea in care acestea se afla in
pachet.
Date de iesire Fisierul de iesire carti1.out contine o singura linie pe care se afla numarul cerut.
Restrictii 1<=N <= 100000
Exemplu
carti1.in
carti1.out
3
2
213
7
3
3671542
Vom construi un vector poz, pozitia initiala a fiecarei carti. Totul se reduce la numarul elemente care
indeplinesc conditia poz[i]>poz[i+1].
int n,i,nrpalme,poz[20000],x;

Ana ntuneric

27

Ana Intuneric
int main()
{
f>>n;
for (i=1;i<=n;i++)
{
f>>x; poz[x-1]=i;
}
for (i=1;i<=n-1;++i)
if (poz[i]>poz[i+1]) nrpalme++;
g<<nrpalme<<"\n";
f.close(); g.close(); return 0;
}

baze
Exist numere care au proprietatea c se scriu, n dou baze diferite, prin trei cifre identice. De exemplu,
numrul 273(10) n baza 9 se scrie 333(9) i n baza 16 se scrie 111(16).
Cerin
Concepei un program care s determine toate numerele mai mici ca N care au aceast proprietate.
Date de intrare
Fiierul de intrare BAZE.IN va conine pe prima linie numrul N.
Date de ieire
n fiierul de ieire BAZE.OUT se vor scrie numerele determinate, fiecare pe cte un rnd. Pentru fiecare
numr se vor scrie, separate prin cte un spaiu, numrul n baza 10 i cele 2 baze n care numrul respectiv
are proprietatea din enun.
Restricii 0<N<=32000
Exemplu
BAZE.IN
BAZE.OUT
300
273 9 16
int n, bmax, nr, NrBaze, b, Limita,baza[10];
#define MIN(a,b) (a) < (b) ? (a) : (b)
int bazab(int nr, int b)//verifica daca nr in baza b are 3 cifre identice
{
int c[100], i=0;
while(nr)
{
c[i]=nr%b;
if((i)&&(c[i]!=c[i-1])) return 0;
nr/=b;
i++; if(i>3) return 0;
}
if(i<3) return 0;
if((c[0]==c[2])) return 1;
return 0;
}
int main()
{
f>>n;

// daca x este baza, atunci x*x+x+1<=n-- x^2+x-n+1<=0-- int((-1+sqrt(4*n-3))/2)


bmax=(-1+sqrt(4*n-3))/2;
for(nr=7;nr<=n;nr++)//7 in baza 10 este 111 in baza 2
{
NrBaze=0;
Limita=MIN(bmax, nr);
for(b=2; b<=Limita; b++)
if(bazab(nr,b))
{
NrBaze++; baza[NrBaze]=b;
}
if(NrBaze==2) g<<nr<< <<baza[1]<< <<baza[2];
}
f.close();g.close();return 0;
}

Ana ntuneric

28

Ana Intuneric
Panglica
Gigel are o panglic alctuit din benzi de 1 cm lime, colorate n diverse culori. Panglica are N benzi
colorate cu C culori, culori pe care le vom numerota de la 1 la C. Gigel vrea ca la ambele capete ale panglicii
s aib aceeai culoare, dar cum nu poate schimba culorile benzilor, singura posibilitate rmne tierea unor
buci de la capete.
Cerin
Scriei un program care s determine modul de tiere a panglicii astfel nct la cele dou capete s fie benzi
de aceeai culoare, iar lungimea panglicii obinute s fie maxim.
Date de intrare
Fiierul de intrare PANGLICA.IN conine:
pe prima linie numerele naturale N i C separate printr-un spaiu;
pe urmtoarele N linii descrierea panglicii: pe fiecare linie un numr natural de la 1 la C, reprezentnd n
ordine culorile fiilor ce alctuiesc panglica.
Date de ieire
Fiierul de ieire PANGLICA.OUT va conine urmtoarele 4 numere:
pe prima linie numrul de fii rmase;
pe linia a doua numrul culorii care se afl la capete;
pe linia a treia cte fii trebuie tiate de la nceputul panglicii iniiale;
pe linia a patra cte fii trebuie tiate de la sfritul panglicii iniiale.
Restricii i precizri
2N10000
1C200
Dac exist mai multe soluii alegei pe cea n care se taie ct mai puin din partea de nceput a panglicii.
Exemplul 1
Exemplul 2
PANGLICA.IN PANGLICA.OUT
PANGLICA.IN
PANGLICA.OUT
63
4
52
4
1
2
1
2
2
1
2
1
1
1
1
0
3
2
2
2
3
Se citesc datele, se memoreaza pentru fiecare culoare pozitia (indicele) pe care apare prima data si ultima
data. Cautam apoi culoarea pentru care diferenta dintre prima si ultima aparitie este maxima. In acest fel e
suficienta o singura parcurgere a sirului (doua "for"-uri pentru un sir de 10000 numere inseamna timp de
executie prea mare). In plus, nu e nevoie nici de memorarea numerelor din sir.
int n,c,i,k,max=0,cmax,pra[201],ulta[201];
int main()
{
//citire
f>>n>>c;
for(i=1;i<=n;i++)
{
f>>k;
if(pra[k]==0) pra[k]=i;//prima aparitie a culorii k
ulta[k]=i; //aici salvam, pe rand toate aparitiile culorii k, a.i. la urma
//ulta[k] va contine ultima aparitie
}
for(i=1;i<=c;i++)
if(ulta[i]-pra[i]+1>max)
{
max=ulta[i]-pra[i]+1; cmax=i;
}
g<<max<<endl<<cmax<<endl<<pra[cmax]-1<<endl<<n-ulta[cmax]);
f.close();g.close();return 0;
}

pluton
n timpul aciunii "Furtuna n deert" din cauza unei furtuni de nisip, n soldai s-au rtcit de plutoanele lor.
Dup trecerea furtunii se pune problema regruprii acestora pe plutoane. Pentru aceasta se folosesc
plcuele de identificare pe care soldaii le poart la gt. Pe aceste plcue sunt scrise numere care pot
identifica fiecare soldat i plutonul din care acesta face parte. Astfel, soldaii din acelai pluton au numrul de

Ana ntuneric

29

Ana Intuneric
identificare format din aceleai cifre, dispuse n alt ordine i numerele de identificare sunt unice. De
exemplu, numerele de identificare 78003433, 83043073, 33347008 indic faptul ca cei trei soldai care le
poart fac parte din acelai pluton.
Cerin
Fiind date cele n numere de pe plcuele de identificare, s se regrupeze cei n soldai pe plutoane,
indicndu-se numrul de plutoane gsite (un pluton refcut trebuie s aib minimum un soldat), numrul de
soldai din cel mai numeros pluton, numrul de plutoane care au acest numr maxim de soldai precum i
componena unui astfel de pluton (cu numr maxim de soldai regrupai).
Date de intrare
Fiierul de intrare pluton.in conine pe prima linie numrul n de soldai recuperai, iar pe fiecare dintre
urmtoarele n linii cte un numr de identificare a celor n soldai.
Date de ieire
Fiierul de ieire pluton.out va conine pe prima linie numrul de plutoane refcute. Linia a doua va conine
numrul de soldai din cel mai numeros pluton refcut. Linia a treia va conine numrul de plutoane care au
numrul maxim de soldai recuperai. Linia a patra va conine componena unui astfel de pluton, cu numr
maxim de soldai recuperai, numerele de identificare ale soldailor din componen fiind scrise unul dup
altul separate prin cte un spaiu.
Restricii

0<n<=4000
0<numr de identificare <2000000000
Exemplu:
pluton.in
10
123
666
321
7890
2213
312
655
1000
1322

pluton.out
6
3
2
321 312 123
1223

Explicaii
Au fost recuperai soldai din 6 plutoane distincte,
cei mai muli soldai recuperai dintr-un pluton
fiind n numr de 3. Exist 2 plutoane cu numr
maxim de soldai recuperai (3), unul dintre ele
fiind format din soldaii cu numerele 321 312 123.
De remarcat c i soluia 1223 2213 1322 este
corect.

s[k]=nr de identificare al soldatului k


so[k]= nr de identificare al soldatului k cu cifrele ordonate descrescator
Gr[]=grupele
nrs[]=nr de soldati dintr-o grupa
int s[4001],so[4001],Gr[4001],nrs[4001];
int n,nrp,maxi,nrmax;
Nr
1223 123 666 321 7890 2213 312
NrSort
3221 321 666 321 9870 3221 321
int main()
Gr
{
1
2
3
4
5
6
7
long i,j,pmax,x;
nrs
1
2
3
2
4
1
2
f>>n;
for(i=1;i<=n;i++)
{
f>>s[i];Gr[i]=i;x=s[i];int fr[10]={0};
while(x>0){fr[x%10]++;x=x/10;}
for(int c=9;c>=0;c--) while(fr[c]>0){ so[i]=so[i]*10+c;fr[c]--;}
}
nrp=1;
for(i=1;i<n;i++)
if(Gr[i]>=i)
{
nrs[nrp]=1;
for(j=i+1;j<=n;j++)
if(so[i]==so[j])
{
Gr[j]=nrp;nrs[nrp]++;
if(nrs[nrp]>maxi) {maxi=nrs[nrp];pmax=nrp;}
}
Gr[i]=nrp;nrp++;

Ana ntuneric

655
655
8
5

1000
1000
9
6

1322
3221
10
1

30

Ana Intuneric
}
nrp--;
for(i=1;i<=nrp;i++)
if(maxi==nrs[i]) nrmax++;
g<<nrp<<"\n"<<maxi<<"\n"<<nrmax<<"\n";
for(i=1;i<=n;i++)
if(Gr[i]==pmax) g<<s[i]<<" ";
g<<endl;
f.close();g.close(); return 0;
}

buline
Zaharel se plictisea la cursurile de la facultate si a inceput sa deseneze buline: a luat N bilete si pe fiecare a
desenat un numar de buline, doar albe sau doar negre. A asezat cele N bilete in cerc si si-a pus urmatoarea
intrebare: daca considera ca pe fiecare biletel este scris un numar intreg (x buline albe va reprezenta
numarul x , iar x buline negre numarul -x) care este suma maxima a unei secvente de biletele aflate pe pozitii
consecutive?
Date de intrare
Fisierul de intrare buline.in va contine pe prima linie numarul natural N. Urmatoarele N linii vor contine cate
doua numerele naturale , reprezetand numarul de buline de pe biletele si culoarea lor (0 pentru negru
si 1 pentru alb), in ordinea in care acestea au fost asezate.
Date de iesire
Fisierul de iesire buline.out va contine trei numerele naturale: S P L cu semnificatia ca secventa de biletele
de suma maxima are suma S, incepe pe pozitia P si are lungime L. Daca exista mai multe solutii se va afisa
cea cu pozitia P minima, iar daca exista mai multe solutii cu pozitia P minima se va afisa cea cu
lungimea L minima.
Restrictii si observatii
1 N 200.000
Numarul de buline de pe un biletel este cuprins in intervalul [0, 10.000]
Biletele sunt numerotate cu numere de la 1 la N
Avand in vedere ca biletele sunt asezate in cerc, dupa biletelul N urmeaza biletelul 1
Secventa aleasa trebuie sa fie formata din cel putin un biletel
Pentru un test se va acorda 50% din punctaj pentru o solutie corecta, dar pentru care
valorile P sau L nu sunt minime
Exemplu
buline.in
buline.out
5
10
21
40
31
51

944

Explicatie
Cele 5 biletele, pe fiecare fiind trecut numarul sau si bulinele:
Problema este o variatie a unei probleme clasice: dandu-se un sir de N numere intregi sa se determine o
secventa de suma maxima. Singura modificare este ca in aceasta problema sirul este circular. In prima parte
a solutiei nu vom lua in considerare faptul ca sirul este circular. Pentru a rezolva problema pentru un sir
normal exista o solutie clasica O(N). Se calculeaza pentru fiecare i secventa de suma maxima care se
termina cu elementul i: este fie secventa de suma maxima care se termina la elementul i-1, la care se
adauga elementul i, fie doar elementul i. O scurta descriere in pseudocod a acestui algoritm:

Vom trata acum si faptul ca sirul este circular. Astfel, trebuie verificate si secventele de forma i,i+1,...N-

Ana ntuneric

31

Ana Intuneric
1,N,1,2,...j-1,j. Pentru a realiza acest lucru eficient precalculam un sir de sume partiale Si = A1 + A2 + ... +
Ai = Si-1+Ai si un al doilea sir Smaxi = max(S1, S2,..., Si) = max(Smaxi-1, Si). Pentru un i fixat, cea mai buna
secventa de forma i,i+1,...N-1,N,1,2,...j-1,j se poate calcula in O(1) astfel: Smaxi-1+SN-Si-1.
Un alt mod de a verifica secventele de forma i,i+1,...N-1,N,1,2,...j-1,j este daca observam ca suma acestei
secvente este de fapt suma tuturor elementelor din care se scade secventa j+1, j+2, ... i-2, i-1. Astfel ne
intereseaza o secventa de suma minima pe care sa o scadem din suma totala. Aceasta se poate determina
cu o mica modificare a agloritmului pentru suma maxima sau inmultind elementele cu-1 si cautand o
secventa de suma maxima.
Complexitatea rezolvarii este O(N) doar cateva variabile aditionale pentru pozitie si lungime. , iar pentru
reconstituirea solutiei sunt necesare
int v[200001], sum[200001], smax[200001], ind[200001];
int N, S, P, L;
int main()
{
int N, suma=0, st, x, i;
f>>N;
for (i = 1; i <= N; i++)
{
f>>v[i]>>x;
if(x == 0) v[i] = -v[i];
}
//calculam sumele partiale
for(i = 1; i <= N; i++)
sum[i] = sum[i-1] + v[i];
//determinam suma maxima care se termina pe pozitia i
for(i = 1; i <= N; i++)
if(smax[i-1] > sum[i])
{
smax[i] = smax[i-1]; ind[i] = ind[i-1];
}
else {
smax[i] = sum[i]; ind[i] = i;
}
for(i = 1; i <= N; i++)
{
if(suma <= 0){S = 0; st = i;}
suma += v[i];
if ( suma > S ){S = suma; P = st; L = i - st + 1;}
}
for( int i = 1; i <= N; i++ )
if ( sum[N] - sum[i-1] + smax[i-1] > S )
{
S = sum[N] - sum[i-1] + smax[i-1];
P = i;
L = N + ind[i-1] - i + 1;
}
g<<S<<' '<<P<<' '<<L;
f.close();g.close(); return 0;
}

Numere mari
Vom considera ca numerele mari sunt vectori in care elementul de indice 0 indica lungimea numarului, iar
cifrele sunt retinute in ordinea inversa decat cea a citirii.
Suma a doua numere mari
void add(int A[], int B[])
{
int i, t = 0;
for (i=1; i<=A[0] || i<=B[0] || t; i++, t/=10)
A[i] = (t += A[i] + B[i]) % 10;
A[0] = i - 1;
}

Ana ntuneric

32

Ana Intuneric
Inmultirea unui numar mare cu un numar mic
void mul(int A[], int B)
{
int i, t = 0;
for (i = 1; i <= A[0] || t; i++, t /= 10)
A[i] = (t += A[i] * B) % 10;
A[0] = i - 1;
}

Inmultirea unui numar mare cu un numar mare


void mul(int A[], int B[])
{
int i, j, t, C[NR_CIFRE];
memset(C, 0, sizeof(C));
for (i = 1; i <= A[0]; i++)
{
for (t=0, j=1; j <= B[0] || t; j++, t/=10)
C[i+j-1]=(t+=C[i+j-1]+A[i]*B[j])%10;
if (i + j - 2 > C[0]) C[0] = i + j - 2;
}
memcpy(A, C, sizeof(C));
}

Scaderea a doua numere mari


void sub(int A[], int B[])
{
int i, t = 0;
for (i = 1; i <= A[0]; i++)
A[i] += (t = (A[i] -= ((i <= B[0]) ? B[i] : 0) + t) < 0) * 10;
for (; A[0] > 1 && !A[A[0]]; A[0]--);
}

Impartirea unui numar mare la un numar mic


void div(int A[], int B)
{
int i, t = 0;
for (i = A[0]; i > 0; i--, t %= B)
A[i] = (t = t * 10 + A[i]) / B;
for (; A[0] > 1 && !A[A[0]]; A[0]--);
}

Restul unui numar mare la un numar mic


int mod(int A[], int B)
{
int i, t = 0;
for (i = A[0]; i > 0; i--)
t = (t * 10 + A[i]) % B;
return t;
}

next
Se da un numar natural N. Sa gaseasca cel mai mic numar natural M mai mare sau egal cu N si divizibil
cu D.
Date de intrare
Pe prima linie din fisierul de intrare next.in se va gasi numarul N, iar pe a doua linie numarul D.
Date de iesire
In fisierul de iesire next.out se va scrie pe prima linie numarul M.
Restrictii
1.000.000
1 N < 10
16
2 D 10
Pentru 50% din teste D 1.000.000
Exemplu
next.in
next.out

Ana ntuneric

33

Ana Intuneric
47
11

55

Folosind operatii pe numere mari se calculeaza restul lui N la numarul D. Fie R acest rest, se va aduna la
numarul N valoarea (D-R) mod D. Numarul astfel obtinut va reprezenta primul numar mai mare sau egal
decat N divizibil cu D. Complexitatea rezolvarii este O(lg N).
int a[1000005], b[1000005];
char s[1000005];
void add(int A[], int B[])
{
int i,t = 0;
for (i=1;i<=A[0]||i<=B[0]||t;i++)
{
t+=A[i]+B[i];//depasirea
A[i]=t%10;t/=10;
}
A[0]=i-1;//dimensiunea numarului suma o tin minte in A[0]
}
long long mod(int A[], long long B)
{
int i;
long long t = 0;
for (i = A[0]; i > 0; i--) t = (t * 10 + A[i]) % B;
return t;
}
int main()
{
long long d, r;
int i;
f.getline(s,1000005);
for(i=0;i<strlen(s);i++)
a[++a[0]]=s[i]-'0';
reverse(a+1, a+a[0]+1);
f>>d;
r=mod(a, d);
if(r>0) r=d-r;
while(r)
{
b[++b[0]]=r%10;
r/=10;
}
add(a,b);
for(i=a[0];i>0;i--) g<<a[i];
f.close();g.close();return 0;
}

Idee
politic
n ara lui Papur Vod s-au organizat de curnd primele alegeri democratice. A rezultat astfel un parlament
din care fac parte deputai cu diverse doctrine politice, de stnga sau de dreapta. Acestea sunt descrise prin
numere naturale nenule (orientarea politic este cu att mai de stnga cu ct numrul este mai mic).
Parlamentarii s-au asociat n partide politice n funcie de doctrina fiecruia. Oricare doi deputai ale cror
doctrine corespund unor numere consecutive fac parte din acelai partid. Prin urmare, partidele vor fi
alctuite din deputai ale cror doctrine sunt numere consecutive. (De exemplu, dac parlamentul are 5
deputai, cu doctrinele 1,2,3,5 i 6, atunci nseamn c acetia sunt grupai n dou partide: unul format din
1,2 i 3 i altul din 5 i 6.)
Un guvern trebuie s beneficieze de susinerea a mai mult de jumtate dintre parlamentari. De exemplu,
dac parlamentul este format din 7 deputai, atunci un guvern are nevoie de susinerea a cel puin 4 deputai.
Pentru a putea guverna, partidele se pot grupa in coaliii. Regula dup care se asociaz este urmatoarea:
dou partide A i B, A avnd o doctrin mai de stnga, pot face parte din aceeai coaliie doar dac din
coaliia respectiv fac parte toate partidele a cror doctrin este mai de dreapta dect cea a lui A i mai de

Ana ntuneric

34

Ana Intuneric
stnga dect cea a lui B. De exemplu, dac parlamentul este alctuit din deputai cu orientrile politice
1,2,4,5,7 i 8, atunci partidul format din 1 i 2 nu se poate asocia cu partidul format din 7 i 8 dect dac din
coaliia respectiv face parte i partidul format din 4 i 5.
Cerin
Fiind dat parlamentul din ara lui Papur Vod printr-un ir ordonat strict cresctor de numere naturale
nenule, se cere s se stabileasc numrul de partide parlamentare i numrul variantelor de coaliie
majoritar.
Date de intrare
Pe prima linie a fiierului de intrare politic.in se afl un numr natural nenul N, reprezentnd numrul de
deputai din parlament.
Pe a doua linie se afl N numere naturale nenule separate prin cte un spaiu, ordonate strict cresctor,
reprezentnd doctrinele parlamentarilor.
Date de ieire
Prima linie a fiierului politic.out va conine un numr natural nenul X, reprezentnd numrul de partide din
parlament, iar a doua linie va conine un alt numr natural nenul Y, care reprezint numrul de coaliii
majoritare care se pot forma.
Restricii i precizri
0 < N 20000
numerele din ir sunt mai mici sau egale cu 30000
pentru determinarea corect a numrului de partide parlamentare se acord 30%din punctaj, iar pentru
afiarea corect a numrului de variante de coaliie majoritar se acord 70% din punctaj
Exemplu
politic.in
politic.out
Explicaie
10
5
Partidele parlamentare sunt:P1=(1,2,3),
1 2 3 5 6 8 10 11 14 15
4
P2=(5,6),P3=(8),P4=(10,11)iP5=(14,15).
Variantele de coaliie majoritar sunt :
P1+P2+P3, P1+P2+P3+P4, P2+P3+P4,
P2+P3+P4+P5.
Se parcurge irul de n numere reprezentnd orientrile politice ale deputailor i se stabilete m=numrul de
partide. n acelai timp se construiete un vector v, cu m elemente, v[i]=numrul de deputai ai partidului i.
Numrul de coaliii majoritare se stabilete n urma unei parcurgeri a vectorului v. Se folosesc dou variabile,
p i u; p reprezint numrul de ordine al celui mai de stnga partid dintr-o coaliie majoritar, iar u va crete
pn cnd partidele cu numere de ordine din intervalul [p,u] au suficieni parlamentari nct s formeze o
coaliie majoritar sau u depete m. Prin urmare, u reprezint numrul de ordine al celui mai de stnga
partid, cu proprietatea c secvena (p,p+1,,u) este o coaliie majoritar. Dac partidele (p,p+1,,u) pot
forma o coaliie majoritar, atunci i secvenele (p,p+1,,u,u+1), (p,p+1,,u,u+1,u+2), , (p,p+1,,m)
sunt coaliii majoritare. Astfel se stabilete numrul total de coaliii majoritare avnd cel mai de stnga partid
cu numrul de ordine p dup formula m-u+1.n momentul n care u depete m, nu mai exist coaliii
majoritare avnd cel mai de stnga partid cu numrul de ordine p i ne oprim.
Algoritmul are complexitatea O(n), fiind necesare o parcurgere a irului de parlamentari i o parcurgere a
irului de partide (u va lua valori cuprinse ntre 1 i m, fiecare valoare fiind luat o singur dat, iar m nu
poate depi n).
Un algoritm de complexitate O(n2) nu se ncadreaz n timp dect pentru o parte din teste.
int p[15001],N,K,sum[14001];
int main()
{
int N1,i,j,nr,xc,xp,coalitii;
//citesc datele si formez coalitiile
f>>N>>xp;
K = 0;
nr = 1;
for (i=1;i<N;i++)
{
f>>xc;
if(xc == xp+1) nr++;
else
{
p[K++] = nr; nr = 1;
}
xp = xc;
}
p[K++] = nr;

Ana ntuneric

35

Ana Intuneric
//Calculez numarul de coalitii
sum[0] = 0;
for (i=1;i<=K;i++) sum[i] = sum[i-1]+p[i-1];
coalitii = 0;
N1 = N/2;
for (i=1;i<K;i++)
for (j=i+1;j<=K;j++)
if (sum[j]-sum[i-1] > N1) coalitii++;
g<<K<<<<coalitii<<endl;
f.close();g.close();return 0;
}

nasturi
Presupunem c n fiecare ptrat al unei table de ah (3<n<31, n par) avem cte un nasture. tiind c lum x
nasturi de pe tabl scriei un program care s precizeze dac putem face aceast operaie astfel nct pe
fiecare linie i coloan s rmn un numr par de nasturi.
Exemplu:

n=4, x=4---------------o soluie posibil:


Observm c avem 3 situaii posibile:
xn2-2 sau x2
x=4k, caz n care formm k grupe de cte 4
ptrele, pe coloane, ncepnd din colul din
stnga sus

Nu exist soluie

x=4k+2, caz n care putem considera c x=4k+6


i formm k grupe de cte 4 ptrele, pe
coloane, ncepnd din colul din stnga sus, iar n
colul din dreapta jos lum 6 nasturi ca n imagine

int a[32][32],x,n,i,s,j;
int main()
{
f>>n>>x;
if(x>=n*n-2 || x<=2 || x%2==1)
g<<"Nu exista solutie!"<<'\n';
else
{
if(x%4==0)
for(j=1;j<=n;j=j+2)
for(i=1;i<=n;i=i+2)
{
if(s>=x) break;
a[i][j]=1;a[i+1][j]=1;a[i][j+1]=1;a[i+1][j+1]=1;
s+=4;;//calculez cati nasturi iau in S
}
else
{
a[n-2][n-1]=1;a[n-2][n]=1;a[n-1][n-2]=1;
a[n-1][n]=1;a[n][n-2]=1;a[n][n-1]=1;
x-=6;
for(j=1;j<=n && x;j=j+2)
for(i=1;i<=n && x;i=i+2)
{
a[i][j]=1;a[i+1][j]=1;a[i][j+1]=1;a[i+1][j+1]=1;

Ana ntuneric

36

Ana Intuneric
x-=4; //scad din x cati nasturi iau
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
if(a[i][j]==0)g<<N;else g<< ;
g<<'\n';
}
}
f.close();g.close();return 0;
}

N=3, S=51
2 dintre solutiile posibile:

Generare tablou
Scrieti un program care sa genereze un tablou bidimensional cu
proprietatile:
-contine N linii si N coloane;
-elementele sale sunt numere naturale nenule;
-suma elementelor este egala cu numarul natural nenul S;
-pe nici o linie si nici o coloana nu exista 2 elemente identice;
-diferenta dintre cel mai mare si cel mai mic element al tabloului este
minima.
Programul va citi numerele naturale nenule N si S si va afisa tabloul generat.
Idee: Pentru ca diferena dintre valoarea maxim i cea minim din tablou s fie minim trebuie s avem
valori identice distribuite pe diagonale paralele cu diagonala principal n matricea extins (conmpletm
matricea cu n-1 linii). Aflm valoarea cea mai mic pe care o distribuim pe diagonala principal innd cont
c pe celelalte, n ordine, distribuim valori consecutive.
Ex: N=3, S=50
x=4
Calculm suma dup prima distribuie:
S1=n*x+n*(x+1)++n*(x+n-1)=n2*x+n2*(n-1)/2
Dac presupunem c S1 este egal cu S, aflm
valoarea lui x:
x=(S- n2*(n-1)/2)/ n2
Diferena dintre S i S1 se distribuie ncepnd cu
ultima diagonal.Nr. de diagonale incrementate cu 1
este:nrdt=(S-S1)/n, iar nrdr=(S-S1)%n reprezint
numrul de elemente incrementate pe ultima
diagonal, adic cea incomplet.

(S-S1)/n=1

(S-S1)%n=2

Soluia fr matrice:
x= (S/n-n*(n-1)/2)/n;
if(a>0) g<<0;
else
{
S1=n*n*x+n*(n-1)/2);
nrdt=(S-S1)/n;//nr. de diagonale actualizate integral
nrdr=(S-S1)%n;//nr. de elemente de actualizat de pe diagonala nrdt+1
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
d=(n+j-i)%n+1; //diagonala elementului i,j
if(((d>n-nrdt)||(d==n-nrdt)&&(j<=nrdr))
g<<x+d<<' ';
else cout<<x+d-1<<' ';
}
g<<endl;
}
}

Ana ntuneric

37

Ana Intuneric
Paranteze
Dat o secven de 0 i 1, unde 0 nseamn parantez deschis '(', iar 1 nseamn parantez nchis ')',
spunei dac secvena reprezint o expresie corect de paranteze i dac da calculai numrul maxim de
paranteze una ntr-alta. Exemplu: 0 1 0 0 1 0 1 1 este corect i are factorul de imbricare de 2, pe cnd
secvena 0 0 0 1 1 1 0 este incorect. Nu avei voie s folosii tablouri (vectori sau matrice).
Putem rezolva problema observnd urmtoarele reguli valabile pentru orice expresie corect:
oriunde "rupem" expresia, n partea stng vom avea un numr de paranteze deschise mai mare sau egal
cu cele nchise
la final numrul de paranteze nchise trebuie s fie egal cu cele nchise
Dac ambele condiii se ndeplinesc expresia e corect. Prima condiie trebuie ndeplinit pentru fiecare
poziie de rupere.
int n, a, i, sum, max;
int main()
{
f>>n;
while (i<n && sum>=0)
{
if(sum>max) max=sum;
f>>a;
if(a==0)sum++;
else sum--;
i++;
}
if(sum==0)
g<<"Parantezarea este corecta, avand factorul de imbricare "<<max;
else g<<"Parantezarea este incorecta";
f.close();g.close();return 0;
}

Selecie
Dat un ir de n numere i o poziie k n acel ir s se spun ce element s-ar afla pe acea poziie dac irul ar
fi sortat.
Solutie: ideea de rezolvare este s folosim primul pas al algoritmului quicksort i anume pivotarea. Prin
pivotare nelegem separarea vectorului original n dou regiuni: cea din stnga cu numere mai mici sau
egale cu pivotul, iar cea din dreapta cu numere mai mari sau egale cu pivotul (nu este o greeal, n ambele
pri putem avea numere egale cu pivotul). Pivotul poate fi ales la ntmplare, orice element din vector. Odat
ce avem subirurile v[1..i] i v[i+1..j] ne vom ntreba n ce interval se afl k i vom relua problema seleciei n
acel interval, mai mic. Acest algoritm duce la o complexitate medie liniar, O(n). Ca i quicksort, pe cazul cel
mai ru complexitatea este O(n2).
Voi prezenta mai jos o implementare nestandard a pivotrii, n care cutm n paralel n stnga un element
mai mare, iar n dreapta unul mai mic, apoi le interschimbm. Pivotul nu ajunge neaprat pe poziie. Iat o
implementare posibil:
int v[1000000];
int main()
{
int n, k, i, begin, end, b, e, pivot, aux;
f>>n>>k;
for ( i = 1; i <=n; i++ )f>>v[i];
k--;
begin = 1; end = n;
while ( begin < end )
{
b = begin; e = end;
pivot = v[(begin + end) / 2]; // alegem un pivot la jumatea vectorului
while ( b <= e )
{
while ( v[b] < pivot ) b++;
while ( v[e] > pivot ) e--;
if ( b <= e )
{
aux = v[b]; v[b] = v[e]; v[e] = aux; b++; e--;
}
}
// acum [begin..e] sunt mai mici sau egale cu pivotul
// si [b..end] sunt mai mari sau egale cu pivotul

Ana ntuneric

38

Ana Intuneric
if( k <= e ) end = e;
else if ( k >= b ) begin = b;
else begin = end = k;
}
g<<v[k]<<\n;
f.close();g.close();return 0;
}

triunghi
Se consider un triunghi alctuit din numere naturale scrise pe n linii ca n figura
alturat. Liniile triunghiului sunt numerotate de la 1 la n, ncepnd cu linia de la
baza triunghiului (linia de jos), iar poziiile pe linie sunt numerotate ncepnd cu 1
de la stnga la dreapta.Fiecare numr din triunghi, exceptnd pe cele de pe linia
1, este egal cu suma numerelor aflate imediat sub el, n stnga i respectiv n
dreapta lui.
Cerin
Cunoscnd cte un numr de pe fiecare linie a triunghiului, determinai toate
numerele de pe linia 1.
Date de intrare
Fiierul de intrare triunghi.in conine pe prima linie numrul natural n
reprezentnd numrul de linii din triunghi. Pe urmtoarele n linii sunt descrise
informaiile despre triunghi. Mai exact, pe linia i (1in) dintre cele n se afl dou numere naturale separate
prin spaiu pi vi indicnd poziia i respectiv valoarea numrului cunoscut de pe linia i a triunghiului.
Date de ieire
Fiierul de ieire triunghi.out va conine o singur linie, pe care se gsesc n numere naturale separate prin
cte un spaiu, reprezentnd n ordinea de la stnga la dreapta numerele scrise pe linia 1 a triunghiului.
Restricii
1 n 1000
1 pi n+1-i, pentru 1in
Toate numerele din triunghi sunt numere naturale cu cel mult 18 cifre.
Pentru elevii care implementeaz n C: cnd utilizai MINGW, dac citii/afiati valori de tip long long int
folosind scanf(), respectiv printf() utilizai specificatorul de format %I64d.
Exemplu
triunghi.in
triunghi.out
Explicaii
5
12342
Triunghiul este:
44
45
25
20 25
3 13
8 12 13
2 25
3 5 7 6
1 45
1 2 3 4 2
unsigned long long val[1001],l1[1001],l2[1001];
int poz[1001],n;
void citire()
{
f>>n; unsigned int i;
for(i=n;i>=1;i--)f>>poz[i]>>val[i];
}
void sol()
{
unsigned long long v;
int p,i,j;
l1[poz[1]]=val[1];
for(i=2;i<=n;i++)
{
p=poz[i]; v=val[i];
l2[p]=v;
for(j=p+1;j<=i;j++) l2[j]=l1[j-1]-l2[j-1];
for(j=p-1;j>=1;j--) l2[j]=l1[j]-l2[j+1];
for(j=1;j<=i;j++) l1[j]=l2[j];
}
}

Ana ntuneric

1
2
3
4
5
1
45
2
20 25
3
8
12 13
4
5
5
4
Cu galben sunt valorile initiale.
Reconstituirea o fac de sus in jos.
Reconstruirea o fac in 2 vectori l1 si l2.
L1
L2

45
20 25

L1
L2
...

20 25
8 12 13

39

Ana Intuneric
void afis()
{
int i;
for(i=1;i<=n;i++) g<<l1[i]<<" ";
g<<endl;
}

int main()
{
citire();
sol();
afis();
f.close();g.close();return 0;
}

expresie
Costel are de rezolvat o tem grea la matematic: avnd la dispoziie N numere naturale nenule trebuie s aeze
ntre acestea 2 operaii de nmulire i N-3 operaii de adunare, astfel nct rezultatul calculelor s fie cel mai
mare posibil. Nu este permis modificarea ordinii numerelor date.
De exemplu, dac N=5 i numerele sunt 4, 7, 1, 5, 3, operaiile pot fi aezate 4 + 7 * 1 + 5 * 3, 4 * 7 *1 + 5 + 3
e.t.c
Cerin
Scriei un program care s aeze dou operaii de nmulire i N-3 operaii de adunare ntre cele N valori date
astfel nct valoarea expresiei obinute s fie maxim.
Date de intrare
Fiierul de intrare expresie.in are urmtoarea structur:
Pe prima linie se afl un numr natural N, reprezentnd numrul elementelor date.
Pe urmtoarele linii se afl cele N numere naturale date, fiecare pe cte o linie.
Date de ieire
Fiierul de ieire expresie.out va conine, pe prima linie, valoarea maxim obinut prin evaluarea expresiei.
Restricii i precizri
4 <=N<= 1000
Numerele date sunt numere naturale ntre 1 i 10000
Exemplu
expresie.in
expresie.out
Explicaie
5
44
Valoarea maxim se obine prin aezarea operaiilor sub
4
forma:
7
4 * 7 + 1 + 5*3
1
5
3
Memorm cele N numere naturale date n tabloul unidimensional t. Calculm suma celor N valori, deoarece
presupunem c, iniial, avem n expresia noastr doar operaii de adunare.
Exist dou cazuri posibile pentru a introduce dou operaii de nmulire n expresie:
Cazul 1. Cele dou nmuliri sunt consecutive. Obinem valoarea maxim a expresiei n variabila suma1, lund
pe rand toate tripletele de numere consecutive t[i], t[i+1], t[i+2] i alegnd tripletul pentru care suma-t[i]-t[i+1]t[i+2]+t[i]*t[i+1]*t[i+2] este maxim.
Cazul 2. Cele dou operaii de nmulire nu sunt aezate consecutiv. Obinem valoarea maxim a expresiei n
variabila suma1, lund pe rand toate perechile (t[i], t[i+1]) i (t[j], t[j+1]) i alegnd combinaia pentru care sumat[i]-t[i+1]-t[j]-t[j+1]+t[i]*t[i+1]+t[j]*t[j+1] este maxima.
Deoarece numerele date sunt ntre 1 i 10000, valoarea expresiei poate depi tipul de date int.
Pentru exemplul din enunt, avem:
T 1
2
3
4
5
4
7
1
5
3
N=5
Suma iniial este suma=20.
Cazul 1. Avem expresiile posibile:
4*7*1+5+3 = 36
4+7*1*5+3 = 42
4+7+1*5*3 = 26
deci valoarea maxim de pn acum este 42
Cazul 2. Avem expresiile posibile:
4*7+1*5+3 = 28+5+3 = 36
4*7+1+5*3 = 28+1+15= 44
4+7*1+5*3 = 4+7+15=26
deci valoarea maxim este 44

Ana ntuneric

40

Ana Intuneric
int N,v[1001],i,j;
long long S1,S,Smax;
int main()
{
//citire
f>>N;
for(i=1;i<=N;i++){f>>v[i];S=S+v[i];}
//*** cazul 1
for(i=1;i<=N-2;i++)
{
S1=S+v[i]*v[i+1]*v[i+2]-v[i]-v[i+1]-v[i+2];
if(S1>Smax)Smax=S1;
}
//*+* cazul 2
for(i=1;i<=N-3;i++)
for(j=i+2;j<=N-1;j++)
{
S1=S+v[i]*v[i+1]+v[j]*v[j+1]-v[i]-v[i+1]-v[j]-v[j+1];
if(S1>Smax)Smax=S1;
}
//afisare
g<<Smax<<endl;
f.close();g.close();return 0;
}

Urmatoarea permutare lexicografica

int n,i,v[222],imax,maxi,j,aux,m,ok;
int main()
{
f>>n;
for(i=1;i<=n;i++) f>>v[i];
//cautam primul i de la dreapta la stanga cu pp ceruta
i=n;
while(v[i]<v[i-1] && i>1) i--;
//cautam cel mai mic element din stanga lui i mai mare ca el
imax=i;maxi=n+1;
for(j=i;j<=n;j++)
if(v[i-1]<v[j] && v[j]<maxi){maxi=v[j];imax=j;}
//le interschimbam
aux=v[i-1];v[i-1]=v[imax];v[imax]=aux;
//sortam crescator elementele din dreapta sa
m=n;
do
{
ok=1;
for(j=i;j<n;j++)
if(v[j]>v[j+1]){aux=v[j];v[j]=v[j+1];v[j+1]=aux;ok=0;}
m--;
}while(!ok);
for(i=1;i<=n;i++) g<<v[i]<<' ';
f.close();g.close();return 0;
}

Ana ntuneric

41

Ana Intuneric
Elementul majoritar
Dat un vector cu n elemente s se spun dac conine un element majoritar. Un element majoritar este un
element care apare de cel puin n/2 + 1 ori. ncercai s dai o soluie mai bun dect sortarea.
Solutie: dac exist un element majoritar, maj, rezult c fiecare din elementele vectorului diferite de maj poate
fi cuplat cu un element egal cu maj astfel nct dup ce toate cuplrile au fost fcute s rmn cel puin un
element maj necuplat. Ideea de rezolvare este s simulm aceast cuplare. Vom porni cu primul element al
vectorului ca un candidat de element majoritar. Parcurgem elementele vectorului innd minte ci candidai
necuplai avem. De fiecare dat cnd dm peste un element egal cu candidatul incrementm numrul de
elemente necuplate. Cnd dm peste un element diferit scdem numrul de elemente necuplate. Dac la un
moment dat vom avea zero candidai necuplai i mai vine un element diferit de candidat rezult c am eliminat
din vector un numr egal de candidai i non-candidai, drept pentru care putem reporni problema pentru
vectorul rmas: vom considera elementul curent drept candidat, cu o apariie.
La final vom rmne cu un candidat ce trebuie acum verificat: numrm de cte ori apare el in vector printr-o
parcurgere. Dac apare de mcar n/2+1 ori am gsit elementul majoritar, altfel el nu exist. Complexitatea
acestei soluii este liniar, O(n), algoritmul fcnd dou parcurgeri prin vector.
int v[3000000], n, i, nr, maj;
int main()
{
f>>n;
for ( i = 1; i <= n; i++ )f>>v[i];
maj = v[1]; nr = 1; // cautam candidatul la element majoritar
for ( i = 2; i <=n; i++ )
if ( v[i] == maj ) nr++;// cita vreme avem maj incrementam numarul de maj gasite
else {
nr--;// altfel decrementam numarul de maj
if ( nr < 0 )
{ // daca am scazut sub zero
maj = v[i];
// alegem drept candidat elementul curent
nr = 1;
// care apare o data
}
}
// verificare candidat la element majoritar
nr = 0;
for ( i = 1; i <=n; i++ ) // numaram de cit ori apare maj in vector
if ( v[i] == maj ) nr++;
if(nr > n/2 ) // daca maj apare de mai mult de n/2 ori este majoritar
g<< maj<< <<nr<<\n ;
else g<<"-1\n";
f.close();g.close();return 0;
}

maxp
Considerm un ir de numere a1, a2, ..., aN. O secven nevid n acest ir este de forma ai, ai+1, ..., aj, unde i
<= j. De exemplu, pentru N=4 i irul 2 3 4 3, secvenele nevide sunt: 2, 2 3, 2 3 4, 2 3 4 3, 3, 3 4, 3 4 3, 4, 4 3,
3. Definim puterea unui element ai ca fiind numrul de secvene care-l conin pe ai i n care ai este strict mai
mare dect celelalte elemente ale fiecreia dintre respectivele secvene. Astfel n irul 2 3 4 3 puterea
elementului a1 este 1 (fiind maxim doar n secvena format din el nsui), a elementului a2 este 2 (a2 fiind
maxim n secvenele 2 3 i 3), a elementului a3 este 6 (fiind maxim n secvenele 2 3 4, 2 3 4 3, 3 4, 3 4 3, 4 i 4
3), iar a elementului a4 este 1.
Cerine
Scriei un program care determin puterea cea mai mare a unui element din irul dat, precum i numrul de
elemente din ir care au cea mai mare putere.
Date de intrare
Fiierul maxp.in conine pe prima linie numrul natural N, iar pe a doua linie, n ordine, numerele naturale a1,
a2, ..., aN separate prin cte un spaiu.
Date de iesire
Fiierul maxp.out va conine pe prima linie un numr natural ce reprezint puterea cea mai mare a unui
element din irul dat i pe a doua linie va conine un numr natural ce reprezint numrul de elemente din ir
care au cea mai mare putere.

Ana ntuneric

42

Ana Intuneric
Restricii i precizri:
2 <= N <= 200000
Elementele irului sunt numere naturale i au cel mult 6 cifre
Se acord 50% din punctaj pentru determinarea corect a celei mai mari puteri a unui element din ir i 50% din
punctaj pentru determinarea numrului de elemente din ir care au cea mai mare putere.
Exemplu
maxp.in
maxp.out
Explicaii
7
12
Elementul 5 de pe poziia 4 este maxim n 12 secvene:
9345122
1
3 4 5, 3 4 5 1, 3 4 5 1 2, 3 4 5 1 2 2, 4 5,
4 5 1, 4 5 1 2, 4 5 1 2 2, 5, 5 1, 5 1 2,
5 1 2 2, deci puterea lui este 12. Este singurul element care are
aceast putere, celelalte elemente avnd puteri mai mici.
maxp.in
maxp.out
Explicaii
6
3
Elementele din poziiile 3 i 4 sunt maxime n 3 secvene, deci puterea
107726
2
lor este 3. Celelalte elemente au puteri mai mici.
Solutie de complexitate O(n)
Vom determina pentru fiecare element a[i] al irului numrul p[i] de secvene n care a[i] este maxim. Pentru
aceasta, se construiesc doi vectori sti dr de lungime n n care:
st[i] = numrul de valori mai mici ca a[i] aflate imediat n stnga poziiei i.
dr[i] = numrul de valori mai mici ca a[i] aflate imediat n dreapta poziiei i.
Construcia vectorului st se poate realiza n O(n), innd cont de faptul c dac un element a[i] este maxim n
secvena a1, a2, ..., ai, atunci orice numr mai mare ca ai i aflat n dreapta lui ai va fi automat mai mare ca toate
elementele precedente. Asemntor se construiete i vectorul dr parcurgnd de la dreapta la stnga
elementele irului a.
Elementul a[i] va fi maxim ntr-un numr de secvene egal cu p[i] = (st[i] + 1) * (dr[i] + 1). Cunoscnd valorile din
vectorul p, putem imediat determina valoarea maxim i de cte ori apare.
int a[200001],st[200001], dr[200001];
long long rez;
int i,j,k,n,ct;
long long pmax, putere;
int main()
{
//citire
f >> n;
for(i=1;i<=n;i++) f>>a[i];
//constructie vector st
a[n+1]=a[0]=2000000000;
st[1]=0;
dr[n]=0;
for (i=1;i<=n;i++)
{
j=i-1;
while (a[j]<a[i])
j = j - st[j] - 1;
st[i]=i-j-1;
}
//constructie vector dr
for (i=n;i>=1;i--)
{
j = i+1;
while (a[j]<a[i])
j = j + dr[j] + 1;
dr[i]=j-i-1;
}
//calcul putere
for (i=1;i<=n;i++)
{
putere = st[i] + dr[i] + 1 + st[i]*dr[i];
if (putere > pmax)

Ana ntuneric

43

Ana Intuneric
{pmax = putere;ct=1;}
elseif (putere == pmax) ct++;
}
g<< pmax << "\n" << ct << "\n";
f.close();g.close();return 0;
}

Matrice
Pianjen
S ne imaginm o reea planar, format din noduri situate n punctele de coordonate ntregi, fiecare nod fiind
unit prin bare paralele cu axele de coordonate de cele 4 noduri vecine. Un pianjen este plasat iniial n originea
sistemului de coordonate. La fiecare secund, pianjenul se poate deplasa din nodul n care se afl n unul din
nodurile vecine.
Y

X
O

Scriei un program care s determine n cte moduri se poate deplasa pianjenul din poziia iniial, ntr-o
poziie final dat prin coordonatele ei x i y, n timpul cel mai scurt. (ONIG 2001, VII-VIII)
Exemple
Pentru x=1 i y=2, numrul de moduri determinat va fi 3. Pentru x=2 i y=3, numrul de moduri va fi 10.
Soluie
Cum pianjenul se deplaseaz numai de-a lungul barelor, el poate s ajung (n timpul cel mai scurt) n poziia
(x, y) numai din poziia (x-1, y) sau din poziia (x, y-1). Dac notm cu nr(x,y) numrul de modaliti prin care
pianjenul poate ajunge n timp minim n poziia (x, y), atunci deducem c:
nr(0,y)=nr(x,0)=1;
nr(x,y)=nr(x-1,y)+nr(x,y-1), pentru orice x,y>0.
unsigned int nr[21][21];
int main()
{
int x, y;
f>>x>>y;
for (int i=0; i<=x; i++) nr[i][0]=1;
for (int j=0; j<=y; j++) nr[0][j]=1;
for (i=1; i<=x; i++)
for (j=1; j<=y; j++)
nr[i][j]=nr[i-1][j]+nr[i][j-1];
g<<nr[x][y]<<endl;
f.close();g.close(); return 0;
}

Maximum Sum. Se d o matrice de dimensiuni NxN cu elemente ntregi. Se cere determinarea unei submatrici
a carei elemente au suma maxim. N 100 si numerele din matrice [-127, 127].
De exemplu pentru matricea:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2

submatricea de sum maxim este urmtoarea:


92
-4 1
-1 8

Vom pstra n sum[i][j] suma tuturor elementerlor a[i1][j1] cu proprietatea c 1 <= i1 <= i, i 1 <= j1 <= j. Aceste

Ana ntuneric

44

Ana Intuneric
sume vor fi calculate astfel: sum[i][j] = a[i][j] + sum[i][j-1] + sum[i-1][j] sum[i-1][j-1].
Acum pentru a calcula suma elementelor din matricea cu colurile (i1, j1), (i2, j2) unde i1 <= i2 i j1 <= j2 este
sufficient s facem calculul sum[i2][j2]sum[i11][j2]sum[i2][j1-1]+sum[i1-1][j1-1].
int a[101][101],i,j,n,i1,j11,i2,j2,i1max,j11max,i2max,j2max;
long s[101][101],S,Smax;
int main()
{
f>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{f>>a[i][j];s[i][j] = a[i][j] + s[i][j-1] + s[i-1][j] - s[i-1][j-1];}
for(i1=1;i1<=n;i1++)
for(j11=1;j11<=n;j11++)
for(i2=i1;i2<=n;i2++)
for(j2=j11;j2<=n;j2++)
{
S=s[i2][j2]-s[i1-1][j2]-s[i2][j11-1]+s[i1-1][j11-1];
if(S>Smax){Smax=S;i1max=i1;i2max=i2;j11max=j11;j2max=j2;}
}
for(i=i1max;i<=i2max;i++)
{
for(j=j11max;j<=j2max;j++)g<<a[i][j]<<" ";
g<<"\n";
}
f.close(); g.close(); return 0;
}

cladiri
Institutul de Fizic a Pmntului studiaz efectele unui potenial cutremur folosind simulri
computerizate. Harta plan a cldirilor de pe un teritoriu oarecare este reprezentat folosind coordonatele GPS
n plan, longitudine i latitudine, fa de un reper considerat de coordonate (0,0), ca n figura de mai jos.
Fiecare dintre cldirile aflate pe hart,
au dou coordonate GPS, (Longitudine,
Latitudine) i un Grad de rezisten la
cutremure.
Un cutremur se poate produce n orice
punct de coordonate de pe hart, numit centrul
seismului i are o anumit intensitate. Unda
de oc se propag sub forma unor ptrate
concentrice cu centrul seismului, numite nivele
(nivelul 0 reprezint centrul seismului, nivelul 1
primul ptrat concentric, nivelul 2 al doilea
ptrat concentric i aa mai departe).
Intensitatea slbete la fiecare ptrat
concentric cu centrul seismului cu cte o
unitate. Cldirile sunt afectate de cutremur
doar dac gradul lor de rezisten la cutremur
este mai mic sau egal cu intensitatea
cutremurului n poziia cldirii.
Cerin
Scriei un program care s citeasc coordonatele centrului seismului i intensitatea sa n acel punct, precum i
coordonatele cldirilor i gradul lor de rezisten la cutremur, i apoi s determine:
a)
numrul N total de cldiri afectate;
b)
numrul M maxim de cldiri afectate pe un nivel;
c)
numerele nivelelor cu M cldiri afectate, n ordinea cresctoare a numerelor acestor nivele.
Date de intrare
Fiierul de intrare cladiri.in conine:

pe prima linie, trei numere naturale Long Lat Intensitate, separate prin cte un spaiu, reprezentnd

Ana ntuneric

45

Ana Intuneric
coordonatele centrului seismului i respectiv intensitatea sa;

pe fiecare dintre urmtoarele linii, pn la sfritul fiierului, cte trei numere naturale Long Lat Grad,
separate prin cte un spaiu, reprezentnd coordonatele unei cldiri, respectiv gradul de rezisten la cutremur.
Date de ieire
Fiierul de ieire cladiri.out va conine trei linii:

pe prima linie se va scrie numrul natural N reprezentnd numrul total de cldiri afectate;

pe a doua linie se va scrie numrul natural M reprezentnd numrul maxim de cldiri afectate pe un
nivel;

pe a treia linie se vor scrie numerele nivelelor cu M cldiri afectate, n ordinea cresctoare a numerelor
acestor nivele.
Restricii i precizri

0 Long, Lat, Grad, Intensitate 10000;

0 < numr cldiri 100000;

n centrul seismului se pot afla cldiri;

nu exist mai multe cldiri cu aceleai coordonate;

52% din punctaj se poate obine pe teste de intrare cu 0 Long, Lat, Grad, Intensitate 100

se acord punctaje pariale din punctajul acordat pe fiecare test, astfel: 25% pentru cerina a), 25%
pentru cerina b), respectiv 50% pentru cerina c).
Exemple:
cladiri.in
cladiri.out
Explicaii
12 7 11
8
Numrul N total al cldirilor afectate este 8.
10 9 2
3
Numrul M maxim de cldiri afectate pe acelai nivel este 3 i este
10 7 3
24
atins pe nivelele 2 i 4.
13 5 1
8 11 4
876
15 4 3
15 9 10
13 10 1
16 8 4
333
0
Intensitatea cutremurului este 3 i nu poate afecta cele 3 cldiri, deci
135
0
avem N=0 cldiri afectate, iar maximul cldirilor afectate pe un nivel
247
este, evident, M=0.
329
Timp maxim de executare/test: 1 secund
Soluia problemei const n crearea unui vector al nivelelor, care va pstra numarul cladirilor de pe acel nivel
care sunt afectate de cutremur (gradul de rezisten mai mic sau egal cu intensitatea cutremurului n acel loc).
Identificarea nivelului pe care se gsete o cldire se realizeaz prin calculul expresiei max(xc-x,yc-y), unde
(xc,yc) coordonatele cldirii si (x, y) coordonatele epicentrului cutremurului. Odata creat vectorul nivelelor,
se identific elementul maxim i care dintre nivele au numr maxim de cladiri afectate.
ifstream f("cladiri.in");
ofstream g("cladiri.out");
int x,y,ic,nivel[10001],nivmax;
// testam daca o cladire rezista cutremurului
void test(int xf,int yf,int grf)
{
int mx=abs(xf-x),my=abs(yf-y),niv=max(mx,my);
if (niv>nivmax) nivmax=niv;
if (grf<=ic-niv) nivel[niv]++;
}
// calculam numarul total de cladiri distruse
int total(vector v,int n)
{
int s=0,i;
for(i=0;i<=n;i++)s=s+v[i];
return s;

Ana ntuneric

46

Ana Intuneric
}
// determinam nivelul pe care se gasesc cele mai multe cladiri distruse
int maxim(int v[],int n)
{
int Max=v[0],i;
for(i=1;i<=n;i++)
if (v[i]>Max) Max=v[i];
return Max;
}
int main()
{
int xc,yc,gr,i,m,c=0;
f>>x>>y>>ic;
// citesc succesiv datele cladirilor
while (f>>xc>>yc>>gr)
{
test(xc,yc,gr);c++;
}
g<<total(nivel,nivmax)<<"\n";
m=maxim(nivel,nivmax);g<<m<<"\n";
// determin nivelele cu cele mai multe cladiri distruse
if (m)
for(i=0;i<=nivmax;i++)
if (nivel[i]==m) g<<i<<" ";
g<<"\n";
f.close();g.close();return 0;
}

Alt rezolvare (de 100 de puncte)


int xc,yc,pas;
int main()
{
int Int,x1,y1,z1,M=0,N=0,nivel[10001]={0},i,nrp,dif1,dif2;
f>>xc>>yc>>Int;
while(f>>x1>>y1>>z1)
{
dif1=abs(yc-y1); dif2=abs(xc-x1);
if(dif1>=dif2) nrp=dif1;
else nrp=dif2;
if(z1<=Int-nrp) {N++;nivel[nrp]++;}
}
//a)
g<<N<<'\n';
//b)
M=nivel[0];
for(i=1;i<=Int;i++)
if(nivel[i]>M) M=nivel[i];
g<<M<<'\n';
//c)
for(i=0;i<=Int;i++)
if(nivel[i]==M) g<<i<<' ';
g<<'\n';
f.close();g.close();return 0;
}

cartele
n sediul unei firme se intr doar cu ajutorul cartelelor magnetice. De cte ori se schimb codurile de acces,
cartelele trebuie formatate. Formatarea presupune imprimarea unui model prin magnetizare. Dispozitivul n care
se introduc cartelele, numit cititor de cartele, verific acest model. Toate cartelele au aceleai 51ensiuni,
suprafaa ptrat i grosimea neglijabil. Cele dou fee plane ale unei cartele se mpart fiecare n NxN celule
ptrate, identice ca 51ensiuni. Prin formatare unele celule, marcate cu negru n exemplu, se magnetizeaz
permind radiaiei infraroii s treac dintr-o parte n cealalt a cartelei. n interiorul cititorului de cartele se

Ana ntuneric

47

Ana Intuneric
ilumineaz uniform una dintre feele cartelei. De cealalt parte fasciculele de lumin care strbat cartela sunt
analizate electronic. Pentru a permite accesul n cldire modelul imprimat pe cartel trebuie s coincid exact
cu modelul ablonului care memoreaz codul de intrare. Prin fanta dispozitivului nu se pot introduce mai multe
cartele deodat. Cartela se poate introduce prin fant cu oricare dintre muchii spre deschiztura fantei i cu
oricare dintre cele dou fee orientate ctre ablon. Dup introducere cartela se dispune n plan paralel cu
ablonul, lipit de acesta, astfel nct cele patru coluri ale cartelei se suprapun exact cu colurile ablonului.
Modelele imprimate pe cele dou fee ale unei cartele sunt identice. Unei celule magnetizate i corespunde pe
faa opus tot o celul magnetizat, iar unei celule nemagnetizate i corespunde una nemagnetizat. O celul
magnetizat este transparent pentru radiaia infraroie indiferent de faa care se ilumineaz.
Un angajat al firmei are mai multe cartele. Pe unele dintre acestea a fost imprimat noul cod de intrare, iar pe
altele sunt coduri mai vechi. Pentru a afla care sunt cartelele care-i permit accesul n sediul firmei angajatul este
nevoit s le verifice pe toate, introducndu-le pe rnd, n toate modurile pe care le consider necesare, n fanta
cititorului de cartele.
ablon

Cartela 1

Cartela 2

Cerin
Scriei un program care determin care dintre cartele permite accesul n sediul firmei.
Date de intrare
Fiierul de intrare cartele.in conine pe prima linie dou numere naturale N i C desprite printr-un spaiu. N
este 51ensiunea tablourilor care reprezint modelul ablon i modelele cartelelelor. C reprezint numrul de
cartele. Urmeaz C+1 blocuri de cte N linii fiecare. Primul bloc de N linii codific ablonul. Urmtoarele C
blocuri de cte N linii codific fiecare cte o cartel. Pe fiecare linie sunt cte N valori ntregi, desprite printrun singur spaiu. Celulelor magnetizate le corespunde valoarea 1, iar celorlalte, valoarea 0.
Date de ieire
n fiierul de ieire cartele.out se vor scrie C linii, cte o valoare pe linie. Pe linia i se va scrie valoarea 1 dac
cartela i permite accesul n cldire i valoarea 0 n caz contrar.
Restricii i precizri
1 <N, C <= 50
Exemplu
cartele.in
32
010
001
100
100
001
010
001
001
010

cartele.out
1
0

Explicaie
Datele de intrare corespund situaiei din figur. Cartela 1 se potrivete
perfect ablonului, dac se rotete n sens trigonometric cu 90 de grade.
Cartela 2 nu se potrivete ablonului, indiferent de modul n care se
introduce n fant.

Pentru fiecare cartela, se compara element cu element, matricea care reprezinta sablonul, cu urmatoarele
tablouri:
1. Cartela
2. Cartela rotita cu 90 grade
3. Cartela rotita cu 180 grade
4. Cartela rotita cu 270 grade
Daca nu s-a gasit o coincidenta, se intoarce cartela, printr-o operatie de oglindire fata de linia i = n / 2, (sau fata
de coloana j = n / 2), dupa care se compara sablonul cu urmatoarele tablouri:
5. Cartela oglindita
6. Cartela oglindita rotita cu 90 grade
7. Cartela oglindita rotita cu 180 grade

Ana ntuneric

48

Ana Intuneric
8. Cartela oglindita rotita cu 270 grade
Rotirile se pot face in sens trigonometric sau orar. Daca s-a gasit o coincidenta la oricare dintre pasii de mai
sus, se opreste cautarea, se afiseaza 1 si se trece la prelucrarea urmatoarei cartele.
Daca nici dupa pasul 8 nu s-a gasit o potrivire exacta, se afiseaza 0 si se trece la prelucrarea urmatoarei
cartele.
int
int
int
int
{

a[51][51], b[51][51];
aux[51][51];
n, C;
Egale()

// sablonul, cartela

for (int i = 1; i <= n; i++)


for (int j = 1; j <= n; j++)
if ( a[i][j] != b[i][j] ) return 0;
return 1;
}
void Inverseaza()// intoarce cartela pe partea cealalta (oglindire fata de linia i = n/2)
{
int i, j, aux1;
for (i = 1; i <= n / 2; i++)
for (j = 1; j <= n; j++)
{aux1 = b[i][j]; b[i][j] = b[n-i+1][j]; b[n-i+1][j] = aux1;}
}
void Roteste()
// rotire 90 grade in sens trigonometric
{
int i, j;
for (i = 1; i <= n; i++)
for (j = 1; j<= n; j++) aux[n-j+1][i] = b[i][j];
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++) b[i][j] = aux[i][j];
}
void Rezolva()
{
f >> n >> C;
int i, j, r;
int identice = 1;
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++) f>>a[i][j];
for (int k = 1; k <= C; k++)
{
identice = 1;
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
{
f >> b[i][j]; if ( b[i][j] != a[i][j] ) identice = 0;
}
for (int fata = 1; fata <= 2 && !identice; fata++) // pentru fata 1 si 2
{
for (r = 1; r <= 4 && !identice; r++) // la a patra rotatie se revine la matricea initiala
{
Roteste();
// cu 90 in sens trigonometric
if ( Egale() ) identice = 1;
}
if ( !identice ) Inverseaza();
}
if ( identice ) g<< 1 << '\n';
else g << 0 << '\n';
}
}
int main(){ Rezolva();f.close();g.close();return 0;}

Ana ntuneric

49

Ana Intuneric

Tehnica Greedy
Algoritmii greedy (greedy = lacom) sunt n general simpli i sunt folosii la probleme de optimizare, cum ar fi: s
se gseasc cea mai bun ordine de executare a unor lucrri pe calculator, s se gseasc cel mai scurt drum
ntr-un graf etc. In cele mai multe situaii de acest fel avem:
1. o mulime de elemente (lucrri de executat, vrfuri ale grafului etc)
2. o funcie care verific dac o anumit mulime de candidai constituie o soluie posibil, nu neaprat optim,
a problemei
3. o funcie care verific dac pentru o mulime de candidai este posibil s o completm astfel nct s obinem
o soluie posibil, nu neaprat optim, a problemei
4. o funcie de selecie care alege la orice moment cel mai potrivit element, nc nefolosit
5. o funcie soluie care spune cnd s-a ajuns la soluie.
Pentru a rezolva o anumit problem, un algoritm greedy construiete soluia pas cu pas. Iniial, mulimea
candidailor selectai este vid. La fiecare pas, ncercm s adugm acestei mulimi cel mai potrivit element,
conform funciei de selecie. Dac, dup o astfel de adugare, mulimea de elemente obinut nu mai poate
duce la soluie, se elimin ultimul element adugat; acesta nu va mai fi niciodat considerat. Dac, dup
adugare, mulimea de elemente selectate poate duce la soluie, ultimul element adugat va rmne de acum
ncolo n ea. De fiecare dat cnd lrgim mulimea elementelor selectate, verificm dac aceast mulime nu
constituie o soluie posibil a problemei noastre.
Dac algoritmul Greedy funcioneaz corect, prima soluie gsit va fi totodat o soluie optim a problemei.
O ntrebare fireasc este aceea dac algoritmul Greedy duce totdeauna la soluie optim? Evident c nu. Sunt
situaii cnd soluia gsit nu este optim. Mai mult, pentru cele mai multe din probleme nu se cunosc algoritmi
Greedy de rezolvare. Spre deosebire de Backtracking, algoritmul Greedy nu permite atunci cnd s-a observat
c nu se poate ajunge la soluie pentru o anumit secven de elemente, revenirea napoi, pe nivelele
anterioare.
Pentru problemele care nu duc la soluia optim este necesar s se caute soluii, chiar dac nu optime, dar ct
mai apropiate de acestea.
Problema spectacolelor_1
Managerul artistic al unui festival trebuie s selecteze o mulime ct mai ampl de spectacole ce pot fi jucate n
singura sal pe care o are la dispoziie. Stiind c i s-au propus n100 spectacole si pentru fiecare spectacol i i-a
fost anunat intervalul n care se poate desfura [si, fi) (si reprezint ora i minutul de nceput, iar fi ora i
minutul de final al spectacolului i) scriei un program care s permit spectatorilor vizionarea unui numr ct mai
mare de spectacole. De exemplu, dac vom citi n=5 i urmtorii timpi:
12 30 16 30
15 0 18 0
10 0 18 30
18 0 20 45
12 15 13 0
spectacolele selectate sunt: 5 2 4.
Soluie
Ordonm spectacolele cresctor dup ora de final. Selectm iniial primul spectacol (deci cel care se termin
cel mai devreme). La fiecare pas selectm primul spectacol neselectat, care nu se suprapune cu cele deja
selectate (deci carencepe dup ce se termin ultimul spectacol selectat).
int inceput[100], sfarsit[100], nr[100];
int n, i, h, m, n1,ok, ultim, aux;
int main()
{
f >> n; //citire
for (i=1; i<=n; i++)
{
nr[i]=i; //transformam timpul in minute
f>>h>>m; inceput[i]=h*60+m;
f>>h>>m; sfarsit[i]=h*60+m;
}
//ordonam spectacolele crescator dupa ora de final
n1=n;

Ana ntuneric

50

Ana Intuneric
do
{
ok=1;
for (i=1; i<m; i++)
if (sfarsit[nr[i]]>sfarsit[nr[i+1]])
{aux=nr[i];nr[i]=nr[i+1];nr[i+1]=aux; ok=0;}
m--;
}
while (!ok);
for (ultim=1, i=1; i<=n; i++)
if (inceput[nr[i]]>=sfarsit[nr[ultim]])
{g<<nr[i]<<' '; ultim=i;}
g<<endl;
f.close();g.close();return 0;
}

Problema programarii spectacolelor_2


Intr-o sala de spectacol trebuie planificate n spectacole intr-o zi. Pentru fiecare spectacol se cunosc ora de
inceput si ora de terminare (numere intregi). Sa se planifice un numar maxim de spectacole astfel inct sa nu fie
doua spectacole care sa se suprapuna.
Exemplu:truct spectacol{int s,d;}sp[101],salese[101];
int n,k;
void citire()
{
fin>>n;
for(int i=1;i<=n;i++) f>>sp[i].s>>sp[i].d;
}
void ordonare()
{
int i,j,m=n,ok;
spectacol aux;
do{
ok=1;
for(i=1;i<m;i++)
if(sp[i].d>sp[i+1].d)
{
aux=sp[i];
sp[i+1]=aux;ok=0;
}
m--;
}while(!ok);
}

sp[i]=sp[i+1];

date.in
7
24
8 11
56
58
37
78
9 12

date.out:
2,4 5,6 7,8 9,12

void afisare()
{
for(int i=1;i<=k;i++)
g<<salese[i].s<<","<<salese[i].d<<" ";
}
void greedy()
{
int i;
k=1;
salse[1]=sp[1];
for(i=2;i<=n;i++)
if(salese[k].d<sp[i].s) salese[++k]=sp[i];
}
int main()
{
citire();ordonare();greedy();afisare();
f.close();g.close();return 0;

Ana ntuneric

51

Ana Intuneric
}

reactivi
ntr-un laborator de analize chimice se utilizeaz N reactivi. Se tie c, pentru a evita accidentele sau
deprecierea reactivilor, acetia trebuie s fie stocai n condiii de mediu speciale. Mai exact, pentru fiecare
reactiv x, se precizeaz intervalul de temperatur [minx, maxx] n care trebuie s se ncadreze temperatura de
stocare a acestuia.
Reactivii vor fi plasai n frigidere. Orice frigider are un dispozitiv cu ajutorul cruia putem stabili temperatura
(constant) care va fi in interiorul acelui frigider (exprimat ntr-un numr ntreg de grade Celsius).
Cerin
Scriei un program care s determine numrul minim de frigidere necesare pentru stocarea reactivilor chimici.
Date de intrare
Fiierul de intrare react.in conine:
pe prima linie numrul natural N, care reprezint numrul de reactivi;
pe fiecare dintre urmtoarele N linii se afl min max (dou numere ntregi separate printr-un spaiu);
numerele de pe linia x+1 reprezint temperatura minim, respectiv temperatura maxim de stocare a reactivului
x.
Date de ieire
Fiierul de ieire react.out va conine o singur linie pe care este scris numrul minim de frigidere necesar.
Restricii

1 <=N <= 8000

-100 <= minx<= maxx<= 100 (numere ntregi, reprezentnd grade Celsius), pentru orice x de la 1 la N

un frigider poate conine un numr nelimitat de reactivi


Exemple
react.in
3
-10 10
-2 5
20 50

react.out
2

react.in
4
25
57
10 20
30 40

react.out
3

react.in
5
-10 10
10 12
-20 10
7 10
78

react.out
2

Soluie
Intervalele de temperatur pot fi considerate segmente de dreapt. Problema cere, de fapt, determinarea unui
numr minim de puncte astfel nct orice segment s conin cel puin unul dintre punctele determinate.
Vom sorta n primul rnd intervalele de temperatur cresctor dup temperatura minim si descresctor dup
temperatura maxim.
Deschidem un frigider si plasm primul reactiv n acest frigider. Pentru frigiderul curent reinem temperatura
minim i temperatura maxim (intervalul de temperatur n care poate fi setat).
Parcurg succesiv reactivii (n ordine) si pentru fiecare reactiv verificm dac el poate fi plasat n frigiderul curent
(pentru aceasta, trebuie ca intersecia dintre intervalul de temperatur al frigiderului i intervalul de temperatur
al reactivului
s fie nevid). Dac da, plasm acest reactiv n frigiderul curent (actualiznd corespunztor intervalul de
temperatur al frigiderului). n caz contrar, deschidem un nou frigider (intervalul de temperatur al acestui
frigider va fi intervalul reactivului plasat n el).
int N;
int ti[8000], tf[8000];
/*ti[i]=temperatura minima pentru reactivul i
tf[i]=temperatura maxima pentru reactivul i */
int main ()
{
int nf, poz, miny, maxx, aux, i, j, icx, icy,N1;
//citire
f>>N;
for (i=1;i<=N;i++) f>>ti[i]>>tf[i];
//sortare
N1=N;
do
{

Ana ntuneric

52

Ana Intuneric
ok=1;
for (i=1; i<N1; i++)
if(ti[i]>ti[i+1] ||ti[i]==ti[i+1] && tf[i]<tf[i+1])
{aux=ti[i];ti[i]=ti[i+1]; ti[i+1]=aux;
aux=tf[i];tf[i]=tf[i+1]; tf[i+1]=aux;ok=0;}
N1--;
}while(!ok);
/* deschidem un frigider si plasam primul reactiv
icx=temperatura minima de functionare a frigiderului curent
icy=temperatura maxima de functionare a frigiderului curent
nf=numarul de frigidere deschise */
nf=1; icx=ti[1];icy=tf[1];
//parcurgem ceilalti reactivi in ordine
for (i=2; i<=N; i++)
{
// verific daca intervalul curent icx, icy se intersecteaza cu intervalul de temperatura al reactivului i
miny=icy;if (miny>tf[i]) miny=tf[i];
maxx=icx;if (maxx<ti[i]) maxx=ti[i];
if (maxx <= miny) //actualizam intervalul de temperatura
{icx=maxx;icy=miny;}
else //deschid un nou frigider
{
nf++;icx=ti[i];icy=tf[i];
}
}
g<<nf<<'\n';
f.close();g.close();return 0;
}

Bere
N prieteni, numerotai de la 1 la N, beau bere fr alcool la o mas rotund. Pentru fiecare prieten i se cunoate
Ci costul berii lui preferate. Din cnd n cnd, cte un prieten, fie el k, cumpr cte o bere pentru o secven
de prieteni aflai pe poziii consecutive la mas, incepand cu el, n sensul acelor de ceasornic. El este dispus s
cheltuiasc x bani i dorete s fac cinste la un numr maxim posibil de prieteni.
Cerin
Se cere numrul de beri pe care le va cumpra fiecare prieten k n limita sumei x de bani de care dispune. n
caz c x este mai mare dect costul berilor pentru toi prietenii de la mas, se vor achiziiona maxim N beri.
Date de intrare
Prima linie a fiierului de intrare br.in conine dou numere naturale N i T separate printr-un spaiu
reprezentnd numrul de prieteni i respectiv numrul de prieteni care doresc s fac cinste prietenilor si.
A doua linie a fiierului de intrare conine N numere naturale C1, C2 CN, separate prin cte un spaiu,
reprezentnd costurile berilor preferate de fiecare prieten. Berea pentru prietenul i are costul Ci.
Fiecare din urmtoarele T linii conine cte dou numere separate printr-un spaiu:
k1x1
k2x2

kTxT
preciznd indicele cte unui prieten care face cinste i respectiv suma de bani de care acesta dispune..
Date de ieire
Fiierul de ieire br.out va conine T linii, fiecare cu un singur numr Di reprezentnd numrul de beri pe care le
va cumpra prietenul ki cu suma de bani xi in condiiile problemei.
Restricii
1 N 15.000
1 T 10.000
1 Ci 100
1 ki N
1 xi 3.000.000
Un program corect, care se ncadreaz n timp pentru T 4000, va obine cel puin 30 de puncte
Un program corect, care se ncadreaz n timp pentru N 2000, va obine cel puin 60 de puncte
Prietenii beau numai berea lor preferat.
Exemplu

Ana ntuneric

53

Ana Intuneric
br.in

br.out

5
4 3
10 5 15 22 13 4
1
32 0
4
50 5
1
9
4 200

Explicaie
Prietenul 1 cumpr cte o bere pentru el i pentru prietenii 2, 3. Costul celor 3 beri
este 30.
Prietenul 4 cumpr 4 beri: cte una pentru el i pentru prietenii 5, 1, 2. Costul celor
4 beri este 50.
Cu 9 bani prietenul 1 nu poate cumpra nici mcar berea lui.
Prietenul 4 cumpr 5 beri. Costul celor 5 beri este sub limita de cost 200.

1.
Citim initial intr-un vector pret, reprezentand costul berilor celor N prieteni si calculam si suma totala a
costurilor berilor.
2.
Pentru fiecare i de la 1 la T verificam daca suma totala este depasita de suma prietenului i, atunci
afisam valoarea N, daca valoarea este mai mica decat a primului prieten , iar in caz contrar scadem si ne
deplasam la urmatorul prieten
Soluie de 70 de puncte
#include<fstream.h>
int n,t,st;
char pret[15001];
ifstream f("br.in");
ofstream g("br.out");
int main()
{
f>>n>>t;
for(int i = 1; i <= n; i++)
{f>>pret[i]);st=st+pret[i];}
int i,pr,s,total;
for(i = 1; i <= t; i++)
{
f>>pr>>s;
if(st <= s) g<<n<<\n;
else if(s < pret[pr]) g<<"0\n";
else
{
total = 0;
while(s >= pret[pr])
{
s = s-pret[pr++];
if(pr == n+1) pr = 1;
total++;
}
g<<total<<\n;
}
}
f.close(); g.close();
return 0;}

Ana ntuneric

54

Ana Intuneric
Depozit
Considerm un depozit cu n (n1000) camere, care conin respectiv cantitilede marf C1, C2, , Cn,
(numere naturale). Scriei un program care s determineun grup de camere cu proprietatea c suma
cantitilor de marf pe care le conin sepoate mpri exact la cele n camioane care o transport.
Soluie
Problema solicit determinarea unei submulimi a unei mulimicu n elemente, divizibil tot cu n. Vom
construi sumele S1, S2, ..., Sn i resturilepe care acestea le dau prin mprire la n astfel:
S1=C1 R1=S1 % n
S2=C1+C2 R2=S2 % n
...
Si=C1+C2+...+Ci Ri=Si % n
...
Sn=C1+C2+...+Cn Rn=Sn % n
Cazul I: Exist un rest Ri=0. n acest caz suma Si este divizibil cu n, prinurmare camerele solicitate sunt
1, 2, ..., i.
Cazul II: Toate resturile sunt diferite de 0. Prin urmare R1, R2, ..., Rn sunt nresturi care iau valori n
muliimea {1, 2, ..., n-1}. n mod obligatoriu exist celpuin dou resturi egale: Ri=Rj (i<j), adic Si i Sj
produc acelasi rest lamprirea cu n suma Sj-Si este divizibil cu n, deci camerele solicitate sunt
i+1, i+2, ..., j.
Observaii
1. Soluia nu este unic. Procedeul prezentat produce o soluie posibil.
2. Rezolvarea se bazeaz pe Principiul cutiei al lui Dirichlet.
int SR[100], n, i, j, k, c;
int main()
{
f>>n;
//calculez sumele de la citire
for (i=1; i<=n; i++)
{
f>>c;SR[i]=SR[i-1]+c;
}
for (i=1; i<=n; i++) SR[i]%=n; //calculez resturile
for (i=1; i<=n; i++) //caut un rest = 0
if (SR[i]==0){for(k=1;k<=i; k++) g<<k<<' '; f.close();g.close();return 0;}
//cazul II, caut doua resturi egale
for (i=1; i<n; i++)
for (j=i+1; j<=n; j++)
if (SR[i]==SR[j]){for(k=i+1;k<=j;k++) g<<k<<' ';
f.close();g.close();return 0;
}

iruri de caractere
TEXT
Vasile lucreaz intens la un editor de texte. Un text este format din unul sau mai multe paragrafe. Orice
paragraf se termin cu Enter i oricare dou cuvinte consecutive din acelai paragraf sunt separate prin
spaii (unul sau mai multe). n funcie de modul de setare a paginii, numrul maxim de caractere care ncap
n pagin pe o linie este unic determinat (Max).
Funcia pe care Vasile trebuie s o implementeze acum este alinierea n pagin a fiecrui paragraf din text
la stnga i la dreapta. Pentru aceasta el va trebui s mpart fiecare paragraf n linii separate de lungime
Max (fiecare linie terminat cu Enter). mprirea se realizeaz punnd numrul maxim posibil de cuvinte
pe fiecare linie, fr mprirea cuvintelor n silabe. Pentru aliniere stnga-dreapta, el trebuie s repartizeze
spaii n mod uniform ntre cuvintele de pe fiecare linie, astfel nct ultimul caracter de pe linie s fie diferit
de spaiu, iar numrul total de caractere de pe linie s fie egal cu Max. Excepie face numai ultima linie din

Ana ntuneric

55

Ana Intuneric

paragraf, care rmne aliniat la stnga (cuvintele fiind separate printr-un singur spaiu, chiar dac linia nu
este plin).
n general, este puin probabil ca alinierea s fie realizabil prin plasarea aceluiai numr de spaii ntre
oricare dou cuvinte consecutive de pe linie. Vasile consider c este mai elegant ca, dac ntre unele
cuvinte consecutive trebuie plasat un spaiu n plus fa de alte perechi de cuvinte consecutive, acestea s
fie plasate la nceputul liniei.
Cerin
Scriei un program care s citeasc lungimea unei linii i textul dat i care s alinieze textul la stnga i la
dreapta.
Date de intrare
Fiierul de intrare text.in conine pe prima linie Max, lungimea maxim a unui rnd.
Pe urmtoarele linii este scris textul.
Date de ieire
Fiierul de ieire text.out conine textul aliniat stnga-dreapta.
Restricii
2<=Max<=1000
Lungimea maxim a oricrui cuvnt din text este 25 caractere i nu depete Max.
Lungimea unui paragraf nu depete 1000 de caractere.
Soluia este unic.
Exemple
text.in
text.out
Explicaie
20
Vasile are multe
Pe prima linie au fost plasate cte
Vasile are multe bomboane bune.
bomboane bune.
3
spaii
ntre
cuvintele
consecutive.
text.in
text.out
Explicaie
20
Ana are mere.
ntre Ion i are exist 2 spaii,
Ana are mere.
Ion
are
multe pere ntre are i multe- 2 spaii, iar
Ion are multe pere galbene?
galbene?
ntre multe i pere- 1 spaiu.
Observai c paragraful Ana are mere. (care are lungimea mai mic dect 20) a rmas aliniat la stnga, iar
ultima linie din fiecare paragraf rmne aliniat la stnga, cuvintele consecutive fiind separate printr-un
singur spaiu.
#include <fstream>
#include <string.h>
using namespace std;
ifstream f("text.in");
ofstream g("text.out");
char prg[1001];//memorez paragraful curent
char cuv[1001][26];//memorez cuvintele liniei curente
int Max,nrl,LgLinie;
void afiseaza_linie(int u)
{
int i, j, cate, rest, nrsp;
if(u!=0)//ultima linie
for(i=0;i<nrl-1;i++) g<<cuv[i]<<' ';
else
{
cate=Max-LgLinie; rest=cate%(nrl-1); nrsp=cate/(nrl-1);
for(i=0;i<nrl-1;i++)
{
g<<cuv[i];for(j=0;j<=nrsp;j++) g<<' ';
if(rest>0){g<<' ';rest--;}
}
}
if(nrl>0)g<<cuv[nrl-1]<<endl;else g<<endl;
}
void afiseaza_paragraf()
{

Ana ntuneric

56

Ana Intuneric
char *p;
int LgCuv;
LgLinie=-1; nrl=0;
p=strtok(prg," ");//decupez primul cuvant
while(p)
{
LgCuv=strlen(p);//p=cuvantul curent
if (LgLinie+LgCuv+1<=Max){strcpy(cuv[nrl],p); nrl++; LgLinie+=LgCuv+1;}
else
{afiseaza_linie(0); //afisez linia curenta
nrl=1; LgLinie=LgCuv; strcpy(cuv[0],p);//trec la linia urmatoare
}
p=strtok(NULL," ");//decupez urmatorul cuvant
}
afiseaza_linie(1);//afisez cuvintele paragrafului
}
int main()
{
f>>Max; f.get();//golesc buffer-ul de citire
//citesc paragraf cu paragraf
while(f.getline(prg,1001))
afiseaza_paragraf();
f.close(); g.close();return 0;
}

comp
Locuitorii planetei Eudora folosesc o reprezentare mai ciudat a numerelor naturale, astfel c orice numr
natural va fi scris notnd cte mii, sute, zeci, respectiv uniti conine acesta. De exemplu, numrul 3207 se
poate reprezenta n mai multe moduri echivalente: 3m2s7u (3 mii 2 sute i 7 uniti), 32s0z7u (32 sute 0
zeci i 7 uniti), 32s7u, 3207u, etc.
Pentru a compara dou numere naturale, eudorienii folosesc semnele < i >, acestea avnd semnificaia
cunoscut i pe Terra, iar pentru a calcula suma a dou numere naturale utilizeaz semnul +.
Pentru a testa abilitile pmntenilor n privina lucrului cu numere naturale, eudorienii au trimis pe Terra
un fiier text ce conine N linii, fiecare linie fiind o comparaie de forma:
expresie1>expresie2
sau
expresie1<expresie2
Observai c o comparaie este constituit din dou expresii separate prin semnul < sau prin semnul >.
O expresie este compus dintr-un numr natural sau dintr-o sum de dou sau mai multe numere naturale,
toate scrise n forma eudorian. Fiierul nu conine caractere spaiu.
Cerin
Scriei un program care determin cte dintre comparaiile date utilizeaz semnul <, precum i valoarea de
adevr a fiecrei comparaii dintre cele N date (afind 0 dac acea comparaie e fals, respectiv 1 dac
acea comparaie e adevrat).
Date de intrare
Fiierul comp.in conine pe prima linie numrul natural nenul N, reprezentnd numrul de comparaii, iar pe
fiecare dintre urmtoarele N linii cte un ir de caractere corespunztor unei comparaii.
Date de ieire
Fiierul comp.out va conine pe prima linie un numr natural reprezentnd numrul de comparaii n care se
utilizeaz semnul <. Urmeaz N linii, fiecare linie coninnd doar valoarea 0 sau valoarea 1. Valoarea de pe
a i-a linie dintre cele N este 0, dac cea de-a i-a comparaie din fiierul de intrare este fals, respectiv 1 n
caz contrar.
Restricii
0 < N 1000
Numerele din fiier nu depesc n valoare numrul eudorian 1000m1000s1000z1000u.
Lungimea fiecrei linii din fiier este cel mult 250.
Punctaj. Dac numrul de comparaii care utilizeaz semnul < este corect se va acorda 20% din

Ana ntuneric

57

Ana Intuneric
punctajul pe test. Punctajul integral se acord pentru rezolvarea corect a ambelor cerine.
Exemplu
comp.in
comp.out
2
1
120u+7z13u>2s13u
0
1m11s+2z+1u<2m1s2z5u+0u
1
Timp maxim de execuie/test: 1 secund

Explicaii
O comparaie folosete semnul <.
Prima comparaie e fals (203>213).
A doua comparaie e adevrat (2121<2125).

int n,nr;
char s[251];
bool v[1001];
int transformare(char *p)//transformare numar eudorian in numar zecimal
{
int nr=0,x=0;
for(int i=0;i<strlen(p);i++)
if(p[i]>='0' && p[i]<='9') //daca p[i] e cifra
x=x*10+(p[i]-'0');
else
{
if(p[i]=='m') x*=1000;
else if(p[i]=='s') x*=100;
else if(p[i]=='z')x*=10;
else x*=1;
nr+=x;x=0;
}
return nr;
}
int prelucrare(char s[])
{
bool semn=1;
int e1=0; int e2=0;
if(strchr(s,'<')) semn=0;
char *p1=strtok(s,"<>");//prima expresie
char *p2=strtok(NULL,"<>");//a doua expresie
char *p11=strtok(p1,"+");
while(p11)
{
e1+=transformare(p11);
p11=strtok(NULL,"+");
}
char *p22=strtok(p2,"+");
while(p22)
{
e2+=transformare(p22);
p22=strtok(NULL,"+");
}
if(semn && e1<=e2) return 0;
if(semn==0 && e1>=e2) return 0;
return 1;
}
int main()
{
f.getline(s,251); int i;//citire n ca sir
for(i=0;i<strlen(s);i++)
n=n*10+(s[i]-'0');
for(i=1;i<=n;i++)
{
f.getline(s,251);
if(strchr(s,'<')) nr++;
if(prelucrare(s)) v[i]=1;

Ana ntuneric

58

Ana Intuneric
else v[i]=0;
}
g<<nr<<'\n';
for(i=1;i<=n;i++) g<<v[i]<<'\n';
f.close(); g.close();return 0;

Ana ntuneric

59