Sari la conținut

Bac informatică 2024 Varianta 8, rezolvată

Varianta 8 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 8 din 2024

Varianta 8 din 2024 trece prin expresii logice, recursivitate, șiruri de caractere, arbori, grafuri orientate, backtracking, structuri, numere prime, matrice și fișiere. Este o variantă echilibrată, bună pentru recapitularea întregii materii.

Subiectul I (20p): 5 grile: o expresie care verifică dacă un interval nu conține numere de două cifre, apelul unui subprogram recursiv care afișează 13579, o secvență cu strcmp și strcpy, rădăcina unui arbore dat prin vectorul de „tați” și numărul maxim de vârfuri izolate ale unui graf orientat cu 24 de vârfuri și 24 de arce.

Subiectul al II-lea (40p): Un algoritm în pseudocod care alipește prima cifră a unui număr cu primele două și cu ultimele două cifre, o problemă de backtracking cu buchete de câte trei flori și o secvență care verifică dacă două note muzicale, memorate într-o structură interval, formează o terță.

Subiectul al III-lea (30p): Un subprogram cu numere prime (moderat, produsul a două numere prime consecutive), o problemă cu o matrice în care se tund parcelele cu gazon prea înalte și o problemă de eficiență care scrie în fișierul bac.txt, descrescător, termenii unui șir definit printr-o formulă de recurență.

⚠️ La ce să fii atent

  • La I.1: Intervalul [x,y] conține un număr de două cifre când se suprapune cu [10,99], adică x<=99 && y>=10. Răspunsul este negația acestei condiții.
  • La I.5: Între 5 vârfuri încap cel mult 5·4 = 20 de arce, prea puține pentru 24, dar între 6 vârfuri încap 30. Rămân izolate 24 - 6 = 18 vârfuri.
  • La II.1.d: repetă...până când execută corpul cel puțin o dată, iar bucla dată nu se execută deloc pentru un n de o cifră. Pune structura cu test final sub condiția n>9, altfel algoritmul nu mai e echivalent.
  • La II.3: În gamă, după G (sol) vin A (la) și B (si), care în alfabet sunt înaintea lui F și G. Pentru nota1 egal cu C, D sau E, terța este cu două litere mai departe, iar pentru F și G este cu cinci litere mai înapoi.
  • La III.3: Întoarce formula ca să obții termenul de dinainte: din d = 4c - 3b - 2a rezultă a = (4c - 3b - d)/2. Te oprești după ce ai scris cele două valori 0 de la începutul șirului, iar pentru 4*y cu y până la 10⁹ folosește long long.

