Sari la conținut

Bac informatică 2023 Varianta 7, rezolvată

Varianta 7 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 7 din 2023

Varianta 7 din 2023 trece prin expresii cu % și /, recursivitate, șiruri de caractere, backtracking, grafuri și arbori, structuri, divizori, matrice și fișiere. Este o variantă echilibrată, bună pentru recapitularea întregii materii.

Subiectul I (20p): 5 grile: valorile pentru care o expresie cu % și / este nenulă, un subprogram recursiv care calculează o putere prin înjumătățirea exponentului, o secvență cu strcpy scris în mijlocul unui șir, o problemă de backtracking cu parfumuri din câte trei esențe și gradele posibile ale nodurilor unui graf neorientat cu 5 noduri.

Subiectul al II-lea (40p): Un algoritm în pseudocod care păstrează prima cifră a lui a, pe poziția ei, și îi adaugă b, rădăcinile pentru care un arbore are număr minim de niveluri și o secvență care atribuie unei variabile char prima literă a denumirii unui produs, după prețul din structura produs.

Subiectul al III-lea (30p): Un subprogram cu divizori (DNPI, care afișează divizorii impari care nu sunt primi), o problemă cu matrice care caută pătratul 2×2 cu suma maximă și o problemă de eficiență care numără perechile de valori egale din două șiruri citite din fișierul date.in.

⚠️ La ce să fii atent

  • La I.1: Varianta c) are y=0, deci x/y ar fi o împărțire la zero. Doar pentru x=25 și y=15 se obține 15 - 1·3 = 12, diferit de 0.
  • La I.3: strcpy(s+3,"23") scrie de la poziția 3, adică peste cifra 9, și pune terminatorul după 23. Primele trei caractere rămân, deci șirul devine 20123.
  • La I.5: Suma gradelor trebuie să fie pară, iar într-un graf cu 5 noduri un grad este cel mult 4. În plus, un nod de grad 4 e legat de toate celelalte, deci niciun nod nu poate avea gradul 0. Rămâne varianta d).
  • La III.1: 1 nu este număr prim, deci trebuie afișat și el. Pentru n=90, divizorii impari care nu sunt primi sunt 1, 9, 15 și 45.
  • La III.3: Fiecare poziție apare în cel mult o pereche, deci pentru o valoare care apare de a ori în A și de b ori în B poți forma doar cel mai mic dintre a și b perechi. Răspunsul este suma acestor minime, calculată cu doi vectori de frecvență.

