Sari la conținut

Bac informatică 2022 Simulare, rezolvată

Simularea 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 Simularea din 2022

Simularea din 2022 trece prin expresii logice, recursivitate, backtracking, structuri, grafuri și arbori, matrice, divizibilitate, șiruri de caractere și fișiere. Este o variantă bună pentru exersat atenția la definiții și la cazurile de margine.

Subiectul I (20p): 5 grile: o expresie logică echivalentă cu x<=3 || x>30, un subprogram recursiv care împarte un tablou în jumătăți, o problemă de backtracking cu echipe de patru jucători pe roluri, densitatea primului oraș dintr-un tablou de structuri și numărul de muchii pe care nu îl poate avea un subgraf al grafului complet cu 4 noduri.

Subiectul al II-lea (40p): Un algoritm în pseudocod care taie cifre din fiecare număr citit cât timp are altă paritate decât x, frunzele de pe niveluri impare ale unui arbore dat prin vectorul de „tați” și o secvență care caută „romburi” de flori de același tip într-o matrice cu 3 linii.

Subiectul al III-lea (30p): Un subprogram cu resturi (rest, cea mai mare valoare din [1,n] care dă restul 2 la împărțirea la x și la y), o problemă cu șiruri de caractere care afișează numele invitaților cu prenumele x și o problemă de eficiență care calculează cea mai mare putere a lui 45 care divide 1·2·...·n, scrisă în fișierul bac.txt.

⚠️ La ce să fii atent

  • La I.1: Verifică variantele pe valorile de la margine. Varianta b) se reduce la x<3 || x>30, care este 0 pentru x=3, deși expresia dată este 1.
  • La I.5: Un subgraf nu este un graf parțial! Când ștergi noduri, rămân toate muchiile dintre nodurile păstrate, deci un subgraf al grafului complet cu 4 noduri poate avea doar 6, 3, 1 sau 0 muchii. Valoarea 2 nu se poate obține.
  • La II.2: Rădăcina este nodul 5, singurul cu tatăl 0. Frunzele de pe niveluri impare sunt 3, pe nivelul 1, și 1, 4 și 6, pe nivelul 3. Frunzele 7 și 8 sunt pe nivelul 2, deci nu intră.
  • La III.2: Compară doar prenumele, adică primul cuvânt al fiecărui invitat. În exemplu, la EDANA DAN, DAN este numele, iar DANILA doar începe cu DAN, deci niciunul dintre acești invitați nu se afișează.
  • La III.3: Pentru că 45 = 3²·5, p este cel mai mic dintre jumătatea puterii lui 3 și puterea lui 5 din produs. Produsul nu poate fi calculat pentru n de până la un miliard: puterea lui 3 este [n/3]+[n/9]+[n/27]+..., la fel pentru 5.

