Subiect și barem BAC 2021 Informatică C/C++ (mate-info)
2021
Model oficial
Rezolvare explicată

Rezolvare BAC 2021 Informatică C/C++ (mate-info) — Model oficial, pas cu pas

Subiectul și baremul sunt documentele oficiale ale Ministerului Educației; rezolvarea de mai jos este explicația echipei MeditatiiDirect.ro, cu punctajul din barem pentru fiecare cerință.

Rezolvarea completă a modelului de subiect pentru Bacalaureat 2021 la Informatică, limbajul C/C++, profil mate-info. Pentru fiecare item ai răspunsul, raționamentul pas cu pas, codul C++ complet și punctajul din baremul oficial.

Sfat: încearcă întâi singur fiecare cerință, apoi verifică aici. La programe, baremul punctează orice soluție corectă — nu trebuie să scrii exact codul de mai jos.

Subiectul I (20 de puncte)

Răspunsuri: 1 – c, 2 – a, 3 – d, 4 – b, 5 – c (câte 4 puncte).

1. Valoarea expresiei 21/2*2-5 → c. 15

Împărțire întreagă, evaluare de la stânga la dreapta: 21/2 = 10, 10*2 = 20, 20-5 = 15.

2. Afișarea datei → a. cout<<x.zi<<" "<<x.luna<<" "<<x.an;

Câmpurile se accesează cu variabilă.câmp: x.zi, x.luna, x.an. Variantele b (ordine inversată), c (sintaxă inexistentă) și d (folosește numele tipului data) sunt greșite.

3. Valoarea f(3,1) → d. −9

Parametrul x este transmis prin valoare, deci fiecare apel are propria copie.

  • f(3,1): x = 2 → returnează f(2,2) - 2
  • f(2,2): x = 3 → returnează f(1,3) - 3
  • f(1,3): x = 4 → returnează f(0,4) - 4 = 0 − 4 = −4

Revenind: f(2,2) = −4 − 3 = −7, iar f(3,1) = −7 − 2 = −9.

4. Numărul maxim de frunze → b. 4

Gradele nodurilor: 1 → 3, 3 → 3, 4 → 2, 5 → 2, iar 2, 6, 7, 8 au gradul 1. Frunzele sunt nodurile de grad 1, cu excepția rădăcinii. Alegând drept rădăcină un nod de grad mai mare (de exemplu 1), toate cele 4 noduri de grad 1 sunt frunze → maximul este 4.

5. Muchii eliminate pentru a obține un arbore → c. 190

Graful complet cu 21 de noduri are 21⋅20/2=21021 \cdot 20 / 2 = 210 muchii. Un graf parțial conex și fără cicluri este un arbore, cu 21 − 1 = 20 de muchii. Se elimină 210−20=210 - 20 = 190 muchii.

Subiectul al II-lea (40 de puncte)

1. Algoritmul în pseudocod

La fiecare pas se uită la ultima cifră a lui n și o elimină. Dacă acea cifră era impară, cifra următoare (noua ultimă cifră) se adaugă în stânga lui nr; dacă era pară, k scade. Se oprește când n devine 0 sau k devine 0.

a) Pentru 3845267 și 3 → 46

cifra eliminatăparitaten dupăacțiunenrk
7impară384526adaugă 663
6pară38452k−162
2pară3845k−161
5impară384adaugă 4461
4pară38k−1460

k = 0, bucla se oprește → se afișează 46. (6p)

b) k = 2, n cu 4 cifre, se afișează 20

Numere de forma 2x0y‾\overline{2x0y} cu x, y impare. De exemplu, pentru 2105: 5 impar → se adaugă 0 (nr = 0); 0 par → k = 1; 1 impar → se adaugă 2 (nr = 20); 2 par → k = 0, stop. Alte exemple: 2301, 2907. (6p)

c) Programul C/C++ (10p)

cppcod
#include <iostream>
using namespace std;

int main()
{
    int n, k, p = 1, nr, c;
    cin >> n >> k;
    if (k == 0) nr = -1;
    else
    {
        nr = 0;
        do
        {
            c = n % 2; n = n / 10;
            if (c != 0)
            {
                nr = nr + (n % 10) * p;
                p = p * 10;
            }
            else k = k - 1;
        } while (n != 0 && k != 0);
    }
    cout << nr;
    return 0;
}

„până când n=0 sau k=0” devine while (n != 0 && k != 0) (negația, cu De Morgan).

d) Structura „repetă” înlocuită cu una cu test inițial (6p)

Pe ramura „altfel”, k ≠ 0. Dacă și n ≠ 0, prima iterație se execută oricum; dacă n = 0, bucla „repetă” ar face un singur pas care nu modifică nr (doar k), deci rezultatul afișat este același. Putem folosi direct testul inițial n ≠ 0 și k ≠ 0.

