Sari la conținut

Bac informatică 2022 Varianta 5, rezolvată

Varianta 5 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 Varianta 5 din 2022

Varianta 5 din 2022 trece prin expresii logice, recursivitate, backtracking, matrice, grafuri și arbori, cel mai mare divizor comun, structuri, șiruri de caractere și fișiere. Este o variantă echilibrată, bună ca test complet.

Subiectul I (20p): 5 grile: o expresie logică echivalentă cu x>=3 && x<10, completarea unui subprogram recursiv care verifică dacă un număr este prim, o problemă de backtracking cu platouri de câte trei fructe, coloana unui element de pe diagonala secundară și cele două muchii care lipsesc dintr-un graf cu un lanț elementar de lungime maximă dat.

Subiectul al II-lea (40p): Un algoritm în pseudocod care coboară de la n până la primul număr care are un divizor comun cu m, rădăcinile pentru care un nod are doi „frați” într-un arbore și o secvență care afișează CALDUROS, RACOROS sau NORMAL după un câmp al unei structuri meteo.

Subiectul al III-lea (30p): Un subprogram cu cifre (schimb, care înlocuiește cifra de pe poziția p), o problemă cu șiruri de caractere care codifică o parolă înlocuind fiecare consoană cu „vocala prietenă” și o problemă de eficiență cu „secvențe paritare” dintr-un șir citit din fișierul bac.txt.

⚠️ La ce să fii atent

  • La I.1: Varianta a) pare bună, dar x<3 && x>=10 nu poate fi niciodată adevărată, deci !(x<3 && x>=10) are mereu valoarea 1.
  • La I.5: Nu e de ajuns ca lanțul dat să existe. Cu [3,6] și [5,7] ar apărea lanțul 1, 2, 7, 5, 4, 3, 6, care trece prin toate cele 7 noduri, deci lanțul din enunț n-ar mai fi de lungime maximă.
  • La II.1.a: Bucla interioară calculează prin scăderi cel mai mare divizor comun dintre m și n, iar cea exterioară continuă cât timp acesta este 1. Pentru 21 și 47 se afișează 45, primul număr care are un divizor comun cu 21.
  • La III.2: Vocalele rămân neschimbate. Consoanele b, c și d primesc a, iar consoanele de după u primesc u. Așa, sport devine ooooo.
  • La III.3: Nu uita de ultima secvență: după ea nu mai vine niciun termen care să o încheie. În exemplu, ultimii cinci termeni, 2 6 4 0 16, formează una dintre cele patru secvențe de lungime maximă 5.

