Bac informatică 2026 Varianta 1, rezolvată

Lucrarea „2026 Varianta 1” de la Bacalaureatul la informatică, specializarea Mate-Info, limbajul C/C++: 3 subiecte, 90 de puncte și 3 ore de lucru la examen. Sub fiecare exercițiu ai răspunsul și explicația, închise până le deschizi, ca să încerci întâi singur.

Enunțurile sunt cele oficiale, publicate de Ministerul Educației pe subiecte.edu.ro. Răspunsurile și explicațiile sunt scrise de subac.

Subiectul I20 de puncte

  1. Exercițiul 14p

    Variabila x este de tip întreg și memorează un număr natural nenul.

    Indicați o expresie C/C++ care are valoarea 1 dacă și numai dacă valoarea variabilei x este divizibilă cu 26, dar NU este divizibilă cu 2026.

    • a)!(x%26!=0) || x%2026!=0
    • b)!(x%26!=0) && !(x%2026==0)
    • c)!(x%26==0 || x%2026==0)
    • d)!(x%26!=0 && x%2026!=0)
    Arată răspunsul și explicația

    Răspuns corect: b) !(x%26!=0) && !(x%2026==0)

    x%26!=0 înseamnă „x nu se divide cu 26”, deci !(x%26!=0) înseamnă „x se divide cu 26”. La fel, !(x%2026==0) înseamnă „x nu se divide cu 2026”. Cele două condiții trebuie îndeplinite simultan, deci se leagă cu &&: varianta b).

    a) folosește || și e adevărată și pentru numere care nu se divid cu 26 (de exemplu 1); c) cere ca x să nu se dividă nici cu 26, nici cu 2026; d) e adevărată dacă x se divide cu 26 sau cu 2026, deci și pentru 2026.

  2. Exercițiul 24p

    Subprogramul alăturat, f, este incomplet definit.

    Indicați o expresie cu care pot fi înlocuite punctele de suspensie astfel încât, în urma apelului de mai jos, să se afișeze, în ordine strict crescătoare, primele 10 numere naturale nenule, separate prin câte un spațiu.

    f(10);

    void f(int x)
    { if(......)
      { f(x-1);
        cout<<x<<' '; | printf("%d ",x);
      }
    }
    • a)x<=10
    • b)x<=11
    • c)x>=2
    • d)x>=1
    Arată răspunsul și explicația

    Răspuns corect: d) x>=1

    f(x) îl apelează întâi pe f(x-1) și abia după aceea afișează x, deci numerele ies de la cel mai mic la cel mai mare. Ca f(10) să afișeze 1 2 … 10, autoapelurile trebuie să meargă până la f(1) și să se oprească la f(0): condiția x>=1.

    Cu x>=2 s-ar opri la f(1), iar 1 n-ar mai fi afișat. Cu x<=10 sau x<=11 condiția rămâne adevărată și pentru 0, -1, …, deci autoapelurile nu se mai opresc.

  3. Exercițiul 34p

    Variabila m memorează simultan, pentru o casă de marcat a unui magazin, numărul de tipuri de bancnote prezente la sfârșitul zilei (maximum 20) și, pentru fiecare tip, valoarea unei bancnote (număr natural) și numărul de exemplare existente.

    Indicați expresia C/C++ care are valoarea egală cu suma de bani obținută cu bancnotele de primul tip.

    struct magazin
    {  int nr;
       int valoare[20];
       int exemplare[20];
    }m;
    • a)m[0].valoare*m[0].exemplare
    • b)m.[0][valoare]*m.[0][exemplare]
    • c)m.valoare[0]*m.exemplare[0]
    • d)m.[valoare.0]*m.[exemplare.0]
    Arată răspunsul și explicația

    Răspuns corect: c) m.valoare[0]*m.exemplare[0]

    m este o singură structură, nu un tablou; tablourile sunt câmpurile ei, valoare și exemplare. Primul tip de bancnotă are indicele 0, deci valoarea unei bancnote este m.valoare[0], numărul de exemplare m.exemplare[0], iar suma de bani e produsul lor.

    a) îl tratează pe m ca tablou (m[0]), iar b) și d) nu sunt expresii C/C++ valide.

  4. Exercițiul 44p

    Utilizând metoda backtracking se generează toate posibilitățile de a selecta poezii ale autorilor din mulțimea ordonată astfel: {Arghezi, Blaga, Coșbuc, Eminescu}. Două soluții diferă prin cel puțin un autor. Primele patru soluții generate sunt, în această ordine: {Arghezi}, {Arghezi, Blaga}, {Arghezi, Blaga, Coșbuc}, {Arghezi, Blaga, Coșbuc, Eminescu}.

    Indicați a 5-a soluție generată.

    • a){Arghezi, Blaga, Eminescu}
    • b){Arghezi, Coșbuc, Eminescu, Blaga}
    • c){Blaga, Coșbuc, Eminescu}
    • d){Coșbuc, Eminescu}
    Arată răspunsul și explicația

    Răspuns corect: a) {Arghezi, Blaga, Eminescu}

    După o soluție, backtracking-ul încearcă întâi să adauge următorul autor din mulțime; când nu mai are ce adăuga, renunță la ultimul autor și îl înlocuiește cu unul aflat după el.

    După {Arghezi, Blaga, Coșbuc, Eminescu} nu mai există autor de adăugat, deci se renunță la Eminescu, iar Coșbuc se înlocuiește cu următorul, Eminescu: {Arghezi, Blaga, Eminescu}. b) nu respectă ordinea din mulțime (Blaga după Eminescu), iar c) și d) nu îl mai conțin pe Arghezi, deci vin mult mai târziu.

  5. Exercițiul 54p

    Într-un arbore cu rădăcină, un nod se află pe nivelul x dacă lanțul elementar care are o extremitate în nodul respectiv și cealaltă extremitate în rădăcina arborelui, are lungimea x. Pe nivelul 0 se află un singur nod (rădăcina).

    Se consideră următoarea operație prin care se transformă un arbore cu rădăcină: i se adaugă un nod „frunză”, astfel încât acesta să aibă cel mult un nod „frate”, iar valoarea absolută a diferenței dintre eticheta nodului adăugat și eticheta nodului său ascendent direct („tată”) să fie minimă.

    Asupra unui arbore cu rădăcină, având inițial doar un nod, cu eticheta 4, se efectuează de șase ori, succesiv, operația precizată, etichetele nodurilor adăugate fiind, în această ordine:

    1. 2
    2. 3
    3. 1
    4. 5
    5. 7
    6. 6

    Indicați numărul minim de niveluri ale arborelui obținut.

    • a)2
    • b)3
    • c)4
    • d)5
    Arată răspunsul și explicația

    Răspuns corect: b) 3

    Un nod are cel mult un „frate”, deci fiecare nod are cel mult doi fii. Unde doi „tați” sunt la fel de apropiați, alegerea contează.

    2 se leagă de 4. Pentru 3, atât 4, cât și 2 sunt la diferența 1. Dacă 3 ar merge sub 4, rădăcina s-ar umple, 5 ar ajunge sub 3 și 7 sub 5: patru niveluri. Punându-l pe 3 sub 2: 1 merge tot sub 2 (diferența 1), 5 sub 4 (diferența 1, 4 mai are loc), 7 sub 5 (diferența 2), iar 6 sub 5 (diferența 1).

    Nivelurile sunt 0: 4; 1: 2 și 5; 2: 3, 1, 7 și 6 — trei niveluri. Mai puțin nu se poate: cu cel mult doi fii pe nod, pe două niveluri încap doar 3 noduri, iar arborele are 7.

