Sunteți pe pagina 1din 6

SUBIECTUL I

1. Răspuns corect: c

Justificare: dacă desfaceţi parantezele şi aplicaţi negaţia unei expresii logice compuse
se obţine:
x>=18 && x>=19 && x<=20 && x<=21
Pe acest caz particular se observă că prima şi ultima condiţie sunt redundante (de fapt
din primele două rămâne valabilă doar x>=19 iar din ultimele două doar x<=20).

2. Răspuns corect: c

Justificare: Avem de-a face cu o problemă de generare în care trebuie ca, dintr-o mulţime
cu 5 elemente să determinăm toate posibilităţile de a pune în orice ordine diferită, cele
5 elemente. Aşadar, este vorba de generarea
permutărilor.
Pe modelul dat, ne dăm seama că putem reduce la
permutarea mulţimii {1,2,3,4,5} pentru care
1=caprifoi, 2=iasomie, 3=liliac, 4=tamarix, 5=scumpie

(!!ce-o fi asta?! - sunt prea curios să nu gugălesc...


aha, e Cotinus coggygria, adică planta asta din poză)

Închidem paranteza.
So, ne trebuie de fapt penultima soluţia de la
permutări de 5. Ea este:
(5,4,3,1,2)
care după reidentificarea plantelor cu numere devine
(scumpie, tamarix, liliac, caprifoi, iasomie)

3. Răspuns corect: a

Justificare: acesta este genul de exerciţiu la care putem să nici nu citim enunţul (e
recomandat să nu faceţi, totuşi, acest lucru, la examenul de bacalaureat) deoarece, prin
simpla inspectare a răspunsurilor şi pe baza struct-ului definit alăturat (şi a
variabilelor A,B definite acolo) ne dăm seama că răspunsurile b,c,d sunt non-sensuri, ba
chiar dau eroare dacă am scrie aşa ceva în C++

4. Răspuns corect: d

Dacă desenăm graful pe baza muchiilor date, obţinem un arbore neierarhizat, ca în figura
de mai jos. Pe acest arbore chiar şi aşa, neierarhizat, ne-apucăm să numerotăm rădăcina
cu 0, apoi vecinii săi nenumerotaţi deja cu 1, apoi vecinii ăstora cu 1, nenumerotaţi
deja, cu 2. Astfel, deducem nodurile care se află pe nivelul al 2-lea:
5. Răspuns corect: b

Un graf tare conex are proprietatea că există drum între oricare două vârfuri pe care le
alegem din acest graf. Cel mai "sărac" în arce graf orientat care este tare conex, este
un graf care conţine un circuit elementar prin toate vârfurile grafului. Încercăm să ne
bazăm pe acest lucru şi, dacă nu putem forma un astfel de circuit, măcar să descoperim
cele mai lungi lanţuri din graf şi să le închidem pe acestea.
Vedem că, pe graful dat, oricum am pune un arc nu putem rezolva problema, pe când cu două
arce poate fi rezolvată, ca în desenul de mai jos:

SUBIECTUL al II-lea

1. Algoritmul este ceva mai greu de analizat "printre rânduri", astfel că începem prin a
urmări evoluţia valorilor variabilelor pentru cerinţa de la punctul a) şi apoi încercăm o
generalizare a efectului algoritmului:

a) Răspuns: 4 (se afişează valoarea lui nr - ultima din tabelul de mai jos

n | nr| i | x | y | r | j | După ce am analizat evoluţia variabilelor pe tabelul


---+---+---+---+---+---+---+ alăturat, observăm următoarele:
7 | 0 | 1 | 0| 1| | 1 | - există o repetitivă exterioară care este echivalentă
| 1 | 2 | 0| 1| -1| 1 | cu un for i1,7
| | | 1| -1| | 2 | - în aceasta există o repetitivă interioară care
| | 3 | 0| 1| -1| 1 | generează, fără a folosi un vector, termenii şirului
| | | 1| -1| 3| 2 | 1 -1 3 -5 11 -21 43 -85 171 ...
| 2 | | -1| 3| | 3 | (ultimul termen se obţine pe baza celor 2 anteriori prin
| | 4 | 0| 1| -1| 1 | formula 2*x-y unde y este termenul anterior celui curent
| | | 1| -1| 3| 2 | iar x este termenul anterior lui y)
| | | -1| 3| -5| 3 | - la fiecare pas i, se testează dacă ultimul termen
| | | 3| -5| | 4 | generat din acest şir este pozitiv iar dacă da, se
| | 5 | 0| 1| -1| 1 | numără (am colorat cu verde / roşu valorile care se
| | | 1| -1| 3| 2 | testează şi care produc / NU produc creşterea lui nr)
| | | -1| 3| -5| 3 |
| | | 3| -5| 11| 4 | Deci, de fapt algoritmul numără câţi dintre primii n
| 3 | | -5| 11| | 5 | termeni ai acestui şir sunt pozitivi.
| | 6 | 0| 1| -1| 1 |
| | | 1| -1| 3| 2 | În final, deducem că, datorită faptului că termenii
| | | -1| 3| -5| 3 | alternează la pozitiv/negativ/pozitiv/negativ..., acest
| | | 3| -5| 11| 4 | număr se învârte în jurul jumătăţii lui n, deci tot
| | | -5| 11|-21| 5 | acest algoritm complicat este perfect echivalent cu
| | | 11|-21| | 6 | următorul:
| | 7 | 0| 1| -1| 1 |
| | | 1| -1| 3| 2 | citește n (număr natural nenul)
| | | -1| 3| -5| 3 | scrie [(n+1)/2] (unde cu [] am notat partea întreagă)
| | | 3| -5| 11| 4 |
| | | -5| 11|-21| 5 |
| | | 11|-21| 43| 6 |
| 4 | |-21| 43| | 7 |
| | 8 | | | | |

b) Pe baza a ceea ce am descoperit că algoritmul face, la punctul a) deducem că există de


fapt doar două răspunsuri posibile pentru acest punct:
Răspuns: 19 şi 20
c)
#include <iostream>
using namespace std;

int main()
{
int n,nr,i,x,y,r,j;
cin>>n;
nr=0;i=1;
while(i<=n)
{
x=0;y=1;j=1;
while(j<i)
{
r=2*x-y;x=y;y=r;
j++;
}
i++;
if(y>0)nr++;
}
cout<<nr;
return 0;
}

d) Ştim că nu orice cât timp se poate înlocui cu pentru (ne referim aici STRICT la
pseudocod - în C++ acest lucru ESTE posibil pe orice caz, însă în pseudocod NU) însă în
algoritmul de faţă ambele repetitive pot fi înlocuite, pentru că de fapt ambele joacă
rolul unor for-uri.
- Dacă o înlocuim pe prima obţinem acest algoritm:

citește n (număr natural nenul)


nr <- 0
┌pentru i <- 1,n execută
│ x <- 0; y <- 1; j <- 1
│ ┌cât timp j<i execută
│ │ r <- 2*x-y; x <- y; y <- r
│ │ j <- j+1
│ └■
│ ┌dacă y>0 atunci
│ │ nr <- nr+1
│ └■
└■
scrie nr

- Dacă o înlocuim pe a doua obţinem acest algoritm:


(remarcăm că al doilea while merge cu j<i, deci pe for, limita finală este i-1)

citește n (număr natural nenul)


