Sari la conținut

Bac informatică 2025 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 2025

Varianta 7 din 2025 trece prin tipuri de date, structuri, backtracking, arbori, grafuri orientate, factori primi, recursivitate, șiruri de caractere, matrice și fișiere. Este o variantă echilibrată, bună pentru recapitularea întregii materii.

Subiectul I (20p): 5 grile: o expresie cu o împărțire reală și una întreagă, data expirării dintr-o structură medicament cu un câmp expira care este tot o structură, o problemă de backtracking cu comenzi de încălțăminte, rădăcinile pentru care un arbore are trei frunze și numărul minim de arce adăugate ca un graf orientat să aibă două componente tare conexe.

Subiectul al II-lea (40p): Un algoritm în pseudocod care află cel mai mare factor prim și produsul factorilor primi distincți ai unui număr, valorile unui subprogram recursiv și o secvență cu strstr și strcpy.

Subiectul al III-lea (30p): Un subprogram cu numere (consecutiv, care găsește f cu (f-1)·f < n ≤ f·(f+1)), o problemă cu o matrice care numără tripletele de locuri libere alăturate de pe primul și ultimul rând al unei parcări și o problemă de eficiență care extrage trei numere dintre valorile inversate citite din fișierul bac.in.

⚠️ La ce să fii atent

  • La I.5: Graful dat nu are niciun circuit. Arcul (3,2) închide circuitele 2→1→3→2 și 2→6→4→3→2, iar vârful 5 rămâne singur: un singur arc ajunge.
  • La II.2: Pentru 17 recursivitatea coboară doar prin numerele impare, până la f(3) = 3. Calculează pe rând de jos în sus: f(5) = 2, f(7) = 5 și așa mai departe, până la f(17) = 8.
  • La II.3: strstr întoarce adresa primei apariții a lui car, deci s2 devine carea și n este 5. Apoi strcpy(s1+3, s2+3) scrie ea peste restul lui s1, care devine parea.
  • La III.2: Tripletele se pot suprapune. Pe ultimul rând din exemplu, locurile 1-2-3 și 2-3-4 se numără separat, deci răspunsul este 3.
  • La III.3: Cele trei numere sunt cel mai mic, cel mai mare și al doilea cel mai mic dintre valorile distincte. Valorile repetate se socotesc o singură dată: în exemplu, 2131 apare de două ori, dar 1312 se ia o singură dată.