Subiectul al II-lea40 de puncte

  1. Exercițiul 1.a6p

    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 10.

    citește n
       (număr natural nenul)
     s←0; i←1
    ┌cât timp s<n execută
    │ j←i; nr←0
    │┌cât timp j≠0 execută
    ││ nr←nr+j%2; j←[j/2]
    │└■
    │┌dacă nr=1 atunci
    ││ s←s+i
    │└■
    │ i←i+1
    └■
    scrie s
    Arată răspunsul și explicația

    Răspunsul din barem: 15

    15
    
    Algoritmul adună numerele i care au exact o cifră 1 în scrierea în baza 2, adică puterile lui 2: nr adună resturile împărțirilor repetate ale lui i la 2.
    Pentru n=10, s devine 1, apoi 3 (după i=2), 7 (după i=4) și 15 (după i=8). Cum 15 ≥ 10, bucla se oprește și se afișează 15.
  2. Exercițiul 1.b6p

    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 două valori care pot fi citite astfel încât, în urma executării algoritmului, pentru fiecare dintre acestea, numărul afișat să fie 31.

    citește n
       (număr natural nenul)
     s←0; i←1
    ┌cât timp s<n execută
    │ j←i; nr←0
    │┌cât timp j≠0 execută
    ││ nr←nr+j%2; j←[j/2]
    │└■
    │┌dacă nr=1 atunci
    ││ s←s+i
    │└■
    │ i←i+1
    └■
    scrie s
    Arată răspunsul și explicația
    Exemplu: 16 și 31
    
    Suma crește prin puteri ale lui 2: 1, 3, 7, 15, 31, 63, …, iar bucla se oprește la prima sumă care ajunge cel puțin la n.
    Se afișează 31 exact când 15 < n ≤ 31, adică pentru orice n din intervalul [16,31].
  3. Exercițiul 1.c10p

    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 programul C/C++ corespunzător algoritmului dat.

    citește n
       (număr natural nenul)
     s←0; i←1
    ┌cât timp s<n execută
    │ j←i; nr←0
    │┌cât timp j≠0 execută
    ││ nr←nr+j%2; j←[j/2]
    │└■
    │┌dacă nr=1 atunci
    ││ s←s+i
    │└■
    │ i←i+1
    └■
    scrie s
    Arată răspunsul și explicația
    #include <iostream>
    using namespace std;
    
    int main()
    {
        int n, s = 0, i = 1, j, nr;
        cin >> n;
        while (s < n)
        {
            j = i; nr = 0;
            while (j != 0)
            {
                nr = nr + j % 2;
                j = j / 2;
            }
            if (nr == 1) s = s + i;
            i = i + 1;
        }
        cout << s;
        return 0;
    }
    
    Primul cât timp devine while (s < n), al doilea while (j != 0). Operația [j/2] este chiar împărțirea a două numere întregi în C/C++, iar j%2 este restul.
  4. Exercițiul 1.d6p

    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 în pseudocod un algoritm, echivalent cu cel dat, înlocuind a doua structură cât timp...execută cu o structură repetitivă cu test final.

    citește n
       (număr natural nenul)
     s←0; i←1
    ┌cât timp s<n execută
    │ j←i; nr←0
    │┌cât timp j≠0 execută
    ││ nr←nr+j%2; j←[j/2]
    │└■
    │┌dacă nr=1 atunci
    ││ s←s+i
    │└■
    │ i←i+1
    └■
    scrie s
    Arată răspunsul și explicația
    citește n (număr natural nenul)
    s←0; i←1
    ┌cât timp s<n execută
    │ j←i; nr←0
    │┌repetă
    ││ nr←nr+j%2; j←[j/2]
    │└până când j=0
    │┌dacă nr=1 atunci
    ││ s←s+i
    │└■
    │ i←i+1
    └■
    scrie s
    
    repetă…până când execută corpul cel puțin o dată, pe când cât timp poate să nu îl execute deloc. Aici nu e nevoie de o condiție în plus: i pornește de la 1 și doar crește, deci j←i este mereu nenul la intrare, iar corpul s-ar fi executat oricum măcar o dată. Condiția de oprire este negata celei de continuare: se continua cât timp j≠0, deci se oprește când j=0.
  5. Exercițiul 26p

    Un graf neorientat are 8 noduri și 10 muchii.

    Scrieți numărul de valori nenule și numărul de valori nule din matricea de adiacență corespunzătoare grafului.

    Arată răspunsul și explicația

    Răspunsul din barem: 20 44

    20 44
    
    Matricea de adiacență a unui graf cu 8 noduri are 8·8 = 64 de elemente. Fiecare muchie [x,y] pune 1 în două locuri, pe linia x, coloana y și pe linia y, coloana x, deci cele 10 muchii dau 20 de valori nenule. Restul, 64 − 20 = 44, sunt nule.
  6. Exercițiul 36p

    Variabilele i și j sunt de tip întreg, iar variabila a memorează un tablou bidimensional cu 5 linii și 5 coloane, numerotate de la 1 la 5, cu elemente numere întregi.

    Fără a utiliza alte variabile, scrieți secvența C/C++ de mai jos, înlocuind punctele de suspensie cu instrucțiuni adecvate, dintre care cel mult trei atribuiri, astfel încât, în urma executării secvenței obținute, tabloul memorat în variabila a să aibă elementele alăturate.

    for(i=1;i<=5;i++)
      for(j=1;j<=5;j++)
       ..................
    23232
    30303
    23232
    30303
    23232
    Arată răspunsul și explicația
    for(i=1;i<=5;i++)
      for(j=1;j<=5;j++)
       if(i%2==1 && j%2==1) a[i][j]=2;
       else if(i%2==0 && j%2==0) a[i][j]=0;
            else a[i][j]=3;
    
    Pe pozițiile cu linia și coloana impare este 2, pe cele cu linia și coloana pare este 0, iar unde una este pară și cealaltă impară este 3. Sunt trei atribuiri, exact cât permite enunțul.