Subiectul I

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

    Variabila x este de tip întreg.

    Indicați o expresie care are valoarea 1 dacă și numai dacă expresia C/C++ alăturată are valoarea 1.

    x>=3 && x<10
    • a)!(x<3 && x>=10)
    • b)!(x<3 || x>=10)
    • c)x<3 && !(x>=10)
    • d)!(x<3) || x>=10
    Vezi rezolvarea

    Răspuns corect: b) !(x<3 || x>=10)

    x>=3 && x<10 este adevărată exact când nu e adevărată niciuna dintre x<3 și x>=10, adică !(x<3 || x>=10). În a) negarea unei expresii mereu false dă mereu 1; în c) rămâne x<3, adică exact numerele excluse; în d) rămâne x>=3, care e 1 și pentru x=10.

  2. Exercițiul 2 4p Recursivitate

    Subprogramul f este definit incomplet, alăturat.

    Indicați o expresie cu care pot fi înlocuite punctele de suspensie pentru ca f(n,3) să aibă valoarea 1 pentru orice număr prim n (n∈[2,10^4]) și valoarea 0 în caz contrar.

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

    Răspuns corect: a) y+2

    Subprogramul verifică dacă x e prim: elimină întâi numerele pare, apoi caută un divizor y, pornind de la 3. Cum numerele pare sunt deja tratate, are rost să încerce doar divizorii impari, deci pasul este y+2. Cu y-2 apelul ar merge înapoi la infinit, cu y*2 s-ar sări peste divizori impari, iar y/2 ar ajunge la 1, care împarte orice număr.

  3. Exercițiul 3 4p Backtracking

    Utilizând metoda backtracking, se generează toate posibilitățile de a forma platouri de câte trei fructe distincte din mulțimea {măr, gutuie, prună, caisă, piersică}, astfel încât pe același platou nu se află o gutuie și o piersică simultan. Două platouri sunt distincte dacă ele conțin cel puțin un fruct diferit. Primele patru soluții generate sunt, în această ordine:

    1. (măr, gutuie, prună)
    2. (măr, gutuie, caisă)
    3. (măr, prună, caisă)
    4. (măr, prună, piersică)

    Indicați soluția generată imediat după (gutuie, prună, caisă).

    • a)(caisă, piersică, măr)
    • b)(gutuie, prună, piersică)
    • c)(măr, caisă, piersică)
    • d)(prună, caisă, piersică)
    Vezi rezolvarea

    Răspuns corect: d) (prună, caisă, piersică)

    Platourile se generează în ordinea fructelor din mulțime, iar gutuia și piersica nu pot fi împreună. După (gutuie, prună, caisă) ar urma (gutuie, prună, piersică) și (gutuie, caisă, piersică), dar amândouă au și gutuie, și piersică, deci se sar; rămâne (prună, caisă, piersică).

  4. Exercițiul 4 4p Tablouri bidimensionale

    Variabila j este de tip întreg, iar variabila A memorează un tablou bidimensional cu 100 de linii și 100 de coloane, numerotate de la 0 la 99.

    Indicați valoarea variabilei j, dacă elementul A[20][j] se află pe diagonala secundară a tabloului.

    • a)20
    • b)49
    • c)79
    • d)80
    Vezi rezolvarea

    Răspuns corect: c) 79

    Pe diagonala secundară a unui tablou cu 100 de linii și 100 de coloane, numerotate de la 0 la 99, suma indicilor unui element este 99. Din 20+j=99 rezultă j=79.

  5. Exercițiul 5 4p Grafuri neorientate

    Un graf neorientat are 7 noduri, numerotate de la 1 la 7, și 8 muchii, dintre care șase sunt:

    1. [1,2]
    2. [2,4]
    3. [2,7]
    4. [3,4]
    5. [4,5]
    6. [4,6]

    Știind că unul dintre lanțurile elementare care au lungimea maximă este 1, 2, 7, 5, 4, 6, indicați care ar putea fi celelalte două muchii ale grafului.

    • a)[1,4] și [4,7]
    • b)[1,4] și [5,7]
    • c)[2,5] și [4,7]
    • d)[3,6] și [5,7]
    Vezi rezolvarea

    Răspuns corect: b) [1,4] și [5,7]

    Lanțul dat folosește muchiile [1,2], [2,7], [7,5], [5,4] și [4,6]; dintre ele, [5,7] nu e în lista celor șase, deci e una dintre muchiile care lipsesc. Cealaltă trebuie să nu creeze un lanț mai lung: cu [1,4], nodurile 3 și 6 rămân legate doar de 4, deci niciun lanț nu le poate cuprinde pe amândouă împreună cu restul, iar lanțul dat, cu șase noduri, rămâne maxim. Cu [3,6] în schimb ar exista lanțul 1, 2, 7, 5, 4, 3, 6, cu toate cele șapte noduri, mai lung decât cel din enunț.

