Sari la conținut

Bac informatică 2021 Simulare, rezolvată

Simularea de la Bacalaureatul la Informatică (Mate-Info, C/C++): conține 3 subiecte (90 de puncte) și are un timp de lucru de 3 ore. Sub fiecare exercițiu găsești răspunsul corect și rezolvarea.

Subiecte oficiale publicate de Ministerul Educației. Rezolvări realizate de subac. Actualizat la .

📌 Despre Simularea din 2021

Simularea din 2021 trece prin expresii logice, backtracking, structuri imbricate, recursivitate, grafuri și arbori, șiruri de caractere, matrice și fișiere. Este o variantă echilibrată, bună pentru recapitularea întregii materii.

Subiectul I (20p): 5 grile: intervalul pe care o expresie cu negații are valoarea 1, o problemă de backtracking cu numere formate din cifrele lui 289, o atribuire corectă într-o structură care conține altă structură, condiția care face dintr-un subprogram recursiv algoritmul lui Euclid prin scăderi și numărul de muchii ale unui graf cu 40 de noduri și 5 componente conexe care sunt arbori.

Subiectul al II-lea (40p): Un algoritm în pseudocod care mută fiecare cifră nenulă a unui număr la coada sau în fața rezultatului, un lanț neelementar și un ciclu elementar într-un graf dat prin liste de adiacență și o secvență care transformă șirul ELITIST caracter cu caracter.

Subiectul al III-lea (30p): Un subprogram (putere) care returnează factorul prim cu puterea cea mai mică din descompunerea lui n, o problemă cu matrice în care elementele din stânga diagonalei principale de pe linia k se deplasează circular spre dreapta și o problemă de eficiență cu costul elementelor grafice ale unui site, citite din fișierul bac.in.

⚠️ La ce să fii atent

  • La I.1: Scapă de negații pe rând! Condiția din mijloc, !(x<2002 || x>2020), este cea mai strânsă, deci intervalul este [2002,2020].
  • La I.2: Numerele trebuie să fie strict mai mici decât 289, deci 289 nu se generează. După 282 și 288 vine 29, iar 8 este al 10-lea număr generat.
  • La II.1.a: Cifra 0 este sărită de tot: nu ajunge în rezultat, iar p nu se înmulțește cu 10 la pasul ei. Rezultatul este 2197553.
  • La III.1: Dacă mai mulți factori primi apar la aceeași putere minimă, returnezi cel mai mic dintre ei. La 880, 5 și 11 apar amândoi la puterea 1, iar răspunsul este 5.
  • La III.3: Taxa de 10 lei se plătește o singură dată pentru fiecare model, nu pentru fiecare element. Cum laturile sunt între 1 și 10, un vector de frecvență cu 10 poziții e suficient, oricât de lung ar fi fișierul.

Subiectul I