Subiectul I

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

    Variabilele x și y memorează câte un număr natural (x≤y).

    Indicați expresia C/C++ cu valoarea 1 dacă și numai dacă intervalul [x,y] NU conține niciun număr de două cifre.

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

    Răspuns corect: b) !(x<=99 && y>=10)

    Intervalul [x,y] conține un număr de două cifre exact când se suprapune cu [10,99], adică x<=99 && y>=10. Negația acestei condiții este varianta b).

    a) este adevărată, de exemplu, pentru [5,50], care conține numere de două cifre; c) este adevărată tot pentru [5,50]; d) nu poate fi adevărată niciodată, pentru că x≤y.

  2. Exercițiul 2 4p Recursivitate

    Subprogramul f este definit alăturat.

    Indicați un apel în urma căruia se afișează pe ecran secvența:

    13579

    void f(int x,int y,int z)
    { if(z<x)
       { cout<<y; | printf("%d",y);
         f(x,y+2,z+1);
       }
    }
    • a)f(5,0,0);
    • b)f(5,1,1);
    • c)f(6,1,6);
    • d)f(6,1,1);
    Vezi rezolvarea

    Răspuns corect: d) f(6,1,1);

    Fiecare apel cu z<x afișează y și continuă cu y mai mare cu 2 și z mai mare cu 1. Se afișează deci y, y+2, y+4, … de x−z ori.

    Pentru 13579 trebuie să se înceapă de la 1 și să se afișeze 5 valori: y=1 și x−z=5, adică f(6,1,1). a) începe de la 0, b) afișează doar patru valori, iar c) nu afișează nimic.

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

    Variabilele s, x și y permit memorarea câte unui șir de cel mult 15 caractere.

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

    strcpy(x,"soare");
    strcpy(y,"ploaie");
    if (strcmp(x,y)>0) strcpy(s,x+1);
    else strcpy(s,y+2);
    • a)oare
    • b)oaie
    • c)ploaie
    • d)soare
    Vezi rezolvarea

    Răspuns corect: a) oare

    strcmp(x,y) compară șirurile alfabetic, literă cu literă: „soare” începe cu s, care vine după p, deci este mai mare decât „ploaie” și rezultatul este pozitiv.

    Se execută strcpy(s,x+1), care copiază șirul x începând cu a doua literă: oare.

  4. Exercițiul 4 4p Arbori

    Un arbore cu 14 noduri, numerotate de la 1 la 14, este reprezentat prin vectorul de “tați” (13,3,0,6,13,3,3,7,6,2,13,2,6,13).

    Indicați nodul care este rădăcina arborelui.

    • a)1
    • b)3
    • c)7
    • d)13
    Vezi rezolvarea

    Răspuns corect: b) 3

    În vectorul de tați, rădăcina este singurul nod care nu are tată, adică cel pentru care valoarea din vector este 0. Valoarea 0 se află pe poziția 3, deci rădăcina este nodul 3.

  5. Exercițiul 5 4p Grafuri orientate

    Indicați numărul maxim de vârfuri izolate pe care le poate avea un graf orientat cu 24 de vârfuri și 24 de arce poziționate adecvat.

    • a)5
    • b)6
    • c)18
    • d)21
    Vezi rezolvarea

    Răspuns corect: c) 18

    Ca să rămână cât mai multe vârfuri izolate, arcele se pun între cât mai puține vârfuri. Între k vârfuri pot exista cel mult k·(k−1) arce, câte unul în fiecare sens pentru fiecare pereche.

    5 vârfuri permit doar 20 de arce, prea puține, dar 6 vârfuri permit 30, suficient pentru 24. Rămân izolate 24 − 6 = 18 vârfuri.

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 valoarea afișată în urma executării algoritmului dacă se citește numărul 412531.

     citește n
      (număr natural nenul)
     x ← -1; y ← -1
    ┌cât timp n>9 execută
    │┌dacă x=-1 atunci x←n%100
    ││altfel y←n%100
    │└■
    │ n←[n/10]
    └■
    ┌dacă x<y atunci n←(n*100+x)*100+y
    │altfel n←(n*100+y)*100+x
    └■
    scrie n
    Vezi rezolvarea

    Răspunsul din barem: 43141

    La prima trecere prin buclă, x primește ultimele două cifre ale numărului; la fiecare trecere următoare, y primește ultimele două cifre ale valorii curente, deci la final y conține primele două cifre. Bucla se oprește când rămâne prima cifră. Rezultatul alipește prima cifră și cele două perechi, cea mai mică dintre ele înaintea celeilalte. Pentru 412531: x = 31, y = 41, iar n rămâne 4. Cum 31 < 41, n devine (4·100+31)·100+41 = 43141.

  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 din intervalul [1,11110] care pot fi citite pentru variabila n, astfel încât, pentru fiecare dintre acestea, în urma executării algoritmului, să se afișeze valoarea 11111.

    Vezi rezolvarea

    Exemplu: 111 1111

    Rezultatul este prima cifră, urmată de cea mai mică și apoi de cea mai mare dintre perechile x (ultimele două cifre) și y (primele două cifre). Ca să iasă 11111, prima cifră trebuie să fie 1, iar ambele perechi 11. Din intervalul [1,11110], asta se întâmplă pentru 111, 1111 și 11011.

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

    cât timp devine while, iar [n/10] 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 adecvat structura cât timp...execută cu o structură repetitivă cu test final.

    Vezi rezolvarea
    citește n (număr natural nenul)
    x←-1; y←-1
    ┌dacă n>9 atunci
    │┌repetă
    ││┌dacă x=-1 atunci x←n%100
    │││altfel y←n%100
    ││└■
    ││ n←[n/10]
    │└până când n≤9
    └■
    ┌dacă x<y atunci n←(n*100+x)*100+y
    │altfel n←(n*100+y)*100+x
    └■
    scrie n

    repetă…până când execută corpul cel puțin o dată, iar cât timp poate să nu îl execute deloc: pentru un n de o cifră, bucla dată nu se execută. De aceea structura cu test final este pusă sub condiția n>9. Condiția de oprire este negația celei de continuare: n≤9.

  5. Exercițiul 2 6p Backtracking

    Utilizând metoda backtracking, se generează toate buchetele formate din câte trei flori distincte din mulțimea ordonată astfel: {trandafir, crin, gerbera, iris, eustoma, orhidee, zambilă}; în același buchet crinul nu poate fi împreună cu eustoma sau cu zambila. Două buchete diferă prin cel puțin o floare. Primele cinci soluții sunt, în ordinea generării:

    1. (trandafir, crin, gerbera)
    2. (trandafir, crin, iris)
    3. (trandafir, crin, orhidee)
    4. (trandafir, gerbera, iris)
    5. (trandafir, gerbera, eustoma)

    Scrieți două soluții, una generată imediat înainte, iar cealaltă generată imediat după (crin, gerbera, orhidee).

    Vezi rezolvarea

    Răspunsul din barem: (crin, gerbera, iris) (crin, iris, orhidee)

    Buchetele se generează ca submulțimi de trei flori, în ordinea din mulțime, iar crinul nu apare împreună cu eustoma sau zambila. Înainte de (crin, gerbera, orhidee): cu (crin, gerbera) pe primele poziții, floarea de dinaintea orhideei care se poate folosi este irisul, pentru că eustoma nu poate sta cu crinul. După el: după orhidee ar urma zambila, interzisă cu crinul, deci se schimbă a doua floare, gerbera, cu următoarea, irisul, iar a treia devine cea mai mică floare de după el care se poate folosi, orhideea.

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

    Gama muzicală conține, în această ordine, notele do, re, mi, fa, sol, la, si. Două note formează un interval muzical, iar acesta este numit terță dacă, în ordinea din gamă, între cele două note există o singură altă notă muzicală. În notația englezească se folosesc unele litere mari ale alfabetului pentru notele muzicale, astfel: litera A pentru nota la, litera B pentru nota si, apoi, în ordine, litera C pentru nota do, litera D pentru nota re, litera E pentru nota mi, litera F pentru nota fa și litera G pentru nota sol.

    Variabila m, declarată alăturat, memorează literele corespunzătoare notației englezești pentru două note care formează un interval muzical, date în ordinea din gamă.

    Știind că în câmpul nota1 se memorează una dintre literele C, D, E, F sau G, scrieți o secvență de instrucțiuni C/C++ în urma executării căreia să se afișeze pe ecran mesajul TERTA, dacă intervalul respectiv formează o terță, sau mesajul NU, în caz contrar.

    Exemplu: dacă în câmpul nota1 se memorează litera G (pentru nota sol), iar în câmpul nota2 se memorează litera B (pentru nota si), se afișează mesajul TERTA.

    struct interval
    { char nota1;
      char nota2;
    }m;
    Vezi rezolvarea
    if ((m.nota1 <= 'E' && m.nota2 == m.nota1 + 2) || (m.nota1 >= 'F' && m.nota2 == m.nota1 - 5))
        cout << "TERTA";
    else cout << "NU";

    În gamă notele sunt, în ordine, C, D, E, F, G, A, B. O terță sare peste o singură notă. Pentru C, D și E, nota aflată la două poziții după ea este tot în ordinea alfabetului: nota1 + 2 (C→E, D→F, E→G). Pentru F și G, ordinea gamei continuă cu A și B, aflate în alfabet cu 5 poziții înainte: F→A și G→B, adică nota1 − 5.