textcod
citește n, k (numere naturale)
p ← 1
┌dacă k = 0 atunci
│  nr ← −1
│altfel
│  nr ← 0
│ ┌cât timp n ≠ 0 și k ≠ 0 execută
│ │  c ← n%2; n ← [n/10]
│ │ ┌dacă c ≠ 0 atunci
│ │ │  nr ← nr + (n%10)*p; p ← p*10
│ │ │altfel
│ │ │  k ← k − 1
│ │ └■
│ └■
└■
scrie nr

2. Ultimele trei numere generate cu prima cifră 4 (6p)

Un număr de 5 cifre strict crescătoare care începe cu 4 folosește alte 4 cifre din {5, 6, 7, 8, 9}. Sunt 5 astfel de numere, în ordinea generării: 45678, 45679, 45689, 45789, 46789. Ultimele trei: 45689, 45789, 46789.

3. Ce se afișează → OAIAE (6p)

k = 'a' - 'A' = 32, deci s[i] - k transformă o literă mică în majusculă. Șirul se parcurge de la dreapta la stânga, iar vocalele mici se transformă și se afișează: din „A realizat tot” obținem, în ordine inversă, o, a, i, a, e → OAIAE. Primul „A” este deja majusculă, deci strchr("aeiou", 'A') îl ignoră.

Subiectul al III-lea (30 de puncte)

1. Subprogramul prime (10p)

Căutăm de la n − 1 în jos primul număr prim (acesta este y), apoi continuăm în jos până la următorul (acesta este x).

cppcod
int estePrim(int a)
{
    if (a < 2) return 0;
    for (int d = 2; d * d <= a; d++)
        if (a % d == 0) return 0;
    return 1;
}

void prime(int n, int &x, int &y)
{
    y = n - 1;
    while (!estePrim(y)) y--;
    x = y - 1;
    while (!estePrim(x)) x--;
}

Exemplu: n = 49 → y = 47, x = 43 ✔. Cum n ≥ 4, există mereu primele 2 și 3 sub n.

2. Tablou cu pătrate perfecte pare descrescătoare (10p)

Pătratele perfecte pare sunt (2t)2(2t)^2: 0, 4, 16, 36, … Primele m·n sunt pentru t = 0 … m·n − 1, iar în ordine descrescătoare începem cu t = m·n − 1.

cppcod
#include <iostream>
using namespace std;

int a[105][105];

int main()
{
    int m, n;
    cin >> m >> n;
    int t = m * n - 1;
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
        {
            a[i][j] = (2 * t) * (2 * t);
            t--;
        }
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++) cout << a[i][j] << ' ';
        cout << '\n';
    }
    return 0;
}

Pentru m = 2, n = 3 → 100 64 36 / 16 4 0 ✔. Valoarea maximă este (2⋅9999)2≈4⋅108(2 \cdot 9999)^2 \approx 4 \cdot 10^8, încape în int.

3. Suma maximă pe tip de produs

a) Descrierea algoritmului (2p)

Tipurile sunt numere din [1, 100], deci folosim un tablou s, unde s[t] = suma cheltuită pentru tipul t. Pentru fiecare linie (t, nr, pret) citită, adăugăm nr*pret la s[t]. La final determinăm maximul din s și numărăm de câte ori apare.

Eficiență: o singură parcurgere a fișierului → timp liniar în numărul de linii, plus o parcurgere a celor 100 de tipuri.

b) Programul C/C++ (8p)

cppcod
#include <fstream>
#include <iostream>
using namespace std;

int main()
{
    ifstream f("cheltuieli.in");
    long long s[101] = {0}, mx = 0;
    int t, nr, pret, cnt = 0;
    while (f >> t >> nr >> pret)
        s[t] += nr * pret;
    for (int i = 1; i <= 100; i++)
        if (s[i] > mx) { mx = s[i]; cnt = 1; }
        else if (s[i] == mx && mx > 0) cnt++;
    cout << mx << ' ' << cnt;
    f.close();
    return 0;
}

Verificare pe exemplu: s[4] = 10 + 16 = 26, s[1] = 16 + 10 = 26, s[2] = 5 → se afișează 26 2 ✔. Suma poate ajunge la 106⋅10410^6 \cdot 10^4, de aceea am folosit long long.

Ce merită reținut din model

  • Parametri prin valoare: fiecare apel recursiv are propria copie a lui x.
  • Frunze într-un arbore cu rădăcină: nodurile de grad 1, cu excepția rădăcinii.
  • Arbore parțial al lui KnK_n: se păstrează n − 1 muchii din n(n−1)/2n(n-1)/2.
  • Litere mici → mari: se scade 'a' - 'A' (32).
  • Sume pe categorii: tablou indexat după categorie, completat pe măsura citirii.

Vrei să iei nota pe care ți-o dorești la BAC 2021?

Ai lucrat subiectul de Informatică C/C++ (mate-info)? Pe MeditatiiDirect.ro îl poți relua cu un profesor sau cu Profesorul AI, exact pe punctele unde ai pierdut puncte la barem.

Alte subiecte BAC Informatică C/C++ (mate-info) rezolvate