Subiectul al III-lea30 de puncte

  1. Exercițiul 110p

    Un număr este reprezentat în baza b dacă cifrele sale aparțin intervalului [0,b-1].

    Subprogramul baza are doi parametri, n și b, prin care primește câte un număr natural (n∈[0,109], b∈[2,10]). Subprogramul returnează valoarea 1, dacă n este reprezentat în baza b, sau -1, în caz contrar.

    Scrieți definiția completă a subprogramului C/C++.

    Exemplu: dacă n=32412 și b=8, subprogramul returnează valoarea 1, iar dacă n=32412 și b=3, subprogramul returnează valoarea -1.

    Arată răspunsul și explicația
    int baza(int n, int b)
    {
        do
        {
            if (n % 10 >= b) return -1;
            n = n / 10;
        } while (n != 0);
        return 1;
    }
    
    Cifrele se iau pe rând de la dreapta, cu n%10. Dacă una este cel puțin b, nu poate fi cifră în baza b și se returnează imediat -1; dacă toate trec, se returnează 1.
    Structura do…while tratează și n=0: are o singură cifră, 0, deci este reprezentat în orice bază.
  2. Exercițiul 210p

    Un text, de cel mult 200 de caractere, reprezintă o succesiune de date despre flori de tipuri distincte. Pentru fiecare floare, textul conține câte o pereche formată, în această ordine, din denumire (un șir de cel mult 20 de caractere, litere mici ale alfabetului limbii engleze) și o valoare naturală din intervalul [1,9], reprezentând necesarul zilnic de lumină, dat în număr de ore; fiecare valoare din pereche este urmată de câte un spațiu, ca în exemplu.

    Scrieți un program C/C++ care citește de la tastatură un text de tipul precizat și afișează pe ecran denumirea florii cu cel mai mic necesar zilnic de lumină, iar dacă sunt mai multe astfel de flori, se alege prima, în ordine alfabetică.

    Exemplu: dacă se citește textul lavanda 7 impatiens 3 iris 5 dalie 6 begonie 3 petunie 7 se afișează pe ecran begonie

    Arată răspunsul și explicația
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    int main()
    {
        char s[201], *p, floare[21], minim[21];
        int ore, oreMin = 10;
        cin.getline(s, 201);
        p = strtok(s, " ");
        while (p != NULL)
        {
            strcpy(floare, p);
            p = strtok(NULL, " ");
            ore = p[0] - '0';
            if (ore < oreMin || (ore == oreMin && strcmp(floare, minim) < 0))
            {
                oreMin = ore;
                strcpy(minim, floare);
            }
            p = strtok(NULL, " ");
        }
        cout << minim;
        return 0;
    }
    
    Textul se citește întreg, apoi se împarte în cuvinte cu strtok: cuvintele vin în perechi, întâi denumirea, apoi numărul de ore, care e o singură cifră (de la 1 la 9), deci valoarea lui este p[0]-'0'.
    Se reține cea mai mică valoare întâlnită și denumirea ei. O floare nouă o înlocuiește pe cea reținută dacă are mai puține ore sau, la același număr de ore, dacă e înaintea ei în ordine alfabetică (strcmp dă un rezultat negativ). Pornind de la oreMin=10, prima floare este reținută sigur.
  3. Exercițiul 3.a2p

    În cadrul testării unor echipamente de comunicații se transmite un șir de biți (0 sau 1), care conține cel puțin un bit 1, iar atât primul cât și ultimul bit sunt 0. Șirul conține cel puțin un mesaj de avertisment de forma unei succesiuni de biți, aflați pe poziții consecutive în șir, dintre care doar unul este 0. Lungimea mesajului este egală cu numărul biților care îl compun.

    Fișierul bac.txt conține cel mult 106 numere naturale din mulțimea {0,1}, reprezentând șirul de biți transmis. Numerele sunt separate prin câte un spațiu. Se cere să se afișeze pe ecran biții care compun cel mai lung mesaj de avertisment din șirul aflat în fișier. Dacă există mai multe astfel de mesaje, se afișează doar biții unuia dintre acestea. Biții afișați sunt separați prin câte un spațiu. Proiectați un algoritm eficient din punctul de vedere al timpului de executare și al spațiului de memorie utilizat.

    Exemplu: dacă fișierul conține numerele 0 1 1 1 1 1 1 1 0 0 1 1 1 0 1 1 1 1 0 1 1 0 se afișează pe ecran 0 1 1 1 1 1 1 1 sau 1 1 1 1 1 1 1 0 sau 1 1 1 0 1 1 1 1

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

    Arată răspunsul și explicația
    Biții se citesc unul câte unul din fișier, fără să fie memorați, numărând poziția curentă.
    
    Cel mai lung mesaj care conține un anumit 0 se întinde de la zeroul dinaintea lui până la zeroul de după el, fără aceste două capete. Dacă p1, p2, p3 sunt pozițiile a trei zerouri consecutive din șir, mesajul cu zeroul de la p2 cuprinde biții de pe pozițiile p1+1, …, p3-1, deci are lungimea p3-p1-1.
    
    Se păstrează pozițiile ultimelor trei zerouri (pornite de la 0) și pozițiile corespunzătoare celui mai lung mesaj găsit până atunci. La fiecare 0 citit, pozițiile se mută (p1←p2, p2←p3, p3←poziția curentă), iar dacă p3-p1 depășește lungimea celui mai lung mesaj, se rețin ca noul maxim. La final se afișează p2m-p1m-1 biți 1, un 0, apoi p3m-p2m-1 biți 1.
    
    Eficiență: fiecare bit se prelucrează o singură dată, în timp constant, deci algoritmul este liniar în numărul de biți din fișier. Se folosesc doar câteva variabile simple, fără niciun tablou, deci memoria folosită este constantă.
  4. Exercițiul 3.b8p

    În cadrul testării unor echipamente de comunicații se transmite un șir de biți (0 sau 1), care conține cel puțin un bit 1, iar atât primul cât și ultimul bit sunt 0. Șirul conține cel puțin un mesaj de avertisment de forma unei succesiuni de biți, aflați pe poziții consecutive în șir, dintre care doar unul este 0. Lungimea mesajului este egală cu numărul biților care îl compun.

    Fișierul bac.txt conține cel mult 106 numere naturale din mulțimea {0,1}, reprezentând șirul de biți transmis. Numerele sunt separate prin câte un spațiu. Se cere să se afișeze pe ecran biții care compun cel mai lung mesaj de avertisment din șirul aflat în fișier. Dacă există mai multe astfel de mesaje, se afișează doar biții unuia dintre acestea. Biții afișați sunt separați prin câte un spațiu. Proiectați un algoritm eficient din punctul de vedere al timpului de executare și al spațiului de memorie utilizat.

    Exemplu: dacă fișierul conține numerele 0 1 1 1 1 1 1 1 0 0 1 1 1 0 1 1 1 1 0 1 1 0 se afișează pe ecran 0 1 1 1 1 1 1 1 sau 1 1 1 1 1 1 1 0 sau 1 1 1 0 1 1 1 1

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

    Arată răspunsul și explicația
    #include <fstream>
    #include <iostream>
    using namespace std;
    
    int main()
    {
        ifstream fin("bac.txt");
        int x, i, pcrt = 0, p1 = 0, p2 = 0, p3 = 0, p1m = 0, p2m = 0, p3m = 0;
        while (fin >> x)
        {
            pcrt++;
            if (x == 0)
            {
                p1 = p2; p2 = p3; p3 = pcrt;
                if (p3 - p1 > p3m - p1m)
                {
                    p1m = p1; p2m = p2; p3m = p3;
                }
            }
        }
        fin.close();
        for (i = p1m + 1; i < p3m; i++)
            if (i == p2m) cout << 0 << ' ';
            else cout << 1 << ' ';
        return 0;
    }
    
    Programul face pașii de la 3.a. Mesajul se afișează din pozițiile reținute: pe poziția p2m este 0, iar pe toate celelalte poziții dintre p1m și p3m sunt biți 1.
    Când există mai multe mesaje de lungime maximă, programul îl păstrează pe primul (comparația e strictă), iar enunțul acceptă oricare dintre ele.

Vrei să vezi cât ai lua?

În test ai cronometrul de la examen, codul tău se compilează pe loc, iar la final primești nota.

Rezolv-o cu timpul de la examen