20 de puncte
  1. Exercițiul 1 4p Expresii și operatori

    Expresia C/C++ are valoarea 1 dacă și numai dacă valoarea memorată de variabila reală x aparține intervalului:

    !(x<2001) && !(x<2002 || x>2020) && !(x>2021)
    • a)[2001,2002]
    • b)[2001,2020]
    • c)[2002,2020]
    • d)[2002,2021]
    Vezi rezolvarea

    Răspuns corect: c) [2002,2020]

    Se scapă de negații, una câte una:

    • !(x<2001) înseamnă x≥2001
    • !(x<2002 || x>2020) înseamnă x≥2002 și x≤2020
    • !(x>2021) înseamnă x≤2021

    Toate trei trebuie să fie adevărate deodată. Condiția din mijloc e cea mai strânsă: ea cere deja x≥2002, mai mult decât prima, și x≤2020, mai mult decât a treia.

    Rămâne intervalul [2002, 2020], varianta c).

  2. Exercițiul 2 4p Backtracking

    Utilizând metoda backtracking se generează toate valorile naturale formate cu cifre ale numărului 289 și care sunt strict mai mici decât acesta. Primele șase numere generate sunt, în această ordine:

    1. 2
    2. 22
    3. 222
    4. 228
    5. 229
    6. 28

    Indicați al câtelea număr generat este 8.

    • a)al 10-lea
    • b)al 9-lea
    • c)al 8-lea
    • d)al 7-lea
    Vezi rezolvarea

    Răspuns corect: a) al 10-lea

    Backtracking-ul construiește numerele cifră cu cifră, folosind doar cifrele 2, 8 și 9, și reține fiecare valoare mai mică decât 289. Un număr se prelungește doar cât timp rămâne sub 289:

    nr.valoare
    12
    222
    32222222 ar depăși, deci nu se mai prelungește
    4228
    5229
    628
    7282
    8288289 nu se ia: nu e strict mai mic
    929292, 298, 299 depășesc
    108

    Primele șase coincid cu cele din enunț. 8 este deci al 10-lea, varianta a).

  3. Exercițiul 3 4p Tipul înregistrare (struct)

    Variabila s este declarată alăturat.

    Indicați o instrucțiune de atribuire corectă din punctul de vedere sintactic.

    struct site
    {  char cod;
       struct
       {  int nrAccesari,nrAprecieri;
       }vizite;
    }s;
    • a)s(cod,nrAccesari,nrAprecieri)=(1,10,2);
    • b)s=(1,(10,2));
    • c)s.vizite.nrAccesari=2*s.vizite.nrAprecieri;
    • d)s.site.cod=2021;
    Vezi rezolvarea

    Răspuns corect: c) s.vizite.nrAccesari=2*s.vizite.nrAprecieri;

    Structura are un câmp simplu, cod, și un câmp vizite care e la rândul lui o structură cu nrAccesari și nrAprecieri. Accesul se face punct după punct, de la variabilă spre câmpul dorit: s.vizite.nrAccesari — varianta c) e corectă sintactic.

    Celelalte greșesc fiecare altceva: a) folosește paranteze, ca la un apel de funcție; b) încearcă să atribuie toată structura dintr-o listă de valori, ceea ce nu se poate așa; d) pune numele tipului (site) în mijlocul accesului, deși după s. urmează direct numele câmpului.

  4. Exercițiul 4 4p Recursivitate

    Subprogramul f este definit alăturat.

    Indicați o expresie care poate înlocui punctele de suspensie, astfel încât valoarea f(50,2020) să fie egală cu cel mai mare divizor comun al numerelor 50 și 2020.

    int f(int x, int y)
    { if(x==y) return x;
      else if(..........) return f(x-y,y);
           else return f(x,y-x);
    }
    • a)x/10!=0
    • b)x%10!=0
    • c)x+y>0
    • d)x-y>0
    Vezi rezolvarea

    Răspuns corect: d) x-y>0

    Subprogramul e algoritmul lui Euclid prin scăderi repetate: din cel mai mare se scade cel mai mic, până când cele două devin egale — iar atunci valoarea comună e cel mai mare divizor comun.

    Pentru ca scăderea să meargă în direcția bună, ramura f(x-y,y) trebuie aleasă exact când x e mai mare decât y, adică atunci când x-y>0 — varianta d).

    Celelalte n-ar merge: a) și b) se uită la cifrele lui x, fără legătură cu comparația, iar c) e adevărată aproape mereu, deci s-ar scădea y din x chiar și când x<y, iar numerele ar fugi spre valori negative în loc să se apropie.

  5. Exercițiul 5 4p Arbori

    Un graf neorientat are 40 de noduri și 5 componente conexe, fiecare dintre acestea fiind arbore.

    Indicați numărul de muchii ale grafului.

    • a)33
    • b)35
    • c)39
    • d)41
    Vezi rezolvarea

    Răspuns corect: b) 35

    Un arbore cu k noduri are k-1 muchii.

    Graful are 5 componente conexe, fiecare fiind arbore. Dacă ele au k₁, k₂, …, k₅ noduri, cu k₁+…+k₅ = 40, atunci numărul total de muchii este:

    `(k₁-1) + (k₂-1) + … + (k₅-1) = 40 - 5 = 35`

    Varianta b). Observă că nu contează cum sunt împărțite nodurile între componente — se scade câte 1 pentru fiecare componentă, și atât.

Subiectul al II-lea