nr <- 0; i <- 1
┌cât timp i≤n execută
│ x <- 0; y <- 1
│ ┌pentru j <- 1,i-1 execută
│ │ r <- 2*x-y; x <- y; y <- r
│ └■
│ i <- i+1
│ ┌dacă y>0 atunci
│ │ nr <- nr+1
│ └■
└■
scrie nr
2. Dacă luăm un exemplu (f(10,3) respectiv f(3,10)) observăm că funcţia este simetrică.
Întrucât nu putem da un sens algebric foarte precis a ceea ce face această funcţie
recursivă, ne limităm în a testa valori.
Astfel, vom regăsi posibile valori pentru x1 şi x2:
x1 poate fi 6
x2 poate fi 10

3. Există o serie de metode de rezolvare pentru acest exerciţiu.


Cel mai elegant şi scurt de scris, dar destul de algebric, este următorul:

for(i=0;i<4;i++)
for(j=0;j<5;j++)
a[i][j]=15-5*i+j+1;

SUBIECTUL al III-lea:

1) Problema este una clasică, facem descompunere în factori primi şi apoi reînmulţim
factorii fără a îi ridica la putere
Ţinem cont de cerinţă: rezultatul NU este întors de funcţie (deci funcţia este de tip
void) ci este întors prin intermediul parametrului p.
Am folosit versiunea eficientă de descompunere în factori primi:

void prodprim(int n,int &p)


{
p=1;
int f=2,pw;
while(f*f<=n)
{
pw=0;
while(n%f==0)
{
n/=f;
pw++;
}
if(pw)
p*=f;
f++;
}
if(n)
p*=n;
}

La bacalaureat, veţi scrie DOAR implementarea acestei funcţii. Evident, în fazele de


antrenament, scrieţi şi-un main minimal ca să vă puteţi testa dacă funcţia scrisă de voi
este corectă. În arhiva ataşată, găsiţi acest exerciţiu implementat cu tot cu un main
care citeşte o valoare, aplică funcţia şi afişează rezultatul.
2) Din nou avem de-a face cu o problemă destul de clasică: facem mai întâi o separare a
stringului în cuvinte (alegem varianta strtok pentru că este cel mai comod de scris) iar
apoi, pentru fiecare cuvânt numărăm câte consoane şi câte vocale are. Ţinem cont că
trebuie tratat şi cazul "nu există"
/**
Din nou avem de-a face cu o problemă destul de clasică: facem mai întâi
o separare a stringului în cuvinte (alegem varianta strtok pentru că este
cel mai comod de scris) iar apoi, pentru fiecare cuvânt numărăm câte
consoane şi câte vocale are. Ţinem cont că trebuie tratat şi cazul "nu există"
*/
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
char s[101],*p;
int nc,nv,i,ok=0;
cin.getline(s,101);///musai citit cu cin.getline pentru că are spaţii
for(p=strtok(s," ");p;p=strtok(NULL," "))///facem un strtok clasic
{
nc=nv=0;
///parcurgem cuvântul p:
for(i=0;p[i];i++)
if(strchr("aeiou",p[i]))nv++;///dacă litera curentă e vocală o numărăm în nv
else nc++;///în caz contrar în nc
if(nv<nc)
{
cout<<p<<"\n";
ok=1;
}
}
if(!ok)
cout<<"Nu exista";
return 0;
}

