Bac informatică 2025 Varianta 6, rezolvată

Lucrarea „2025 Varianta 6” 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

    Variabilele m, n, p, q și x sunt de tip întreg, iar m<p<q<n.

    Indicați o expresie C/C++ care are valoarea 1 dacă și numai dacă numărul memorat în variabila x aparține intervalului [m,n], dar NU și intervalului (p,q).

    • a)x<=m || x>=p && x<=q || x>=n
    • b)x<=m && x>=p || x<=q && x>=n
    • c)x>=m || x<=p && x>=q || x<=n
    • d)x>=m && x<=p || x>=q && x<=n
    Arată răspunsul și explicația

    Răspuns corect: d) x>=m && x<=p || x>=q && x<=n

    x trebuie să fie în [m,n], dar nu în (p,q). Cum m<p<q<n, asta înseamnă că x este fie între m și p (inclusiv capetele), fie între q și n: x>=m && x<=p || x>=q && x<=n. && are prioritate față de ||, deci expresia se citește exact așa: varianta d).

    a) este adevărată pentru valori din afara lui [m,n] (de exemplu mai mici decât m), b) nu poate fi adevărată niciodată, iar c) este adevărată pentru orice x.

  2. Exercițiul 24p

    Subprogramul f este definit alăturat.

    Indicați ce se afișează în urma apelului de mai jos.

    f(2050);

    void f(int n)
    { cout<<n<<' '; | printf("%d ",n);
      if(n%10!=0) { cout<<n<<' '; | printf("%d ",n);
                    f(n/10);
                  }
      else if(n!=0){ f(n/10);
                     cout<<n<<' '; | printf("%d ",n);
                   }
    }
    • a)2050 205 20 2 0
    • b)2050 205 20 2 0 20 2050
    • c)2050 205 205 20 2 2 0 20 2050
    • d)2050 2050 205 205 20 20 2 2 0
    Arată răspunsul și explicația

    Răspuns corect: c) 2050 205 205 20 2 2 0 20 2050

    f(n) afișează întâi n. Dacă ultima cifră e nenulă, îl mai afișează o dată și continuă cu f(n/10); dacă ultima cifră e 0 și n≠0, continuă cu f(n/10) și abia după aceea îl afișează din nou pe n.

    f(2050) afișează 2050, apelează f(205), apoi afișează iar 2050. f(205) afișează 205 de două ori, apoi f(20). f(20) afișează 20, apelează f(2), apoi iar 20. f(2) afișează 2 de două ori, apoi f(0), care afișează doar 0. În ordine: 2050 205 205 20 2 2 0 20 2050.

  3. Exercițiul 34p

    Utilizând metoda bactracking se generează toate tipurile de propoziții formate din patru unități sintactice (părți ale propoziției): un subiect, un predicat, un atribut și un complement, astfel încât atributul să fie plasat imediat înainte ori imediat după subiect. Două propoziții diferă prin ordinea unităților sale sintactice. Primele patru soluții generate sunt, în această ordine:

    1. (subiect, atribut, predicat, complement)
    2. (subiect, atribut, complement, predicat)
    3. (predicat, subiect, atribut, complement)
    4. (predicat, atribut, subiect, complement)

    Indicați ultima soluție generată.

    • a)(complement, atribut, subiect, predicat)
    • b)(complement, atribut, predicat, subiect)
    • c)(complement, subiect, atribut, predicat)
    • d)(complement, predicat, subiect, atribut)
    Arată răspunsul și explicația

    Răspuns corect: a) (complement, atribut, subiect, predicat)

    Primele soluții arată ordinea în care sunt încercate unitățile: subiect, predicat, atribut, complement (de pildă, (subiect, predicat, …) nu apare, pentru că atributul n-ar mai fi lângă subiect).

    Ultima soluție începe cu complement și continuă cu unitățile cele mai târzii din ordine: pe poziția a doua, atribut. Pe a treia, predicat ar veni după subiect în ordine, dar (complement, atribut, predicat, subiect) desparte atributul de subiect. Rămâne (complement, atribut, subiect, predicat).

  4. Exercițiul 44p

    Variabila m memorează elementele unui tablou bidimensional cu 100 de linii și 100 de coloane, numerotate de la 0 la 99.

    Indicați o expresie C/C++ prin care poate fi accesat un element aflat pe diagonala principală a tabloului.

    • a)m[1,16]
    • b)m[16][16]
    • c)m(16,16)
    • d)m(16)(1)
    Arată răspunsul și explicația

    Răspuns corect: b) m[16][16]

    Pe diagonala principală se află elementele cu indicele liniei egal cu cel al coloanei, iar în C/C++ un element al unui tablou bidimensional se scrie cu câte o pereche de paranteze drepte pentru fiecare indice: m[16][16].

    a), c) și d) nu sunt expresii C/C++ valide pentru accesarea unui element.

  5. Exercițiul 54p

    Un graf neorientat are 7 noduri și 21 de muchii.

    Indicați numărul minim de muchii care pot fi eliminate din acest graf, astfel încât graful parțial obținut să aibă două componente conexe, cu cel puțin două noduri fiecare.

    • a)6
    • b)8
    • c)10
    • d)12
    Arată răspunsul și explicația

    Răspuns corect: c) 10

    Un graf neorientat cu 7 noduri are cel mult 7·6/2 = 21 de muchii, deci graful este complet.

    Ca să rămână două componente conexe, nodurile se împart în două grupuri și se elimină toate muchiile dintre ele. Cu grupuri de 2 și 5 noduri sunt 2·5 = 10 astfel de muchii, iar cu grupuri de 3 și 4 noduri, 3·4 = 12. Minimul este 10.

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 numerele afișate dacă se citesc, în această ordine, numerele 75 și 90.

    citește m,n
      (numere naturale nenule, m≤n)
    ┌pentru i←n,m,-1 execută
    │ x←i
    │ c←x%10
    │┌repetă
    ││ x←[x/10]
    │└până când x%10≠c
    │┌dacă x=0 atunci
    ││ scrie i,' '
    │└■
    └■
    Arată răspunsul și explicația

    Răspunsul din barem: 88 77

    88 77
    
    Pentru fiecare i, de la n în jos până la m, se reține ultima cifră c și se taie cifre de la dreapta cât timp următoarea cifră este tot c. x ajunge 0 exact când toate cifrele lui i sunt egale cu c, și atunci i se afișează.
    Între 75 și 90, numerele cu toate cifrele egale sunt 88 și 77, afișate în ordine descrescătoare.
  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.

    Dacă pentru variabila m se citește valoarea 2025, scrieți două numere distincte care pot fi citite pentru variabila n, astfel încât, pentru fiecare dintre acestea, în urma executării algoritmului, să se afișeze o singură valoare.

    citește m,n
      (numere naturale nenule, m≤n)
    ┌pentru i←n,m,-1 execută
    │ x←i
    │ c←x%10
    │┌repetă
    ││ x←[x/10]
    │└până când x%10≠c
    │┌dacă x=0 atunci
    ││ scrie i,' '
    │└■
    └■
    Arată răspunsul și explicația
    Exemplu: 2222 și 3000
    
    Se afișează numerele cu toate cifrele egale dintre m=2025 și n. Primele astfel de numere după 2025 sunt 2222 și 3333, deci se afișează o singură valoare exact când n este în intervalul [2222,3332].
  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 m,n
      (numere naturale nenule, m≤n)
    ┌pentru i←n,m,-1 execută
    │ x←i
    │ c←x%10
    │┌repetă
    ││ x←[x/10]
    │└până când x%10≠c
    │┌dacă x=0 atunci
    ││ scrie i,' '
    │└■
    └■
    Arată răspunsul și explicația
    #include <iostream>
    using namespace std;
    
    int main()
    {
        int m, n, i, x, c;
        cin >> m >> n;
        for (i = n; i >= m; i--)
        {
            x = i;
            c = x % 10;
            do
            {
                x = x / 10;
            } while (x % 10 == c);
            if (x == 0) cout << i << ' ';
        }
        return 0;
    }
    
    pentru i←n,m,-1 execută devine for (i = n; i >= m; i--), cu pasul -1. repetă…până când x%10≠c devine do…while cu condiția negată, x % 10 == c.
  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 structura pentru...execută cu o structură repetitivă de tip cât timp...execută.

    citește m,n
      (numere naturale nenule, m≤n)
    ┌pentru i←n,m,-1 execută
    │ x←i
    │ c←x%10
    │┌repetă
    ││ x←[x/10]
    │└până când x%10≠c
    │┌dacă x=0 atunci
    ││ scrie i,' '
    │└■
    └■
    Arată răspunsul și explicația
    citește m,n (numere naturale nenule, m≤n)
    i←n
    ┌cât timp i≥m execută
    │ x←i
    │ c←x%10
    │┌repetă
    ││ x←[x/10]
    │└până când x%10≠c
    │┌dacă x=0 atunci
    ││ scrie i,' '
    │└■
    │ i←i-1
    └■
    
    Cu cât timp, contorul se gestionează explicit: i primește valoarea inițială n înainte de buclă, se continuă cât timp i≥m (pasul este -1, deci se coboară spre m), iar i←i-1 se face la sfârșitul corpului.
  5. Exercițiul 26p

    Un arbore cu 8 noduri, numerotate de la 1 la 8, este reprezentat prin vectorul de „tați” (3, 0, 2, 5, 2, 5, 1, 5). Enumerați două noduri ale arborelui care pot fi alese drept rădăcină (cu excepția rădăcinii curente), astfel încât nodul 4 să aibă aceiași „frați” ca în reprezentarea dată.

    Arată răspunsul și explicația
    Exemplu: 1 3
    
    În reprezentarea dată rădăcina este 2, iar tatăl lui 4 este 5, cu fiii 4, 6 și 8; frații lui 4 sunt 6 și 8. Ca frații să rămână aceiași, 5 trebuie să rămână tatăl lui 4, 6 și 8, deci tatăl lui 5 trebuie să fie tot 2, singurul lui vecin în afară de 4, 6 și 8.
    Asta se întâmplă pentru orice rădăcină din partea arborelui legată de 5 prin 2: nodurile 2, 3, 1 și 7. În afară de rădăcina curentă, 2, pot fi alese 1, 3 sau 7.
  6. Exercițiul 36p

    În declarările alăturate variabila d memorează în câmpurile A și B coordonatele, în sistemul de coordonate xOy, ale vârfurilor din stânga – sus, respectiv din dreapta – jos ale unui dreptunghi cu laturile paralele cu axele sistemului de coordonate.

    Scrieți o secvență de instrucțiuni C/C++ în urma executării căreia se afișează pe ecran mesajul DA, dacă figura corespunzătoare variabilei d este pătrat sau mesajul NU în caz contrar.

    struct punct
           { int x,y;
           };
    struct figura
           { punct A, B;
           } d;
    Arată răspunsul și explicația
    if (d.B.x - d.A.x == d.A.y - d.B.y) cout << "DA";
    else cout << "NU";
    
    A este vârful din stânga-sus și B cel din dreapta-jos, deci lățimea dreptunghiului este d.B.x - d.A.x, iar înălțimea d.A.y - d.B.y. Figura este pătrat când cele două sunt egale.