Subiectul I

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

    Indicați numerele pe care le pot memora variabilele întregi x și y, astfel încât valoarea expresiei C/C++ alăturate să fie 1.

    y%x-(x/y)*3!=0
    • a)x=25 și y=75
    • b)x=25 și y=15
    • c)x=15 și y=0
    • d)x=10 și y=30
    Vezi rezolvarea

    Răspuns corect: b) x=25 și y=15

    Pentru x=25 și y=15: y%x este 15, x/y este 1, iar 15 − 1·3 = 12, diferit de 0, deci expresia are valoarea 1.

    În a) și d), y%x și x/y sunt amândouă 0, deci diferența este 0, iar c) împarte la y=0, ceea ce nu e permis.

  2. Exercițiul 2 4p Recursivitate

    Subprogramul f este definit alăturat.

    Indicați valoarea f(3,2).

    int f(int x, int y)
    {  int z;
       if (y==0) return 1;
       z=f(x,y/2);
       if (y%2!=0) return z*z*x;
       return z*z;
    }
    • a)1
    • b)2
    • c)9
    • d)18
    Vezi rezolvarea

    Răspuns corect: c) 9

    Funcția calculează x la puterea y prin înjumătățirea exponentului. f(3,1) folosește f(3,0) = 1 și, cum 1 este impar, returnează 1·1·3 = 3. f(3,2) folosește f(3,1) = 3 și, cum 2 este par, returnează 3·3 = 9.

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

    Variabila s poate accesa un șir cu cel mult 20 de caractere.

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

    strcpy(s,"2019");
    strcpy(s+3,"23");
    • a)20123
    • b)201923
    • c)202223
    • d)2023
    Vezi rezolvarea

    Răspuns corect: a) 20123

    După strcpy(s,"2019"), s+3 indică poziția cifrei 9. strcpy(s+3,"23") scrie de acolo „23” și terminatorul de șir, deci primele trei caractere, „201”, rămân neschimbate, iar șirul devine 20123.

  4. Exercițiul 4 4p Backtracking

    Utilizând metoda backtracking, se generează toate parfumurile formate prin amestecarea a câte 3 esențe distincte din mulțimea {bergamotă, cireș, iris, lămâie, salcâm}. Două parfumuri sunt distincte dacă diferă prin cel puțin o esență. Primele patru soluții obținute sunt, în această ordine: (bergamotă, cireș, iris), (bergamotă, cireș, lămâie), (bergamotă, cireș, salcâm) și (bergamotă, iris, lămâie).

    Indicați penultima soluție generată.

    • a)(cireș, iris, salcâm)
    • b)(cireș, lămâie, salcâm)
    • c)(lămâie, iris, salcâm)
    • d)(iris, lămâie, salcâm)
    Vezi rezolvarea

    Răspuns corect: b) (cireș, lămâie, salcâm)

    Parfumurile sunt submulțimi de trei esențe, generate în ordinea din mulțime, deci ultimele încep cu esențele cele mai târzii. Ultima soluție este (iris, lămâie, salcâm), iar chiar înaintea ei vine ultima soluție care începe cu cireș: (cireș, lămâie, salcâm).

    c) nu respectă ordinea din mulțime (lămâie înaintea lui iris), deci nu este generată deloc.

  5. Exercițiul 5 4p Grafuri neorientate

    Un graf neorientat are 5 noduri, numerotate de la 1 la 5, cu gradele figurate în tabelul alăturat.

    Indicați o pereche de valori posibile pentru x și y.

    Nod   1  2  3  4  5
    Grad  2  x  3  3  y
    • a)0 și 4
    • b)1 și 5
    • c)2 și 3
    • d)3 și 3
    Vezi rezolvarea

    Răspuns corect: d) 3 și 3

    Suma gradelor este dublul numărului de muchii, deci pară, iar într-un graf cu 5 noduri un grad este cel mult 4.

    b) are gradul 5; c) dă suma 2 + 2 + 3 + 3 + 3 = 13, impară; în a), nodul de grad 4 ar fi legat de toate celelalte, deci niciun nod n-ar putea avea gradul 0. Rămâne d): de exemplu, din graful complet cu 5 noduri se elimină muchiile [1,2], [1,3] și [4,5], iar gradele devin 2, 3, 3, 3, 3.

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 [c] partea întreagă a numărului real c.

    Scrieți valoarea afișată dacă se citesc, în această ordine, numerele 3, 746, 82, 3067, 67, 78, 178.

    citește n (număr natural nenul)
    x←0
    ┌cât timp n>0 execută
    │ citește a,b  (numere naturale)
    │ c←a; p←1
    │┌cât timp a>9 execută
    ││ a←[a/10]; p←p*10
    │└■
    │ a←a*p+b
    │┌dacă a≠c atunci
    ││ x←x+1
    │└■
    │ n←n-1
    └■
     scrie x
    Vezi rezolvarea

    Răspunsul din barem: 2

    Pentru fiecare pereche (a,b), algoritmul păstrează doar prima cifră a lui a, pe poziția ei (p este puterea lui 10 corespunzătoare), și îi adaugă b; x numără perechile pentru care rezultatul diferă de a. Rezultatul este egal cu a exact când b este chiar a fără prima cifră. (746, 82): 700 + 82 = 782, diferit de 746; (3067, 67): 3000 + 67 = 3067, egal; (78, 178): 70 + 178 = 248, diferit de 78. Se afișează 2.

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

    Același algoritm ca la 1.a.

    Dacă pentru n se citește numărul 2, scrieți un șir de numere naturale din intervalul [0,9] care pot fi citite în continuare, în acea ordine, astfel încât, în urma executării algoritmului, să se afișeze valoarea 0.

    Vezi rezolvarea

    Exemplu: 5 0 7 0

    Pentru un număr a de o cifră, p rămâne 1, iar rezultatul este a + b, egal cu a doar dacă b = 0. Cu n=2 se citesc două perechi, deci șirul are forma x, 0, y, 0, cu x și y din intervalul [0,9].

  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 n, x = 0, a, b, c, p;
        cin >> n;
        while (n > 0)
        {
            cin >> a >> b;
            c = a;
            p = 1;
            while (a > 9)
            {
                a = a / 10;
                p = p * 10;
            }
            a = a * p + b;
            if (a != c) x = x + 1;
            n = n - 1;
        }
        cout << x;
        return 0;
    }

    Cele două structuri cât timp devin while, iar [a/10] este împărțirea întreagă din C/C++. a și b se citesc la fiecare pas al buclei exterioare, ca în algoritm.

  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 prima structură cât timp...execută cu o structură repetitivă de tip pentru...execută.

    Vezi rezolvarea
    citește n (număr natural nenul)
    x←0
    ┌pentru i←1,n execută
    │ citește a,b (numere naturale)
    │ c←a; p←1
    │┌cât timp a>9 execută
    ││ a←[a/10]; p←p*10
    │└■
    │ a←a*p+b
    │┌dacă a≠c atunci
    ││ x←x+1
    │└■
    └■
    scrie x

    n era folosit doar ca un contor care scade până la 0, deci bucla se executa de n ori. Structura pentru, cu un contor nou i de la 1 la n, face același număr de pași, iar instrucțiunea n←n-1 dispare.

  5. Exercițiul 2 6p Arbori

    Î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).

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

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

    Scrieți nodurile care pot fi desemnate ca rădăcină, astfel încât fiecare dintre arborii obținuți să aibă un număr minim de niveluri.

    Vezi rezolvarea

    Răspunsul din barem: 2, 3

    Numărul de niveluri este cel mai mic atunci când rădăcina este cât mai la mijlocul arborelui. Cu rădăcina 2, nodurile cele mai îndepărtate (4 și 5) sunt la distanța 2, deci arborele are 3 niveluri; la fel cu rădăcina 3, pentru care cele mai îndepărtate sunt 1 și 6. Orice altă rădăcină are un nod la distanța 3 sau mai mare (de exemplu, din 1 până la 4), deci cel puțin 4 niveluri.

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

    Variabila p, declarată alăturat, memorează caracteristicile unui produs: denumire și preț.

    Scrieți o secvență de instrucțiuni C/C++ prin care variabila a memorează valoarea primei litere a denumirii produsului respectiv, dacă acesta are prețul strict mai mic decât 100, sau caracterul * în caz contrar.

    struct produs
    {  char denumire[20];
       int pret;
    }p;
    char a;
    Vezi rezolvarea
    if (p.pret < 100) a = p.denumire[0];
    else a = '*';

    Prima literă a denumirii este primul caracter al șirului, p.denumire[0]. Caracterul * se scrie între apostrofuri, ca o constantă de tip caracter.