3) Remarcăm în primul rând o mică "scăpare" în enunţ: există situaţii în care nu avem
soluţie, de exemplu pentru orice număr prim de 2 cifre şi nu numai. Dacă scapă la bac un
astfel de exerciţiu cu greşeli (sau, mă rog, situaţii neprecizate) e ok să scrieţi voi că
în exerciţiu nu se precizează şi care este decizia pe care aţi luat-o pentru tratarea
acestui caz.
Eu de exemplu, aici, voi lua decizia ca, dacă nu există soluţii să nu afişez nimic (aş
mai fi putut opta să aleg soluţia de a afişa un mesaj de genul "nu există")
Ca să ne fie mai uşor de rezolvat, să luăm un exemplu:
(aleg exemplul a.i. să nu fie extrem de multe soluţii)
de exemplu p1=12 şi p2=7
Pentru p1 avem combinaţiile: 62,43,34,26 iar pentru p2: 71 şi 17
soluţiile ar fi deci
6299971 | 6299917 | 4399971 | 4399917 | 3499971 | 3499917 | 1799971 | 1799917
6288871 | 6288817 | 4388871 | 4388817 | 3488871 | 3488817 | 1788871 | 1788817
6277771 | 6277717 | 4377771 | 4377717 | 3477771 | 3477717 | 1777771 | 1777717
6266671 | 6266617 | 4366671 | 4366617 | 3466671 | 3466617 | 1766671 | 1766617
6255571 | 6255517 | 4355571 | 4355517 | 3455571 | 3455517 | 1755571 | 1755517
6244471 | 6244417 | 4344471 | 4344417 | 3444471 | 3444417 | 1744471 | 1744417
6233371 | 6233317 | 4333371 | 4333317 | 3433371 | 3433317 | 1733371 | 1733317
6222271 | 6222217 | 4322271 | 4322217 | 3422271 | 3422217 | 1722271 | 1722217
6211171 | 6211117 | 4311171 | 4311117 | 3411171 | 3411117 | 1711171 | 1711117
6200071 | 6200017 | 4300071 | 4300017 | 3400071 | 3400017 | 1700071 | 1700017
Aşadar începem cu b)-ul:
Descrierea algoritmului: Atât pentru p1 cât şi pentru p2, e suficient să generăm doar una
dintre cifrele, deoarece pe-a doua o obţinem împărţind p1 la prima cifră, punând mai
întâi condiţia ca p1 să se dividă cu cifra respectivă. Procedăm analog şi la p2. Între
ele punem în ordine descrescătoare toate cifrele de la 9 la 0, necondiţionat.
De exemplu, dacă p1=12 luăm toate posibilităţile pt. prima cifră: 9,8,7,6,5,4,3,2,1
(0 nu poate fi, nici pt. p1, nici pt. p2, deoarece se garantează că p1, p2 0). Dacă p1
se împarte la vreuna dintre ele (de ex. p1 se împarte la 6) cealaltă e pur şi simplu
p1/6.

Astfel, numărul total de paşi pe care îl face algoritmul este de 9 pt. a parcurge cifrele
pt. p1, combinaţi cu alţi 9 pt. a parcurge cifrele pt. p2, combinaţi cu exact 10 pt.
cifrele din mijloc.
Astfel, numărul total de paşi ai algoritmului este 9*9*10=810, ceea ce este foarte
rezonabil pentru orice date de intrare.

Practic, algoritmul este eficient d.p.d.v. al timpului de executare deoarece se fac


puţini paşi, şi anume maxim 810, fiind destul de puţin paşi făcuţi în gol, adică fără a
se determina vreo soluţie pe care o şi afişăm.
Este eficient şi d.p.d.v. al memoriei, deoarece nu utilizăm decât câteva variabile
simple.

a)
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
ofstream fout("bac.out");
int p1,p2,i,j,k;
cin>>p1>>p2;
for(i=9;i>=1;i--)
if(p1%i==0 && p1/i<=9)
for(j=9;j>=1;j--)
if(p2%j==0 && p2/j<=9)
for(k=9;k>=0;k--)
fout<<i<<p1/i<<k<<k<<k<<j<<p2/j<<"\n";
return 0;
}

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

  • Vocab
    Vocab
    Document1 pagină
    Vocab
    Doru MODRISAN
    Încă nu există evaluări
  • Cicloida
    Cicloida
    Document2 pagini
    Cicloida
    Doru MODRISAN
    Încă nu există evaluări
  • Cicloida
    Cicloida
    Document2 pagini
    Cicloida
    Doru MODRISAN
    Încă nu există evaluări
  • 22 12 13lucrare
    22 12 13lucrare
    Document3 pagini
    22 12 13lucrare
    Doru MODRISAN
    Încă nu există evaluări