Subiectul al III-lea30 de puncte

  1. Exercițiul 110p

    Subprogramul diviz are un singur parametru, n, prin care primește un număr natural (n∈[1,109]). Subprogramul returnează cel mai mare divizor al lui n care este pătrat perfect.

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

    Exemplu: pentru n=72 subprogramul returnează 36, pentru n=16 subprogramul returnează 16, iar pentru n=15 subprogramul returnează 1.

    Arată răspunsul și explicația
    int diviz(int n)
    {
        int d, maxim = 1;
        for (d = 2; d * d <= n; d++)
            if (n % (d * d) == 0) maxim = d * d;
        return maxim;
    }
    
    Un divizor pătrat perfect are forma d·d. Se încearcă toate valorile d cu d·d ≤ n, în ordine crescătoare, și se reține ultimul pătrat d·d care îl divide pe n, deci pe cel mai mare. 1 divide orice număr, de aceea maxim pornește de la 1.
    Cum n ≤ 10^9, d ajunge cel mult la aproximativ 31623, iar d·d încape în tipul int.
  2. Exercițiul 210p

    Într-un text de cel mult 100 de caractere cuvintele sunt formate doar din litere mici ale alfabetului englez și sunt separate prin unul sau mai multe spații. Textul are cel puțin două cuvinte.

    Scrieți un program C/C++ care citește de la tastatură un text de tipul precizat mai sus și îl transformă în memorie prin eliminarea sau inserarea unor spații și a unor cratime (simbolul -), astfel încât între oricare două cuvinte consecutive în text să fie câte o cratimă, încadrată la stânga și la dreapta de câte un spațiu, ca în exemplu. Programul afișează pe ecran textul obținut.

    Exemplu: pentru textul de pe primul rând de mai jos se obține textul de pe al doilea rând.

    anul     acesta devin         student
    anul - acesta - devin - student
    Arată răspunsul și explicația
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    int main()
    {
        char s[301], t[301] = "", *p;
        cin.getline(s, 101);
        p = strtok(s, " ");
        while (p != NULL)
        {
            if (t[0] != '\0') strcat(t, " - ");
            strcat(t, p);
            p = strtok(NULL, " ");
        }
        strcpy(s, t);
        cout << s;
        return 0;
    }
    
    strtok desparte textul în cuvinte, oricâte spații ar fi între ele. Textul nou se construiește în t: înaintea fiecărui cuvânt, în afară de primul, se adaugă secvența " - ". La final t se copiază înapoi în s, deci transformarea rămâne în memorie.
    s are loc pentru 300 de caractere: textul citit are cel mult 100, dar prin inserarea cratimelor poate crește (două cuvinte de câte o literă separate printr-un spațiu devin 5 caractere).
  3. Exercițiul 3.a2p

    Fișierul text bac.txt conține un șir de cel mult 106 triplete de numere naturale din intervalul [1,102], numerele din fiecare triplet reprezentând lungimile laturilor câte unui triunghi. Fiecare triplet se află pe câte o linie a fișierului, iar numerele care îl compun sunt separate prin câte un spațiu.

    Într-un triunghi dreptunghic pătratul lungimii ipotenuzei este egal cu suma pătratelor lungimilor celor două catete.

    Se cere să se afișeze pe ecran numărul maxim de triunghiuri dreptunghice din fișier care au aceeași lungime a ipotenuzei. Proiectați un algoritm eficient din punctul de vedere al timpului de executare.

    Exemplu: dacă fișierul conține numerele alăturate, pe ecran se afișează 3 (sunt trei triunghiuri de tipul cerut cu ipotenuza 25: două au catetele 7, respectiv 24, și unul are catetele 15, respectiv 20).

    Figura din enunț

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

    Arată răspunsul și explicația
    Laturile au cel mult 100, deci și ipotenuza. Se folosește un vector de apariții v, cu 101 elemente pornite de la 0, în care v[i] numără triunghiurile dreptunghice cu ipotenuza i.
    
    Tripletele se citesc pe rând. Pentru fiecare, cea mai mare latură se aduce pe ultima poziție (prin cel mult două interschimbări) și poate fi ipotenuza; dacă suma pătratelor celorlalte două este egală cu pătratul ei, triunghiul este dreptunghic și crește v[ipotenuză]. La final se afișează cea mai mare valoare din v.
    
    Eficiență: fiecare triplet se prelucrează o singură dată, în timp constant, deci timpul este liniar în numărul de triplete. Tripletele nu se memorează: vectorul v are mereu 101 elemente, oricât de mare ar fi fișierul.
  4. Exercițiul 3.b8p

    Fișierul text bac.txt conține un șir de cel mult 106 triplete de numere naturale din intervalul [1,102], numerele din fiecare triplet reprezentând lungimile laturilor câte unui triunghi. Fiecare triplet se află pe câte o linie a fișierului, iar numerele care îl compun sunt separate prin câte un spațiu.

    Într-un triunghi dreptunghic pătratul lungimii ipotenuzei este egal cu suma pătratelor lungimilor celor două catete.

    Se cere să se afișeze pe ecran numărul maxim de triunghiuri dreptunghice din fișier care au aceeași lungime a ipotenuzei. Proiectați un algoritm eficient din punctul de vedere al timpului de executare.

    Exemplu: dacă fișierul conține numerele alăturate, pe ecran se afișează 3 (sunt trei triunghiuri de tipul cerut cu ipotenuza 25: două au catetele 7, respectiv 24, și unul are catetele 15, respectiv 20).

    Figura din enunț

    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 v[101] = {0}, a, b, c, aux, i, maxim = 0;
        while (fin >> a >> b >> c)
        {
            if (a > c) { aux = a; a = c; c = aux; }
            if (b > c) { aux = b; b = c; c = aux; }
            if (a * a + b * b == c * c) v[c]++;
        }
        fin.close();
        for (i = 1; i <= 100; i++)
            if (v[i] > maxim) maxim = v[i];
        cout << maxim;
        return 0;
    }
    
    Programul face pașii de la 3.a. După cele două interschimbări, c este cea mai mare latură, deci singura care poate fi ipotenuza. Pătratele laturilor ajung cel mult la 20000 și încap în tipul int.

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