Subiectul al III-lea

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

    Subprogramul DNPI are un singur parametru, n, prin care primește un număr natural (n∈[1,10^9]), și afișează pe ecran, separați prin câte un spațiu, toți divizorii pozitivi impari ai lui n care NU sunt primi.

    Scrieți definiția completă a subprogramului.

    Exemplu: dacă n=90, se afișează pe ecran, nu neapărat în această ordine, numerele

    1 9 15 45
    Vezi rezolvarea
    void DNPI(int n)
    {
        int d, v, k, t, prim;
        for (d = 1; d * d <= n; d++)
            if (n % d == 0)
                for (t = 1; t <= 2; t++)
                {
                    if (t == 1) v = d;
                    else v = n / d;
                    if (t == 2 && v == d) break;
                    if (v % 2 == 1)
                    {
                        prim = 1;
                        if (v < 2) prim = 0;
                        for (k = 2; k * k <= v; k++)
                            if (v % k == 0) prim = 0;
                        if (prim == 0) cout << v << ' ';
                    }
                }
    }

    Divizorii lui n se iau în perechi, d și n/d, cu d până la radicalul lui n (când d = n/d, divizorul se ia o singură dată). Pentru fiecare divizor impar se verifică dacă este prim; 1 nu este prim, deci se afișează și el. Enunțul acceptă numerele în orice ordine.

  2. Exercițiul 2 10p Tablouri bidimensionale

    Un joc folosește o tablă dreptunghiulară, pe care sunt reprezentate celule de dimensiune egală, dispuse pe m linii și pe n coloane. În fiecare celulă este înscris un număr natural.

    Numim pătrat de valoare p patru celule ale tablei, situate pe două linii consecutive și pe două coloane consecutive, cu proprietatea că suma valorilor înscrise în aceste celule este egală cu p. Scopul jocului este determinarea unui pătrat de valoare maximă.

    Scrieți un program C/C++ care citește de la tastatură două numere naturale din intervalul [2,20], m și n, apoi elementele unui tablou bidimensional cu m linii și n coloane, numere naturale din intervalul [0,10^4], reprezentând numerele înscrise pe tabla de joc, în ordinea dispunerii celulelor corespunzătoare. Programul determină un pătrat de valoare maximă al tablei și afișează pe ecran această valoare.

    Exemplu: pentru m=5, n=4 și tabloul alăturat, se afișează pe ecran valoarea 36, corespunzătoare pătratului evidențiat în figură.

    11230
    31012
    113121
    1231
    71201
    Vezi rezolvarea
    #include <iostream>
    using namespace std;
    
    int main()
    {
        int m, n, a[20][20], i, j, s, maxim = -1;
        cin >> m >> n;
        for (i = 0; i < m; i++)
            for (j = 0; j < n; j++)
                cin >> a[i][j];
        for (i = 0; i + 1 < m; i++)
            for (j = 0; j + 1 < n; j++)
            {
                s = a[i][j] + a[i][j + 1] + a[i + 1][j] + a[i + 1][j + 1];
                if (s > maxim) maxim = s;
            }
        cout << maxim;
        return 0;
    }

    Un pătrat este determinat de celula lui din stânga-sus, (i,j), care poate fi pe orice linie în afară de ultima și pe orice coloană în afară de ultima. Pentru fiecare se calculează suma celor patru celule și se reține cea mai mare. Valorile sunt naturale, deci maxim poate porni de la -1.

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

    Fișierul date.in conține pe prima linie două numere naturale din intervalul [1,10^6], m și n, iar pe următoarele două linii numere naturale din intervalul [0,10^2): pe a doua linie un șir A, de m numere, iar pe a treia linie un șir B, de n numere. Numerele aflate pe aceeași linie sunt separate prin câte un spațiu. Se cere să se afișeze pe ecran numărul maxim de perechi de forma (pa,pb) (pa∈[1,m], pb∈[1,n]), cu proprietatea că termenul de pe poziția pa din șirul A are aceeași valoare cu termenul de pe poziția pb din șirul B și că fiecare poziție, corespunzătoare șirului A, respectiv șirului B, apare în cel mult o pereche, ca în exemplu. Proiectați un algoritm eficient din punctul de vedere al timpului de executare.

    Exemplu: dacă fișierul conține numerele alăturate, se afișează pe ecran 6 (de exemplu, pentru perechile (1,1), (2,9), (4,2), (5,5), (6,6), (7,7) sau pentru perechile (1,2), (2,9), (4,1), (5,7), (6,8), (8,5)).

    8 9
    1 0 4 1 5 3 5 5
    1 1 1 7 5 3 5 3 0

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

    Vezi rezolvarea

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

    Fiecare poziție poate apărea în cel mult o pereche, iar o pereche leagă doi termeni egali. Pentru o valoare v care apare de a ori în A și de b ori în B se pot forma cel mult min(a, b) perechi cu valoarea v, și chiar atâtea. Răspunsul este suma acestor minime, pentru toate valorile.

    Valorile sunt între 0 și 99, deci se folosesc doi vectori de frecvență cu câte 100 de elemente: pe măsura citirii lui A crește fa[v], iar pe măsura citirii lui B crește fb[v]. La final se adună min(fa[v], fb[v]) pentru v de la 0 la 99.

    Eficiență: fiecare număr se citește și se numără o singură dată, în timp constant, iar suma finală are un număr fix de pași, deci timpul este liniar în numărul de valori din fișier.

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

    Același algoritm ca la 3.a.

    Exemplu: dacă fișierul conține numerele alăturate, se afișează pe ecran 6 (de exemplu, pentru perechile (1,1), (2,9), (4,2), (5,5), (6,6), (7,7) sau pentru perechile (1,2), (2,9), (4,1), (5,7), (6,8), (8,5)).

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

    Vezi rezolvarea
    #include <fstream>
    #include <iostream>
    using namespace std;
    
    int main()
    {
        ifstream fin("date.in");
        int fa[100] = {0}, fb[100] = {0}, m, n, i, v, nr = 0;
        fin >> m >> n;
        for (i = 0; i < m; i++)
        {
            fin >> v;
            fa[v]++;
        }
        for (i = 0; i < n; i++)
        {
            fin >> v;
            fb[v]++;
        }
        fin.close();
        for (v = 0; v < 100; v++)
            if (fa[v] < fb[v]) nr = nr + fa[v];
            else nr = nr + fb[v];
        cout << nr;
        return 0;
    }

    Programul face pașii de la 3.a. Numărul perechilor este cel mult 10^6 și încape în tipul int.

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?