Subiectul al III-lea

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

    Un număr natural nenul, n, se numește moderat dacă este egal cu produsul a două numere prime, iar acestea sunt consecutive în șirul numerelor prime (2, 3, 5, 7, 11, 13, 17...).

    Subprogramul moderat are un singur parametru, n, prin care primește un număr natural (n∈[1,10^5]). Subprogramul returnează valoarea 1, dacă n este un număr moderat, sau valoarea 0, în caz contrar.

    Scrieți definiția completă a subprogramului.

    Exemplu: dacă n=35, subprogramul returnează 1 (35=5·7), iar dacă n=18 sau n=55 sau n=4, subprogramul returnează 0.

    Vezi rezolvarea
    int moderat(int n)
    {
        int p, q, k, d, prim;
        if (n < 6) return 0;
        p = 2;
        while (n % p != 0) p++;
        q = n / p;
        if (q <= p) return 0;
        for (k = p + 1; k <= q; k++)
        {
            prim = 1;
            for (d = 2; d * d <= k; d++)
                if (k % d == 0) prim = 0;
            if (k == q) return prim;
            if (prim == 1) return 0;
        }
        return 0;
    }

    Cel mai mic divizor p ≥ 2 al lui n este sigur prim. Dacă n este produsul a două numere prime consecutive, p este cel mai mic dintre ele, iar celălalt este q = n/p, mai mare decât p. Se parcurg numerele de la p+1 la q: dacă vreunul dintre ele, înainte de q, este prim, atunci p și q nu sunt consecutive și se returnează 0; când se ajunge la q, rezultatul este 1 exact dacă q este prim. Numerele sub 6 nu pot fi moderate (cel mai mic este 2·3).

  2. Exercițiul 2 10p Tablouri bidimensionale

    O grădină este împărțită în parcele pătrate identice, dispuse pe rânduri succesive. Toate parcelele de pe un rând conțin același tip de plante (doar flori sau doar gazon) și oricare două rânduri alăturate conțin tipuri diferite de plante, pe primul rând fiind gazon. Pentru fiecare parcelă se memorează înălțimea acesteia, egală cu înălțimea medie a plantelor conținute, exprimată în decimetri. Pentru a pune în valoare florile, fiecare parcelă cu flori trebuie să fie mai înaltă cu cel puțin un decimetru decât oricare dintre parcelele cu gazon de pe rândul vecin anterior. S-a hotărât tunderea parcelelor cu gazon prea înalte, astfel încât ele să fie aduse la înălțimea maximă permisă.

    Scrieți un program C/C++ care citește de la tastatură două numere naturale din intervalul [2,10^2], m și n, apoi elementele unui tablou bidimensional cu m linii și n coloane, numere naturale din intervalul [2,10], reprezentând înălțimile parcelelor, în ordinea dispunerii acestora în grădină, rând după rând, și pe fiecare rând de la stânga la dreapta. Programul modifică apoi tabloul în memorie corespunzător situației terenului după tunderea gazonului și afișează pe ecran tabloul obținut, fiecare linie a tabloului pe câte o linie a ecranului, elementele de pe aceeași linie fiind separate prin câte un spațiu.

    Exemplu: pentru m=4, n=6 și tabloul

    Două tablouri cu 4 linii și 6 coloane. Primul: 6 2 3 7 9 4; 7 8 5 9 8 5; 8 7 2 6 2 9; 7 2 5 9 3 8. Din el se obține al doilea: 4 2 3 4 4 4; 7 8 5 9 8 5; 1 1 1 1 1 1; 7 2 5 9 3 8. În ambele, pe prima linie coloanele 1, 4 și 5 și toată linia a treia sunt colorate cu gri; în primul tablou sunt încadrate valorile 5 și 5 de pe linia 2 și valoarea 2 de pe linia 4.
    Vezi rezolvarea
    #include <iostream>
    using namespace std;
    
    int main()
    {
        int m, n, a[100][100], i, j, minim;
        cin >> m >> n;
        for (i = 0; i < m; i++)
            for (j = 0; j < n; j++)
                cin >> a[i][j];
        for (i = 1; i < m; i = i + 2)
        {
            minim = a[i][0];
            for (j = 1; j < n; j++)
                if (a[i][j] < minim) minim = a[i][j];
            for (j = 0; j < n; j++)
                if (a[i - 1][j] > minim - 1) a[i - 1][j] = minim - 1;
        }
        for (i = 0; i < m; i++)
        {
            for (j = 0; j < n; j++)
                cout << a[i][j] << ' ';
            cout << '\n';
        }
        return 0;
    }

    Primul rând (linia 0) are gazon, deci rândurile cu flori sunt liniile 1, 3, 5, … Pentru fiecare astfel de linie i se află înălțimea minimă a florilor. Orice parcelă cu gazon de pe rândul anterior, linia i−1, trebuie să fie cu cel puțin un decimetru mai joasă decât toate florile, deci cel mult minim−1; cele mai înalte se tund exact la această valoare. Dacă ultimul rând are gazon, după el nu mai urmează flori și rămâne neschimbat.

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

    Șirul 0, 0, 1, 4, 13, 38, 105, 280, 729 .... este definit astfel: f₁=f₂=0, f₃=1, fₙ=4∙fₙ₋₁-3∙fₙ₋₂-2∙fₙ₋₃ (unde n este un număr natural n≥4).

    Se citesc de la tastatură trei numere naturale x, y și z (x≤y<z≤10^9), valorile a trei termeni aflați pe poziții consecutive în șirul dat, și se cere să se scrie în fișierul bac.txt, în ordine descrescătoare, separați prin câte un spațiu, toți termenii șirului care sunt mai mici sau egali cu z. Proiectați un algoritm eficient din punctul de vedere al timpului de executare și al spațiului de memorie utilizat.

    Exemplu: dacă se citesc numerele 38 105 280 fișierul conține numerele 280 105 38 13 4 1 0 0

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

    Vezi rezolvarea

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

    Formula termenului general se poate întoarce: dacă a, b, c, d sunt patru termeni consecutivi, d = 4c − 3b − 2a, deci termenul dinaintea lor este a = (4c − 3b − d)/2. Din ultimii trei termeni scriși se obține, așadar, termenul de dinaintea lor.

    Se scriu în fișier z, y și x, în această ordine (descrescătoare). Apoi, repetat, se calculează termenul anterior, (4·y − 3·x − z)/2, se scrie și se mută fereastra: z primește y, y primește x, iar x noul termen. Primii doi termeni ai șirului sunt singurele valori 0, deci algoritmul se oprește după ce au fost scrise două valori 0 (numărând și eventualele zerouri dintre valorile citite).

    Eficiență: fiecare termen se obține în timp constant din cei trei scriși înaintea lui, deci timpul este liniar în numărul de termeni scriși; se păstrează doar trei valori, fără tablou, deci memoria folosită este constantă.

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

    Șirul 0, 0, 1, 4, 13, 38, 105, 280, 729 .... este definit astfel: f₁=f₂=0, f₃=1, fₙ=4∙fₙ₋₁-3∙fₙ₋₂-2∙fₙ₋₃ (unde n este un număr natural n≥4).

    Se citesc de la tastatură trei numere naturale x, y și z (x≤y<z≤10^9), valorile a trei termeni aflați pe poziții consecutive în șirul dat, și se cere să se scrie în fișierul bac.txt, în ordine descrescătoare, separați prin câte un spațiu, toți termenii șirului care sunt mai mici sau egali cu z. Proiectați un algoritm eficient din punctul de vedere al timpului de executare și al spațiului de memorie utilizat.

    Exemplu: dacă se citesc numerele 38 105 280 fișierul conține numerele 280 105 38 13 4 1 0 0

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

    Vezi rezolvarea
    #include <fstream>
    #include <iostream>
    using namespace std;
    
    int main()
    {
        long long x, y, z, crt;
        int zerouri;
        cin >> x >> y >> z;
        ofstream fout("bac.txt");
        fout << z << ' ' << y << ' ' << x;
        zerouri = (y == 0) + (x == 0);
        while (zerouri < 2)
        {
            crt = (4 * y - 3 * x - z) / 2;
            fout << ' ' << crt;
            if (crt == 0) zerouri++;
            z = y;
            y = x;
            x = crt;
        }
        fout.close();
        return 0;
    }

    Programul face pașii de la 3.a. Numărul de zerouri pornește de la cele aflate deja printre valorile citite (de exemplu pentru 0 0 1 nu mai trebuie calculat nimic). Termenii ajung la 10^9, iar 4·y trece de limita tipului int, de aceea se folosește long long.

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?