40 de puncte
  1. Exercițiul 1.a 6p Algoritmi în pseudocod

    Algoritmul alăturat este reprezentat în pseudocod.

    S-a notat cu a%b restul împărțirii numărului natural a la numărul natural nenul b și cu [c] partea întreagă a numărului real c.

    Scrieți valoarea afișată dacă se citește numărul 35210579.

     citește x  (număr natural)
      p←1; y←0
    ┌repetă
    │ c←x%10; x←[x/10]
    │┌dacă c≠0 atunci
    ││┌dacă x%10<c atunci y←y*10+c
    │││altfel y←c*p+y
    ││└■
    ││ p←p*10
    │└■
    └până când x=0
     scrie y
    Vezi rezolvarea

    Răspunsul din barem: 2197553

    Algoritmul ia cifrele lui x de la dreapta la stânga, sare peste zerouri și așază fiecare cifră fie la coadă, fie în față, după cum e mai mică sau nu decât cifra dinaintea ei în număr.

    ccifra următoare (x%10)unde se puney
    97mai mică → la coadă9
    75mai mică → la coadă97
    50mai mică → la coadă975
    0—se sare peste975
    12nu e mai mică → în față1975
    25nu e mai mică → în față21975
    53mai mică → la coadă219755
    30mai mică → la coadă2197553

    Se afișează 2197553. Zeroul din 35210579 nu apare deloc în rezultat, iar p nu crește când se sare peste el.

  2. Exercițiul 1.b 6p Algoritmi în pseudocod

    Același algoritm ca la 1.a.

    S-a notat cu a%b restul împărțirii numărului natural a la numărul natural nenul b și cu [c] partea întreagă a numărului real c.

    Scrieți două numere din intervalul [10^3,10^4) care pot fi citite, astfel încât, pentru fiecare dintre acestea, în urma executării algoritmului, numărul afișat să fie 212.

    Vezi rezolvarea

    2012 2201

    Sunt exact trei numere de patru cifre care dau 212: 2012, 2201 și 2210.

    Urmărește 2012 — cifrele se iau de la dreapta, iar fiecare se compară cu cifra rămasă imediat în stânga ei:

    ccifra din stângaunde se puney
    211 < 2 → la coadă2
    100 < 1 → la coadă21
    0—zero, se sare peste21
    200 < 2 → la coadă212

    Toate cifrele nenule au ajuns la coadă, în ordinea în care au fost citite, iar zeroul a fost sărit. Așa se obține 212.

    2201 și 2210 ajung la același rezultat pe alt drum: contează care cifre sunt nenule și cum se compară fiecare cu vecina din stânga.

  3. Exercițiul 1.c 10p Algoritmi în pseudocod

    Același algoritm ca la 1.a.

    S-a notat cu a%b restul împărțirii numărului natural a la numărul natural nenul b și cu [c] partea întreagă a numărului real c.

    Scrieți programul C/C++ corespunzător algoritmului dat.

    Vezi rezolvarea
    #include <iostream>
    using namespace std;
    
    int main()
    {
        int x, p = 1, y = 0, c;
        cin >> x;
        do
        {
            c = x % 10;
            x = x / 10;
            if (c != 0)
            {
                if (x % 10 < c)
                    y = y * 10 + c;
                else
                    y = c * p + y;
                p = p * 10;
            }
        } while (x != 0);
        cout << y;
        return 0;
    }
  4. Exercițiul 1.d 6p Algoritmi în pseudocod

    Același algoritm ca la 1.a.

    S-a notat cu a%b restul împărțirii numărului natural a la numărul natural nenul b și cu [c] partea întreagă a numărului real c.

    Scrieți în pseudocod un algoritm echivalent cu cel dat, înlocuind structura repetă...până când cu o structură repetitivă cu test inițial.

    Vezi rezolvarea

    `` citește x (număr natural) p←1; y←0 c←x%10; x←[x/10] ┌dacă c≠0 atunci │┌dacă x%10<c atunci y←y*10+c ││altfel y←c*p+y │└■ │ p←p*10 └■ ┌cât timp x≠0 execută │ c←x%10; x←[x/10] │┌dacă c≠0 atunci ││┌dacă x%10<c atunci y←y*10+c │││altfel y←c*p+y ││└■ ││ p←p*10 │└■ └■ scrie y ``

    Condiția de oprire x=0 devine condiție de continuare negată: cât timp x≠0.

    Prelucrarea primei cifre se scoate înaintea buclei, fiindcă repetă intră în corp cel puțin o dată, iar o structură cu test inițial poate să nu intre deloc. Fără asta, pentru x=0 algoritmul n-ar mai fi echivalent: cel dat intră o dată, ia cifra 0 și o sare, pe când cât timp x≠0 n-ar face nimic.

  5. Exercițiul 2 6p Grafuri neorientate

    Un graf neorientat cu 6 noduri, numerotate de la 1 la 6, este reprezentat prin listele de adiacență alăturate.

    Pentru acest graf scrieți un lanț care să nu fie elementar, precum și un ciclu elementar.

    1: 2,6
    4: 2,5
    2: 1,4,6
    5: 3,4,6
    3: 5,6
    6: 1,2,3,5
    Vezi rezolvarea

    Lanț neelementar: 1, 2, 4, 5, 6, 2

    Muchiile există toate: [1,2], [2,4], [4,5], [5,6], [6,2]. Nodul 2 apare de două ori, deci lanțul nu e elementar — exact ce se cere.

    Ciclu elementar: 1, 2, 6, 1

    Muchiile [1,2], [2,6] și [6,1] sunt în liste, primul și ultimul nod coincid, iar între ele niciun nod nu se repetă: e un ciclu elementar de lungime 3.

    Un lanț e *elementar* când nu repetă niciun nod; un ciclu e *elementar* când nu repetă niciun nod în afară de cel de plecare, care e și cel de sosire.

  6. Exercițiul 3 6p Șiruri de caractere

    Variabila i este de tip întreg, iar variabila s permite memorarea unui șir de cel mult 20 de caractere.

    Scrieți șirul accesat prin variabila s în urma executării secvenței alăturate.

    strcpy(s,"ELITIST");
    for(i=2;i<6;i++)
      if(i%2==0) s[i]=s[0];
      else s[i]=s[1]+i/2;
    Vezi rezolvarea

    Răspunsul din barem: ELEMENT

    Se pleacă de la ELITIST și se schimbă doar caracterele de pe pozițiile 2, 3, 4 și 5. Pozițiile pare primesc s[0], adică E; cele impare primesc s[1]+i/2, adică litera aflată la i/2 poziții după L.

    ice se punerezultat
    2s[0] = EELETIST
    3L+1 = MELEMIST
    4s[0] = EELEMEST
    5L+2 = NELEMENT

    Primele două litere și ultima nu sunt atinse de buclă, așa că șirul devine ELEMENT.