Subiectul I

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

    Indicați valoarea expresiei C/C++ alăturate.

    15.4/2+15/2
    • a)14
    • b)14.7
    • c)15
    • d)15.2
    Vezi rezolvarea

    Răspuns corect: b) 14.7

    15.4 este un număr real, deci 15.4/2 dă 7.7. 15/2 este însă o împărțire între numere întregi și dă câtul, 7. Suma este 7.7 + 7 = 14.7.

    15.2 ar ieși dacă și 15/2 ar fi 7.5, iar 14 sau 15 dacă primul termen ar fi rotunjit.

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

    Variabila m, declarată alăturat, memorează, pentru un medicament, codul, procentul de compensare și data expirării (ziua, luna și anul).

    Indicați o expresie C/C++ cu valoarea 1 dacă și numai dacă medicamentul expiră în anul 2025, după luna octombrie.

    struct data
    { int zi,luna,an;};
    struct medicament
    {  int cod;
       float compensare;
       data expira;
    }m;
    • a)m.data.an==2025 && m.data.luna>10
    • b)data.an.m==2025 && data.luna.m>10
    • c)m.expira.an==2025 && m.expira.luna>10
    • d)m.an.expira==2025 && m.luna.expira>10
    Vezi rezolvarea

    Răspuns corect: c) m.expira.an==2025 && m.expira.luna>10

    m este variabila de tip medicament, iar data expirării este câmpul ei expira, de tip data, cu câmpurile zi, luna și an. Anul este deci m.expira.an, iar luna m.expira.luna; după octombrie înseamnă luna mai mare decât 10.

    a) folosește numele tipului, data, în locul câmpului expira, iar b) și d) scriu numele în ordine greșită.

  3. Exercițiul 3 4p Backtracking

    Un site de vânzări online oferă reduceri la încălțăminte pentru fiecare comandă care conține trei perechi de articole din categorii diferite din mulțimea ordonată {balerini, botine, cizme, ghete, sandale, teniși}, astfel încât o comandă să nu conțină simultan ghete și cizme, respectiv balerini și sandale. Două soluții diferă prin cel puțin o categorie. Utilizând metoda backtracking, se generează toate comenzile posibile, iar primele patru soluții generate sunt:

    1. (balerini, botine, cizme)
    2. (balerini, botine, ghete)
    3. (balerini, botine, teniși)
    4. (balerini, cizme, teniși)

    Indicați soluția generată imediat înainte de (cizme, sandale, teniși).

    • a)(botine, ghete, sandale)
    • b)(botine, cizme, sandale)
    • c)(botine, cizme, teniși)
    • d)(botine, sandale, teniși)
    Vezi rezolvarea

    Răspuns corect: d) (botine, sandale, teniși)

    Comenzile sunt submulțimi de câte trei categorii, generate în ordinea din mulțime, fără ghete împreună cu cizme și fără balerini împreună cu sandale.

    (cizme, sandale, teniși) este una dintre primele comenzi care încep cu cizme, deci înaintea ei vine ultima comandă care începe cu botine: a doua și a treia categorie trebuie să fie cât mai târzii în ordine, adică sandale și teniși — (botine, sandale, teniși), care respectă ambele restricții.

  4. Exercițiul 4 4p Arbori

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

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

    Indicați două noduri care pot fi alese drept rădăcină, astfel încât arborele obținut, pentru fiecare dintre acestea, să aibă trei frunze.

    • a)1,3
    • b)2,4
    • c)2,5
    • d)4,6
    Vezi rezolvarea

    Răspuns corect: d) 4,6

    Nodurile cu un singur vecin sunt 3, 4, 5 și 6. Oricare dintre ele devine frunză dacă nu este rădăcina; nodurile 1 și 2 au mai mulți vecini, deci nu sunt frunze niciodată.

    Dacă rădăcina este unul dintre nodurile 1 sau 2, toate cele patru rămân frunze. Dacă rădăcina este unul dintre 3, 4, 5, 6, frunzele sunt celelalte trei. Dintre variante, doar 4,6 are ambele noduri cu un singur vecin.

  5. Exercițiul 5 4p Grafuri orientate

    Un graf orientat cu 6 vârfuri, numerotate de la 1 la 6, are arcele:

    1. (1,3)
    2. (2,1)
    3. (2,5)
    4. (2,6)
    5. (4,3)
    6. (6,4)
    7. (6,5)

    Indicați numărul minim de arce care trebuie adăugate pentru ca graful obținut să aibă două componente tare conexe.

    • a)1
    • b)2
    • c)3
    • d)4
    Vezi rezolvarea

    Răspuns corect: a) 1

    Graful dat nu are circuite, deci fiecare vârf este singur în componenta lui tare conexă: șase componente.

    Arcul (3,2) închide circuitele 2→1→3→2 și 2→6→4→3→2, care leagă vârfurile 1, 2, 3, 4 și 6 într-o singură componentă tare conexă, iar vârful 5 rămâne singur (din el nu pleacă niciun arc). Un singur arc ajunge, deci răspunsul este 1.

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 valorile afișate în urma executării algoritmului, dacă se citește numărul 252.

    citește n
     (număr natural, n≥2)
     d←2; x←1; y←1
    ┌cât timp n>1 execută
    │┌dacă n%d=0 atunci
    ││ x←d; y←y*d
    ││┌cât timp n%d=0 execută
    │││ n←[n/d]
    ││└■
    │└■
    │ d←d+1
    └■
     scrie x,' ',y
    Vezi rezolvarea

    Răspunsul din barem: 7 42

    Algoritmul caută divizorii primi ai lui n, în ordine crescătoare: la fiecare divizor d găsit, îl împarte pe n la d de câte ori se poate, reține d în x și îl înmulțește în y. La final x este cel mai mare factor prim, iar y produsul factorilor primi distincți. 252 = 2^2 · 3^2 · 7, deci x = 7 și y = 2 · 3 · 7 = 42.

  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 distincte din intervalul [10,10^2] care pot fi citite, astfel încât, în urma executării algoritmului, pentru fiecare dintre acestea, să se afișeze două valori egale.

    Vezi rezolvarea

    Exemplu: 11 și 16

    x (cel mai mare factor prim) este egal cu y (produsul factorilor primi distincți) exact când n are un singur factor prim, adică este o putere a unui număr prim. Din intervalul [10,100]: orice număr prim, dar și 16, 25, 27, 32, 49, 64 sau 81.

  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 n, d = 2, x = 1, y = 1;
        cin >> n;
        while (n > 1)
        {
            if (n % d == 0)
            {
                x = d;
                y = y * d;
                while (n % d == 0) n = n / d;
            }
            d = d + 1;
        }
        cout << x << ' ' << y;
        return 0;
    }

    Cele două structuri cât timp devin while, iar [n/d] este împărțirea întreagă din C/C++.

  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 a doua structură cât timp...execută cu o structură repetitivă cu test final.

    Vezi rezolvarea
    citește n (număr natural, n≥2)
    d←2; x←1; y←1
    ┌cât timp n>1 execută
    │┌dacă n%d=0 atunci
    ││ x←d; y←y*d
    ││┌repetă
    │││ n←[n/d]
    ││└până când n%d≠0
    │└■
    │ d←d+1
    └■
    scrie x,' ',y

    repetă…până când execută corpul cel puțin o dată, iar cât timp poate să nu îl execute deloc. Aici nu contează: a doua structură este în interiorul lui dacă n%d=0, deci la intrarea în ea n se împarte sigur la d, iar corpul s-ar fi executat măcar o dată. Condiția de oprire este negația celei de continuare: n%d≠0.

  5. Exercițiul 2 6p Recursivitate

    Subprogramul f este definit alăturat.

    Scrieți valoarea f(2), respectiv valoarea f(17).

    int f(int x)
    { if (x<=4) return x;
      else return x-f(x-2);
    }
    Vezi rezolvarea

    Răspunsul din barem: 2 8

    Pentru x ≤ 4 funcția îl returnează chiar pe x, deci f(2) = 2 și f(3) = 3. Pentru x mai mare, f(x) = x − f(x−2), iar pentru 17 se coboară prin numerele impare: f(5) = 5 − 3 = 2, f(7) = 7 − 2 = 5, f(9) = 9 − 5 = 4, f(11) = 11 − 4 = 7, f(13) = 13 − 7 = 6, f(15) = 15 − 6 = 9, f(17) = 17 − 9 = 8.

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

    Variabilele s1 și s2 permit accesarea câte unui șir de cel mult 50 de caractere, iar variabila n este de tip întreg.

    Scrieți șirul accesat prin variabila s1, precum și valoarea lui n, în urma executării secvenței alăturate.

    strcpy(s1,"parcarea");
    strcpy(s2,strstr(s1,"car"));
    n=strlen(s2);
    strcpy(s1+n-2, s2+n-2);
    Vezi rezolvarea

    Răspunsul din barem: parea 5

    strstr(s1,"car") indică începutul lui "car" în "parcarea", deci s2 devine "carea", iar n = strlen(s2) = 5. strcpy(s1+n-2, s2+n-2) copiază în s1, de la poziția 3, șirul s2 de la poziția 3, adică "ea". s1 păstrează primele trei litere, "par", urmate de "ea": "parea".