Subiectul al II-lea

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

    Algoritmul alăturat este reprezentat în pseudocod.

    Scrieți ce se afișează în urma executării algoritmului dacă se citesc, în această ordine, valorile 21 și 47.

     citește m,n
      (numere naturale nenule, m<n)
     x←1
    ┌cât timp x=1 execută
    │ x←m; y←n; n←n-1
    │┌cât timp x≠y execută
    ││┌dacă x>y atunci x←x-y
    │││altfel y←y-x
    ││└■
    │└■
    └■
     scrie n+1
    Vezi rezolvarea

    Răspunsul din barem: 45

    Bucla interioară calculează, prin scăderi repetate, cel mai mare divizor comun dintre m și valoarea curentă a lui n, iar bucla exterioară merge mai departe cât timp acesta este 1. Pentru m=21 se încearcă pe rând 47 și 46, care nu au divizori comuni cu 21, apoi 45: cum 21 și 45 se împart amândouă la 3, bucla se oprește. Se afișează n+1, adică ultima valoare încercată, 45.

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

    Același algoritm ca la 1.a.

    Dacă pentru variabila m se citește numărul 5, scrieți două valori care pot fi citite pentru variabila n astfel încât, în urma executării algoritmului, pentru fiecare dintre acestea, valoarea afișată să fie 10.

    Vezi rezolvarea

    10 și 12

    Se afișează ultima valoare încercată, adică primul număr, coborând de la n, care are un divizor comun cu 5 — altfel spus, primul multiplu de 5. Ca acesta să fie 10, valoarea citită trebuie să fie cel puțin 10 (ca 10 să fie încercat) și cel mult 14 (ca 15 să nu fie întâlnit înaintea lui). Merge deci orice număr din intervalul [10,14].

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

    Același algoritm ca la 1.a.

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

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

    Același algoritm ca la 1.a.

    Scrieți în pseudocod un algoritm echivalent cu cel dat, înlocuind adecvat prima structură cât timp...execută cu o structură repetitivă cu test final.

    Vezi rezolvarea
    citește m,n (numere naturale nenule, m<n)
    ┌repetă
    │ x←m; y←n; n←n-1
    │┌cât timp x≠y execută
    ││┌dacă x>y atunci x←x-y
    │││altfel y←y-x
    ││└■
    │└■
    └până când x≠1
     scrie n+1

    cât timp x=1 verifică la început și merge înainte cât timp condiția e adevărată, iar repetă…până când verifică la sfârșit și se oprește când condiția devine adevărată: condiția se neagă, deci x≠1. Aici înlocuirea nu schimbă nimic, pentru că x←1 de dinainte făcea oricum ca prima verificare să treacă — de altfel, după înlocuire, acea inițializare nu mai e necesară.

  5. Exercițiul 2 6p Arbori

    Un arbore cu 9 noduri, numerotate de la 1 la 9, are muchiile:

    1. [1,8]
    2. [2,3]
    3. [2,5]
    4. [2,7]
    5. [4,5]
    6. [5,6]
    7. [5,8]
    8. [8,9]

    Scrieți două noduri care pot fi alese drept rădăcină, astfel încât nodul 5 să aibă doi “frați”.

    Vezi rezolvarea

    Răspunsul din barem: 2, 8

    Ca nodul 5 să aibă doi frați, părintele lui trebuie să aibă trei fii. Vecinii lui 5 sunt 2, 4, 6 și 8. Dacă rădăcina este chiar 2, fiii lui 2 sunt 3, 5 și 7, deci 5 are doi frați; la fel, dacă rădăcina este 8, fiii lui sunt 1, 5 și 9. Pentru orice altă rădăcină, părintele lui 5 pierde un fiu în favoarea propriului părinte, deci 5 ar rămâne cu un singur frate.

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

    Variabila x, declarată alăturat, memorează simultan un an calendaristic și temperatura medie a aerului, măsurată în grade Celsius, înregistrată în București în anul respectiv.

    Scrieți o secvență de instrucțiuni în urma executării căreia să se afișeze pe ecran mesajul CALDUROS dacă temperatura menționată a fost strict mai mare decât 11°C, mesajul RACOROS dacă temperatura menționată a fost strict mai mică decât 10°C, sau mesajul NORMAL în orice alt caz.

    struct meteo
    {  int an, temperatura;
    }x;
    Vezi rezolvarea
    if (x.temperatura > 11) cout << "CALDUROS";
    else if (x.temperatura < 10) cout << "RACOROS";
         else cout << "NORMAL";

    Se citește câmpul temperatura al înregistrării și se compară, în ordine, cu cele două praguri. Cazurile se leagă cu else, ca fiecare temperatură să intre într-unul singur: peste 11 grade e cald, sub 10 e răcoros, iar ce rămâne — exact valorile 10 și 11 — e normal.