Subiectul al III-lea

30 de puncte
  1. Exercițiul 1 10p Subprograme

    Subprogramul putere are un parametru, n, prin care primește un număr natural (n∈[2,10^9]). Subprogramul returnează numărul prim care apare la puterea cea mai mică în descompunerea în factori primi a lui n. Dacă sunt mai multe astfel de numere, se returnează cel mai mic dintre acestea.

    Scrieți definiția completă a subprogramului.

    Exemplu: dacă n=880, subprogramul returnează numărul 5 (880=2^4·5·11).

    Vezi rezolvarea
    int putere(int n)
    {
        int rezultat = 0, minim = 0;
        for (int d = 2; (long long) d * d <= n; d++)
            if (n % d == 0)
            {
                int e = 0;
                while (n % d == 0)
                {
                    n = n / d;
                    e++;
                }
                if (minim == 0 || e < minim)
                {
                    minim = e;
                    rezultat = d;
                }
            }
        if (n > 1 && (minim == 0 || 1 < minim))
            rezultat = n;
        return rezultat;
    }
  2. Exercițiul 2 10p Tablouri bidimensionale

    Scrieți un program C/C++ care citește de la tastatură numere naturale, în această ordine: n (n∈[2,20]), apoi n∙n numere din intervalul [0,10^2], elemente ale unui tablou bidimensional cu n linii și n coloane, iar la final valoarea k (k∈[2,n]); programul transformă tabloul în memorie, prin deplasarea circulară spre dreapta, cu câte o poziție, a tuturor valorilor aflate pe linia a k-a, în stânga diagonalei principale, ca în exemplu. Elementele tabloului obținut sunt afișate pe ecran, linie cu linie, fiecare linie pe câte o linie a ecranului, cu elementele fiecărei linii separate prin câte un spațiu.

    Exemplu: pentru n=6, k=5 și tabloul

    Figura din enunț
    Vezi rezolvarea
    #include <iostream>
    using namespace std;
    
    int main()
    {
        int n, a[21][21], k;
        cin >> n;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                cin >> a[i][j];
        cin >> k;
        int r = k - 1;
        int ultim = a[r][r - 1];
        for (int j = r - 1; j > 0; j--)
            a[r][j] = a[r][j - 1];
        a[r][0] = ultim;
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                cout << a[i][j];
                if (j < n - 1)
                    cout << ' ';
            }
            cout << '\n';
        }
        return 0;
    }
  3. Exercițiul 3.a 2p Algoritmi eficienți

    La proiectarea unui site web se utilizează elemente grafice realizate pe baza unor modele. Fiecare model este de formă pătrată și oricare două modele distincte au dimensiuni diferite ale laturilor. Toate elementele grafice realizate pe baza unui anumit model au aceeași formă și aceleași dimensiuni ca ale acestuia. În vederea asigurării elementelor grafice necesare, pentru fiecare model dintre cele utilizate se plătește o taxă unică de proiectare, de 10 lei, iar pentru fiecare element grafic realizat pe baza acelui model se plătește o sumă în lei, egală cu valoarea suprafeței acestuia (aria pătratului), calculată în centimetri pătrați. Fișierul bac.in conține un șir de cel mult 10^6 numere naturale din intervalul [1,10], separate prin câte un spațiu, reprezentând dimensiunile laturilor tuturor elementelor grafice utilizate, date în centimetri; fiecare termen al șirului corespunde unui element grafic distinct. Se cere să se afișeze pe ecran suma totală plătită pentru asigurarea elementelor grafice necesare. Proiectați un algoritm eficient din punctul de vedere al timpului de executare.

    Exemplu: dacă fișierul conține numerele 1 7 2 1 1 2 1 7 2 se afișează pe ecran valoarea 144 (10 lei pentru modelul de lățime 1 cm și câte 1∙1 lei pentru fiecare dintre cele patru elemente grafice care îl au la bază, 10 lei pentru modelul de lățime 2 cm și câte 2∙2 lei pentru fiecare dintre cele trei elemente grafice care îl au la bază, respectiv 10 lei pentru modelul de lățime 7 cm și câte 7∙7 lei pentru fiecare dintre cele două elemente grafice care îl au la bază).

    Descrieți în limbaj natural algoritmul proiectat, justificând eficiența acestuia.

    Vezi rezolvarea

    Timp de executare: O(n) · Memorie: O(1)

    Laturile sunt numere din [1,10], deci există cel mult zece modele distincte, oricât de multe elemente grafice ar fi.

    Citesc fișierul o singură dată și țin un vector frecv cu zece poziții, în care număr de câte ori apare fiecare latură. Nu păstrez șirul.

    La final parcurg vectorul: pentru fiecare latură care apare măcar o dată adaug 10 lei — taxa de proiectare, plătită o singură dată pe model — plus latură · latură înmulțit cu numărul de elemente de acel fel.

    Pe exemplul din enunț, 1 7 2 1 1 2 1 7 2: latura 1 apare de 4 ori, latura 2 de 3 ori, latura 7 de 2 ori. Total: (10 + 4·1) + (10 + 3·4) + (10 + 2·49) = 14 + 22 + 108 = 144.

    De ce e eficient: fiecare număr e citit și numărat o singură dată, deci timpul e O(n) pentru cele cel mult 10⁶ numere, plus o trecere fixă prin cele zece poziții. Memoria e constantă — zece contoare — indiferent cât de lung e fișierul.

  4. Exercițiul 3.b 8p Algoritmi eficienți

    La proiectarea unui site web se utilizează elemente grafice realizate pe baza unor modele. Fiecare model este de formă pătrată și oricare două modele distincte au dimensiuni diferite ale laturilor. Toate elementele grafice realizate pe baza unui anumit model au aceeași formă și aceleași dimensiuni ca ale acestuia. În vederea asigurării elementelor grafice necesare, pentru fiecare model dintre cele utilizate se plătește o taxă unică de proiectare, de 10 lei, iar pentru fiecare element grafic realizat pe baza acelui model se plătește o sumă în lei, egală cu valoarea suprafeței acestuia (aria pătratului), calculată în centimetri pătrați. Fișierul bac.in conține un șir de cel mult 10^6 numere naturale din intervalul [1,10], separate prin câte un spațiu, reprezentând dimensiunile laturilor tuturor elementelor grafice utilizate, date în centimetri; fiecare termen al șirului corespunde unui element grafic distinct. Se cere să se afișeze pe ecran suma totală plătită pentru asigurarea elementelor grafice necesare. Proiectați un algoritm eficient din punctul de vedere al timpului de executare.

    Exemplu: dacă fișierul conține numerele 1 7 2 1 1 2 1 7 2 se afișează pe ecran valoarea 144 (10 lei pentru modelul de lățime 1 cm și câte 1∙1 lei pentru fiecare dintre cele patru elemente grafice care îl au la bază, 10 lei pentru modelul de lățime 2 cm și câte 2∙2 lei pentru fiecare dintre cele trei elemente grafice care îl au la bază, respectiv 10 lei pentru modelul de lățime 7 cm și câte 7∙7 lei pentru fiecare dintre cele două elemente grafice care îl au la bază).

    Scrieți programul C/C++ corespunzător algoritmului proiectat.

    Vezi rezolvarea
    #include <fstream>
    #include <iostream>
    using namespace std;
    
    int main()
    {
        ifstream f("bac.in");
        long long frecv[11] = {0};
        int x;
        while (f >> x)
            frecv[x]++;
        f.close();
        long long total = 0;
        for (int v = 1; v <= 10; v++)
            if (frecv[v] > 0)
                total = total + 10 + frecv[v] * v * v;
        cout << total;
        return 0;
    }

Vrei să vezi ce notă ai lua la examen?

Intră în modul simulare: ai cronometru de 3 ore, codul ți se compilează pe loc, iar la final primești nota conform baremului.

Începe simularea3 ore

Ai găsit o problemă sau ai o idee?

Despre ce este vorba?