Subiectul I

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

    Variabila x este de tip întreg.

    Indicați o expresie care are valoarea 1 dacă și numai dacă expresia C/C++ alăturată are valoarea 1.

    x<=3 || x>30
    • a)!(x<3) && x<30
    • b)!(x>=3 && x<=30)
    • c)!(x<3 || x<=30)
    • d)!(x>3) || !(x<=30)
    Vezi rezolvarea

    Răspuns corect: d) !(x>3) || !(x<=30)

    !(x>3) înseamnă x<=3, iar !(x<=30) înseamnă x>30, deci d) este chiar expresia dată. În a) rămâne x>=3 && x<30; în b) rămâne x<3 || x>30, care e 0 pentru x=3, deși expresia dată e 1; în c) rămâne x>30, care pierde toate valorile mai mici sau egale cu 3.

  2. Exercițiul 2 4p Recursivitate

    Subprogramul f este definit alăturat.

    Știind că variabila x memorează un tablou unidimensional cu elementele (7,1,2,5,4), în această ordine, numerotate de la 0 la 4, indicați valoarea f(0,4,x).

    int f(int st,int dr,int v[])
    { if(st==dr) if(v[st]==st)return 1;
                 else return 0;
      else return f(st,(st+dr)/2,v) + f(1+(st+dr)/2,dr,v);
    }
    • a)2
    • b)3
    • c)4
    • d)5
    Vezi rezolvarea

    Răspuns corect: b) 3

    Subprogramul împarte intervalul în două jumătăți, până ajunge la câte un singur element, și adună câte 1 pentru fiecare poziție pe care valoarea coincide cu indicele. În tabloul (7,1,2,5,4) sunt trei astfel de poziții: v[1]=1, v[2]=2 și v[4]=4, deci rezultatul este 3.

  3. Exercițiul 3 4p Backtracking

    Un sport se desfășoară pe o pistă înghețată, cu o echipă alcătuită din 4 jucători, care sunt, în această ordine, lider, secund, vice-skip și skip. Lotul este format din jucătorii din mulțimea {Alin, Bogdan, Cristian, Răzvan, Ștefan, Valentin}; Cristian poate fi doar lider, Alin și Valentin pot fi doar lider sau secund, Bogdan poate fi doar secund, iar ceilalți doi jucători pot fi doar vice-skip sau skip. Două echipe sunt distincte dacă există cel puțin un rol care, în cele două echipe, este atribuit unor jucători diferiți. Pentru antrenamente, s-au format echipe în toate formulele posibile, primele șase soluții generate fiind, în această ordine: {Alin, Bogdan, Răzvan, Ștefan}, {Alin, Bogdan, Ștefan, Răzvan}, {Alin, Valentin, Răzvan, Ștefan}, {Alin, Valentin, Ștefan, Răzvan}, {Cristian, Alin, Răzvan, Ștefan},{Cristian, Alin, Ștefan, Răzvan}.

    Indicați soluția generată imediat după {Cristian, Valentin, Ștefan, Răzvan}.

    • a){Cristian, Bogdan, Răzvan, Ștefan}
    • b){Cristian, Bogdan, Ștefan, Răzvan}
    • c){Valentin, Alin, Răzvan, Ștefan}
    • d){Valentin, Bogdan, Ștefan, Răzvan}
    Vezi rezolvarea

    Răspuns corect: c) {Valentin, Alin, Răzvan, Ștefan}

    Echipele se formează pe roluri, în ordinea jucătorilor din mulțime. După {Cristian, Valentin, Ștefan, Răzvan} s-au epuizat toate echipele cu liderul Cristian, deci se trece la următorul jucător care poate fi lider — Valentin — iar ca secund se ia primul posibil, Alin; pentru ultimele două roluri, prima variantă este Răzvan, apoi Ștefan.

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

    Variabila oras, declarată alăturat, memorează unele date obținute în urma recensământului populației în 100 dintre orașele țării.

    Știind că densitatea unui oraș este egală cu raportul dintre numărul de locuitori și suprafața acestuia (exprimată în km^2), indicați o expresie a cărei valoare este egală cu densitatea primului oraș.

    struct recensamant
    { char nume[21];
      int nrLocuitori;
      float suprafata;
    }oras[100];
    • a)oras[0].nrLocuitori/oras[0].suprafata
    • b)oras.nrLocuitori[0]/oras.suprafata[0]
    • c)nrLocuitori[0].oras/suprafata[0].oras
    • d)nrLocuitori.oras[0]/suprafata.oras[0]
    Vezi rezolvarea

    Răspuns corect: a) oras[0].nrLocuitori/oras[0].suprafata

    oras este un tablou de înregistrări, deci se alege întâi elementul — oras[0] — și abia apoi câmpul: oras[0].nrLocuitori și oras[0].suprafata. Celelalte trei variante inversează ordinea, punând indicele sau numele tabloului după câmp, ceea ce nu are sens.

  5. Exercițiul 5 4p Grafuri neorientate

    Un graf neorientat complet are 4 noduri.

    Indicați o valoare care NU poate fi numărul de muchii ale unui subgraf al acestui graf.

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

    Răspuns corect: c) 2

    Un subgraf se obține ștergând noduri, împreună cu muchiile care pleacă din ele; muchiile rămase între nodurile păstrate rămân toate. Din graful complet cu 4 noduri se obțin astfel grafuri complete cu 4, 3, 2, 1 sau 0 noduri, adică 6, 3, 1, 0 și 0 muchii. Valoarea 2 nu poate fi obținută.

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

    Scrieți ce se afișează în urma executării algoritmului dacă se citesc, în această ordine, numerele 6, 16, 4273, 1679, 3165, 16, 200, 167.

     citește n,x (numere naturale nenule)
     nr←0; i←1
    ┌cât timp i≤n execută
    │ citește y (număr natural)
    │┌cât timp y≠0 și y%2≠x%2 execută
    ││ y←[y/10]
    │└■
    │┌dacă y=x atunci nr←nr+1
    │└■
    │ i←i+1
    └■
     scrie nr
    Vezi rezolvarea

    Răspunsul din barem: 3

    Pentru fiecare număr citit se taie cifre de la dreapta cât timp numărul rămas are altă paritate decât x, iar la final se compară cu x. Cum x=16 este par: 4273 ajunge 42, diferit de 16; 1679 ajunge 16 și se numără; 3165 ajunge 316, diferit; 16 este deja par și se numără; 200 e par de la început, dar nu e 16; 167 ajunge 16 și se numără. În total, trei numere.

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

    Dacă primele două numere citite sunt, în această ordine, 2 și 22, scrieți o secvență de numere distincte din intervalul [10^3,10^4) care pot fi citite în continuare astfel încât, în urma executării algoritmului, să se afișeze valoarea 2.

    Vezi rezolvarea

    2213 și 2235

    x este 22, deci par: dintr-un număr se taie cifre cât timp ce rămâne este impar. Ca un număr de patru cifre să ajungă la 22, el trebuie să înceapă cu 22, iar ultimele două cifre trebuie să fie impare — altfel tăierea s-ar opri mai devreme, pe un număr par diferit de 22. Cum n este 2, se scriu exact două numere de forma 22xy cu x și y cifre impare, de exemplu 2213 și 2235.

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

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

    Vezi rezolvarea
    #include <iostream>
    using namespace std;
    
    int main()
    {
        int n, x, y, nr = 0, i = 1;
        cin >> n >> x;
        while (i <= n)
        {
            cin >> y;
            while (y != 0 && y % 2 != x % 2)
                y = y / 10;
            if (y == x) nr = nr + 1;
            i = i + 1;
        }
        cout << nr;
        return 0;
    }
  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 [a] partea întreagă a numărului real a.

    Scrieți în pseudocod un algoritm, echivalent cu cel dat, înlocuind adecvat prima structură cât timp...execută cu o structură repetitivă de tip pentru...execută.

    Vezi rezolvarea
    citește n,x (numere naturale nenule)
     nr←0
    ┌pentru i←1,n execută
    │ citește y (număr natural)
    │┌cât timp y≠0 și y%2≠x%2 execută
    ││ y←[y/10]
    │└■
    │┌dacă y=x atunci nr←nr+1
    │└■
    └■
     scrie nr

    Structura pentru ține singură contorul: îl pornește de la 1, îl compară cu n și îl crește la fiecare pas. De aceea i←1 dinaintea buclei și i←i+1 din corpul ei dispar, iar restul algoritmului rămâne neschimbat.

  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 rădăcină are 10 noduri și este reprezentat prin vectorul de „tați” (10,5,5,10,0,10,9,2,5,2). Enumerați trei dintre frunzele situate în arbore pe niveluri impare.

    Vezi rezolvarea

    1, 3 și 4

    Rădăcina este nodul 5, fiindcă are tatăl 0. Fiii lui sunt 2, 3 și 9, deci ei sunt pe nivelul 1; pe nivelul 2 se află 8 și 10 (fiii lui 2) și 7 (fiul lui 9); pe nivelul 3 se află 1, 4 și 6, fiii lui 10. Frunzele — nodurile care nu apar în vectorul de „tați" — sunt 3, 8, 7, 1, 4 și 6, iar dintre ele pe niveluri impare stau 3 (nivelul 1) și 1, 4, 6 (nivelul 3). Oricare trei dintre acestea sunt un răspuns bun.

  6. Exercițiul 3 6p Tablouri bidimensionale

    Într-o seră se folosesc vase pătrate, care conțin câte o singură floare (lalea, frezie sau narcisă). Vasele sunt așezate pe trei rânduri și sunt aliniate ca în exemplu. Patru flori de același tip formează un romb dacă vasele în care se află sunt dispuse în jurul unui alt vas, cu care fiecare are în comun câte o latură. Variabilele j și ok sunt întregi, iar variabila a este un tablou bidimensional cu 3 linii și 15 coloane, cu elemente de tip char, în care fiecare linie, în ordine, memorează succesiunea de flori aflate pe un rând al serei, notându-se cu L lalelele, cu F freziile și cu N narcisele. Fiecare linie a tabloului corespunde, în ordine, unui rând de vase din seră. Liniile și coloanele sunt numerotate începând de la 0.

    Scrieți secvența C/C++ de mai jos, înlocuind punctele de suspensie astfel încât, în urma executării secvenței obținute, variabila ok să aibă valoarea 1 dacă florile formează cel puțin un romb, sau valoarea 0 în caz contrar.

    Exemplu: în urma executării secvenței pentru tabloul de mai jos, ok=1 (sunt evidențiate 4 romburi).

    ok=........;
    for(j=.....;j<.....;j++)
        ..................
    Figura din enunț
    Vezi rezolvarea
    ok = 0;
    for (j = 1; j < 14; j++)
        if (a[0][j] == a[1][j - 1] && a[1][j - 1] == a[1][j + 1] && a[1][j + 1] == a[2][j])
            ok = 1;

    Un romb are în mijloc vasul de pe linia 1, iar cele patru flori din jurul lui sunt deasupra — a[0][j] —, dedesubt — a[2][j] — și în stânga și în dreapta, pe aceeași linie: a[1][j-1] și a[1][j+1]. Toate patru trebuie să fie de același fel. Coloana centrului merge de la 1 la 13, ca vecinii din stânga și din dreapta să existe. La prima potrivire ok devine 1 și rămâne așa.