Subiectul al III-lea

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

    Subprogramul schimb are trei parametri:

    • n și x, prin care primește câte un număr natural (n∈[0,10^8], x∈[1,9]);

    • p, prin care primește un număr natural reprezentând poziția unei cifre a numărului n (0≤p). Pozițiile cifrelor sunt numerotate de la dreapta la stânga, astfel: cifra unităților este pe poziția 0, cifra zecilor este pe poziția 1 ș.a.m.d.

    Subprogramul transformă numărul n, înlocuind cifra de pe poziția p cu cifra x, și furnizează numărul obținut tot prin parametrul n.

    Scrieți definiția completă a subprogramului.

    Exemplu: dacă n=12587, x=6 și p=3, după apel, n=16587.

    Vezi rezolvarea
    void schimb(int &n, int x, int p)
    {
        int put = 1;
        for (int i = 0; i < p; i++) put = put * 10;
        int cifra = (n / put) % 10;   // cifra care se schimbă
        n = n + (x - cifra) * put;
    }

    Poziția p înseamnă puterea lui 10 corespunzătoare: put ajunge 10^p. Cifra aflată acolo este (n/put)%10. În loc să fie reconstruit tot numărul, se adaugă diferența dintre cifra nouă și cea veche, înmulțită cu put: restul cifrelor rămân neatinse. Parametrul n e transmis prin referință, fiindcă rezultatul se întoarce tot prin el.

  2. Exercițiul 2 10p Șiruri de caractere

    Se consideră o vocală oarecare a alfabetului englez, notată cu v, și o consoană oarecare a alfabetului englez, notată cu c. Litera v se numește vocală prietenă a lui c dacă în șirul literelor alfabetului englez, ordonat lexicografic, v îl precede pe c, iar între v și c nu există nicio vocală. Se consideră vocale literele:

    1. a
    2. e
    3. i
    4. o
    5. u

    Exemplu: e este vocală prietenă pentru consoanele f, g și h, dar nu este vocală prietenă pentru consoanele d și j.

    Un elev vrea să transmită unui prieten o parolă, codificată. Parola este formată dintr-un singur cuvânt de cel mult 50 de caractere, litere mici ale alfabetului englez, cel puțin una fiind consoană. Codificarea se face prin înlocuirea fiecărei consoane cu vocala sa prietenă, ca în exemplu.

    Scrieți un program C/C++ care citește de la tastatură un cuvânt, reprezentând o parolă de tipul precizat și determină, în memorie, forma codificată a acesteia. Programul afișează pe ecran parola codificată obținută.

    Exemplu: pentru parola rame se afișează oaie, iar pentru parola sport se afișează ooooo

    Vezi rezolvarea
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    int main()
    {
        char s[51];
        cin >> s;
        char vocale[] = "aeiou";
        for (int i = 0; i < strlen(s); i++)
        {
            char prietena = s[i];
            if (strchr(vocale, s[i]) == NULL)
            {
                // Cea mai apropiată vocală dinaintea consoanei.
                prietena = 'a';
                for (int j = 0; j < 5; j++)
                    if (vocale[j] < s[i]) prietena = vocale[j];
            }
            s[i] = prietena;
        }
        cout << s;
        return 0;
    }

    O vocală rămâne neschimbată. Pentru o consoană se caută vocala prietenă: dintre cele cinci vocale, cea mai mare care este încă înaintea ei în alfabet — parcurgându-le în ordine, ultima care îndeplinește condiția. Consoanele dinaintea lui e (b, c, d) primesc a, iar cele de după u primesc u. Cuvântul se modifică pe loc și se afișează la final.

  3. Exercițiul 3.a 2p Algoritmi eficienți

    Numim secvență paritară a unui șir de numere naturale un subșir al acestuia, format din termeni cu aceeași paritate, aflați pe poziții consecutive în șirul dat. Lungimea secvenței este egală cu numărul de termeni ai acesteia.

    Fișierul bac.txt conține un șir de cel puțin două și cel mult 10^6 numere naturale din intervalul [0,10^9]. Numerele sunt separate prin câte un spațiu, iar în șir există cel puțin doi termeni cu aceeași paritate pe poziții consecutive.

    Se cere să se afișeze pe ecran numărul secvențelor paritare de lungime maximă din șirul aflat în fișier, precum și această lungime maximă. Numerele afișate sunt separate printr-un spațiu. Proiectați un algoritm eficient din punctul de vedere al timpului de executare și al memoriei utilizate.

    Exemplu: dacă fișierul conține numerele atunci pe ecran se afișează valorile 4 5

    2 3 5 1 7 9 8 4 4 11 15 17 21 11 6 11 15 17 21 11 6 5 2 6 4 0 16

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

    Vezi rezolvarea

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

    Șirul se citește din fișier o singură dată, fără a fi memorat. Se ține minte doar termenul anterior și lungimea secvenței paritare care se termină în termenul curent: dacă termenul citit are aceeași paritate cu cel dinainte, lungimea crește cu 1, altfel secvența s-a încheiat și începe una nouă, de lungime 1.

    La fiecare încheiere de secvență, lungimea ei se compară cu maximul de până atunci: dacă e mai mare, maximul se actualizează și numărătorul se readuce la 1; dacă e egală, numărătorul crește. După ultimul termen se închide și ultima secvență, care altfel nu ar fi luată în seamă.

    Se face o singură parcurgere, cu un număr de operații proporțional cu numărul de termeni, și se rețin doar câteva variabile — paritatea anterioară, lungimea curentă, maximul și numărătorul — deci memoria folosită nu crește cu lungimea șirului.

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

    Același algoritm ca la 3.a.

    Fișierul bac.txt conține un șir de cel puțin două și cel mult 10^6 numere naturale din intervalul [0,10^9]. Numerele sunt separate prin câte un spațiu, iar în șir există cel puțin doi termeni cu aceeași paritate pe poziții consecutive.

    Se cere să se afișeze pe ecran numărul secvențelor paritare de lungime maximă din șirul aflat în fișier, precum și această lungime maximă. Numerele afișate sunt separate printr-un spațiu. Proiectați un algoritm eficient din punctul de vedere al timpului de executare și al memoriei utilizate.

    Exemplu: dacă fișierul conține numerele atunci pe ecran se afișează valorile 4 5

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

    Vezi rezolvarea
    #include <fstream>
    #include <iostream>
    using namespace std;
    
    int main()
    {
        ifstream f("bac.txt");
        int v, ant, lung = 1, maxim = 0, cate = 0;
        f >> ant;
        while (f >> v)
        {
            if (v % 2 == ant % 2) lung = lung + 1;
            else
            {
                if (lung > maxim) { maxim = lung; cate = 1; }
                else if (lung == maxim) cate = cate + 1;
                lung = 1;
            }
            ant = v;
        }
        // Ultima secvență nu are după ea un termen de altă paritate care să o închidă.
        if (lung > maxim) { maxim = lung; cate = 1; }
        else if (lung == maxim) cate = cate + 1;
        f.close();
        cout << cate << ' ' << maxim;
        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?