Subiectul al III-lea

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

    Subprogramul consecutiv are doi parametri:

    • n, prin care primește un număr natural (n∈[1,10^4]);

    • f , prin care furnizează un număr natural cu proprietatea: (f-1)∙f < n ≤ f∙(f+1).

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

    Exemplu: dacă n=19 atunci f=4 (3∙4 < 19 ≤ 4∙5).

    Vezi rezolvarea
    void consecutiv(int n, int &f)
    {
        f = 1;
        while (f * (f + 1) < n) f++;
    }

    Produsele f·(f+1) cresc odată cu f: 2, 6, 12, 20, … Se caută cel mai mic f pentru care f·(f+1) ≥ n. Fiind cel mai mic, pentru f−1 produsul era mai mic decât n, adică (f−1)·f < n, deci f are exact proprietatea cerută. Valoarea se furnizează prin parametrul transmis prin referință, int &f.

  2. Exercițiul 2 10p Tablouri bidimensionale

    Parcarea unui mall are locuri de parcare dispuse pe nr rânduri, câte np pe fiecare rând, unul lângă altul. Trei prieteni vin cu câte o mașină la mall și caută un triplet de locuri libere alăturate, plasate toate trei doar pe primul sau toate trei doar pe ultimul rând al parcării.

    Scrieți un program C/C++ care citește de la tastatură două numere naturale din intervalul [3,50], nr și np, reprezentând numărul de rânduri din parcare, respectiv numărul de locuri de pe fiecare rând, apoi nr∙np valori din mulțimea {0,1}, elemente ale unui tablou bidimensional cu nr linii și np coloane, reprezentând, în ordinea dispunerii lor pe rânduri, starea locurilor de parcare (0, pentru loc liber, sau 1, pentru loc ocupat).

    Programul afișează pe ecran numărul de triplete de locuri libere pe care le pot găsi prietenii.

    Exemplu: pentru nr=4, np=5 și tabloul alăturat, se afișează pe ecran valoarea 3 (pe prima linie pot găsi tripletul format din al doilea, al treilea și al patrulea loc, iar pe ultima linie pot găsi tripletul format din primul, al doilea și al treilea loc sau tripletul format din al doilea, al treilea, și al patrulea loc).

    Tablou cu 4 linii și 5 coloane, cu valori 0 și 1. Pe linii: 1 0 0 0 1; 0 0 0 1 0; 0 1 0 0 0; 0 0 0 0 1. Pe prima linie sunt încadrate coloanele 2, 3 și 4, iar pe ultima linie coloanele 1, 2 și 3; tot pe ultima linie, coloanele 2, 3 și 4 sunt colorate cu gri.
    Vezi rezolvarea
    #include <iostream>
    using namespace std;
    
    int main()
    {
        int nr, np, a[50][50], i, j, t = 0;
        cin >> nr >> np;
        for (i = 0; i < nr; i++)
            for (j = 0; j < np; j++)
                cin >> a[i][j];
        for (j = 0; j + 2 < np; j++)
        {
            if (a[0][j] == 0 && a[0][j + 1] == 0 && a[0][j + 2] == 0) t++;
            if (a[nr - 1][j] == 0 && a[nr - 1][j + 1] == 0 && a[nr - 1][j + 2] == 0) t++;
        }
        cout << t;
        return 0;
    }

    Un triplet de locuri alăturate începe pe o coloană j și ocupă coloanele j, j+1 și j+2, deci j merge până la np-3. Pentru fiecare astfel de j se verifică, separat, dacă cele trei locuri sunt libere pe primul rând (linia 0) și pe ultimul (linia nr-1). Tripletele se pot suprapune, ca în exemplu, unde pe ultimul rând se numără două.

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

    La o loterie se generează aleatoriu un șir de numere naturale și pentru fiecare număr generat, se inversează ordinea cifrelor. Dintre valorile distincte obținute se extrag trei numere, în această ordine: cel mai mic, cel mai mare dintre cele rămase, apoi cel mai mic dintre cele rămase.

    Fișierul text bac.in conține cel mult 10^6 numere naturale din intervalul [1001,9999], cu cifra unităților nenulă, separate prin câte un spațiu, reprezentând termenii șirului generat aleatoriu în vederea extragerii.

    Scrieți un program C/C++ care afișează pe ecran cele trei numere, în ordinea extragerii acestora. Numerele afișate sunt separate prin câte un spațiu, iar dacă nu există trei astfel de numere distincte, se afișează pe ecran mesajul nu exista. Proiectați un algoritm eficient din punctul de vedere al timpului de executare și al memoriei utilizate.

    Exemplu: dacă fișierul conține numerele 1114 3212 3217 2855 7309 2131 2131 1238 7893 se afișează pe ecran, în această ordine, numerele 1312 9037 2123

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

    Vezi rezolvarea

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

    Numerele se citesc pe rând, fără să fie memorate, și pentru fiecare se calculează inversul, y, luând cifrele de la dreapta.

    Cele trei numere cerute sunt, dintre valorile distincte obținute, cea mai mică, cea mai mare și a doua cea mai mică. De aceea se păstrează doar trei valori: min1 < min2, cele mai mici două valori distincte, și maxim, cea mai mare. Pentru fiecare y: dacă y < min1, vechiul min1 devine min2 și y devine min1; altfel, dacă y este strict între min1 și min2, devine min2; separat, dacă y > maxim, devine maxim. Valorile egale cu una deja reținută nu schimbă nimic.

    La final există trei valori distincte exact când min2 < maxim; atunci se afișează min1, maxim, min2, altfel mesajul nu exista.

    Eficiență: fiecare număr se prelucrează o singură dată, în timp constant (are patru cifre), deci algoritmul este liniar în numărul de valori din fișier; se folosesc doar câteva variabile simple, deci memoria este constantă.

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

    La o loterie se generează aleatoriu un șir de numere naturale și pentru fiecare număr generat, se inversează ordinea cifrelor. Dintre valorile distincte obținute se extrag trei numere, în această ordine: cel mai mic, cel mai mare dintre cele rămase, apoi cel mai mic dintre cele rămase.

    Fișierul text bac.in conține cel mult 10^6 numere naturale din intervalul [1001,9999], cu cifra unităților nenulă, separate prin câte un spațiu, reprezentând termenii șirului generat aleatoriu în vederea extragerii.

    Scrieți un program C/C++ care afișează pe ecran cele trei numere, în ordinea extragerii acestora. Numerele afișate sunt separate prin câte un spațiu, iar dacă nu există trei astfel de numere distincte, se afișează pe ecran mesajul nu exista. Proiectați un algoritm eficient din punctul de vedere al timpului de executare și al memoriei utilizate.

    Exemplu: dacă fișierul conține numerele 1114 3212 3217 2855 7309 2131 2131 1238 7893 se afișează pe ecran, în această ordine, numerele 1312 9037 2123

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

    Vezi rezolvarea
    #include <fstream>
    #include <iostream>
    using namespace std;
    
    int main()
    {
        ifstream fin("bac.in");
        int x, y, min1 = 10000, min2 = 10000, maxim = 0;
        while (fin >> x)
        {
            y = 0;
            while (x != 0)
            {
                y = y * 10 + x % 10;
                x = x / 10;
            }
            if (y < min1)
            {
                min2 = min1;
                min1 = y;
            }
            else if (y > min1 && y < min2) min2 = y;
            if (y > maxim) maxim = y;
        }
        fin.close();
        if (min2 < maxim) cout << min1 << ' ' << maxim << ' ' << min2;
        else cout << "nu exista";
        return 0;
    }

    Programul face pașii de la 3.a. Numerele au patru cifre, iar cifra unităților e nenulă, deci inversul are tot patru cifre și e cel mult 9999; de aceea min1 și min2 pornesc de la 10000, o valoare pe care nicio valoare reală n-o atinge.

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?