Subiectul al III-lea

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

    Subprogramul rest are patru parametri:

    • x, y și n, prin care primește câte un număr natural din intervalul [1,10^6], x<y<n;

    • k, prin care furnizează cea mai mare valoare naturală din intervalul [1,n] pentru care atât restul împărțirii la x, cât și restul împărțirii la y, sunt egale cu 2, sau 0 dacă nu există o astfel de valoare.

    Scrieți definiția completă a subprogramului.

    Exemplu: pentru x=10, y=101 și n=3000, subprogramul returnează numărul 2022 (pentru numerele 2, 1012 și 2022 atât restul împărțirii la 10, cât și restul împărțirii la 101, este 2).

    Vezi rezolvarea
    void rest(int x, int y, int n, int &k)
    {
        for (k = n; k >= 1; k--)
            if (k % x == 2 && k % y == 2) return;
        k = 0;
    }

    Se cere cea mai mare valoare potrivită, deci căutarea pornește de la n și coboară: primul număr găsit este chiar răspunsul, iar subprogramul se oprește acolo. Dacă bucla se termină fără să găsească ceva, k rămâne 0, adică exact valoarea cerută în acest caz. Parametrul k e transmis prin referință, fiindcă prin el se furnizează rezultatul.

  2. Exercițiul 2 10p Șiruri de caractere

    Un text, de cel mult 250 de caractere, reprezintă o listă cu date de identificare ale invitaților la o petrecere; fiecare invitat are un prenume și un nume, care apar în listă în această ordine, urmate de simbolul ; (punct și virgulă), ca în exemplu. Numele și prenumele sunt formate din câte un singur cuvânt, compus din litere mari ale alfabetului englez, și sunt separate printr-un spațiu.

    Scrieți un program C/C++ care citește de la tastatură un text de tipul precizat mai sus apoi, de pe rândul următor, un cuvânt, x, și afișează pe ecran, separate prin câte un spațiu, numele tuturor invitaților care au prenumele x, ca în exemplu, sau mesajul NU dacă nu există astfel de invitați.

    Exemplu: dacă lista este DAN MARIS; DANILA PREPELEAC; DAN POPA; EDANA DAN; și cuvântul x este DAN se afișează pe ecran MARIS POPA

    Vezi rezolvarea
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    char s[251], x[251];
    
    int main()
    {
        cin.getline(s, 251);
        cin >> x;
        int gasit = 0;
        for (char *p = strtok(s, ";"); p != NULL; p = strtok(NULL, ";"))
        {
            while (*p == ' ') p++;              // spațiul de după punct și virgulă
            char *sp = strchr(p, ' ');
            if (sp == NULL) continue;
            *sp = '\0';                        // p rămâne prenumele, sp+1 este numele
            if (strcmp(p, x) == 0)
            {
                if (gasit) cout << ' ';
                cout << sp + 1;
                gasit = 1;
            }
        }
        if (gasit == 0) cout << "NU";
        return 0;
    }

    Lista se taie în invitați după ;, iar fiecare invitat se taie la primul spațiu: în stânga rămâne prenumele, în dreapta numele. Prenumele se compară cu x, iar numele celor care se potrivesc se scriu unul după altul, separate prin câte un spațiu. Dacă nu s-a scris nimic până la sfârșit, se afișează NU.

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

    Se citește de la tastatură un număr natural, n (n∈[1,10^9]), și se cere să se scrie în fișierul text bac.txt cel mai mare număr natural p cu proprietatea că numărul 45^p este divizor al numărului obținut prin evaluarea produsului 1∙2∙3∙...∙n.

    Proiectați un algoritm eficient din punctul de vedere al timpului de executare și al memoriei utilizate.

    Exemplu: dacă n=14, fișierul conține numărul 2 (45^2=2025 este divizor al lui 1∙2∙3∙..∙14=87178291200)

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

    Vezi rezolvarea

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

    45 = 3²·5, deci 45^p înseamnă 3^2p·5^p. Numărul p căutat este cel mai mare pentru care produsul 1·2·…·n se împarte la 3^2p și la 5^p, adică p este cea mai mică dintre valorile [e₃/2] și e₅, unde e₃ și e₅ sunt puterile lui 3, respectiv ale lui 5, din descompunerea produsului.

    Puterea unui număr prim d în produsul 1·2·…·n se obține fără a calcula produsul: dintre numerele de la 1 la n, [n/d] se împart la d, [n/d²] se împart încă o dată la d și așa mai departe, deci e_d = [n/d] + [n/d²] + [n/d³] + … Suma are termeni doar cât timp puterea lui d nu depășește n.

    Numărul de termeni este deci logaritmic în raport cu n — pentru n de ordinul unui miliard, sub douăzeci de împărțiri pentru fiecare dintre cele două numere prime — iar memoria folosită este constantă: doar câteva variabile. Produsul propriu-zis nu se calculează niciodată, fiindcă ar depăși orice tip de date.

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

    Se citește de la tastatură un număr natural, n (n∈[1,10^9]), și se cere să se scrie în fișierul text bac.txt cel mai mare număr natural p cu proprietatea că numărul 45^p este divizor al numărului obținut prin evaluarea produsului 1∙2∙3∙...∙n.

    Proiectați un algoritm eficient din punctul de vedere al timpului de executare și al memoriei utilizate.

    Exemplu: dacă n=14, fișierul conține numărul 2 (45^2=2025 este divizor al lui 1∙2∙3∙..∙14=87178291200)

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

    Vezi rezolvarea
    #include <fstream>
    #include <iostream>
    using namespace std;
    
    // Puterea numărului prim d în produsul 1·2·…·n.
    long long putere(long long n, long long d)
    {
        long long e = 0, p = d;
        while (p <= n)
        {
            e = e + n / p;
            if (p > n / d) break;   // altfel p*d ar depăși domeniul
            p = p * d;
        }
        return e;
    }
    
    int main()
    {
        long long n;
        cin >> n;
        long long e3 = putere(n, 3) / 2, e5 = putere(n, 5);
        long long p = e3 < e5 ? e3 : e5;
        ofstream g("bac.txt");
        g << p;
        g.close();
        return 0;
    }

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?