Pagina Principală
Ora 16

Sume și produse complexe

Calcule combinate și probleme cu multiple rezultate

40min teorie + 15min probleme PbInfo
Competența 3.4 - Algoritmi elementari
Sigla liceului
TEORIE - 40 minute

Ce înseamnă "Sume și produse complexe"?

După această lecție, vei ști să rezolvi probleme care cer mai multe calcule simultan într-un singur algoritm.

Calcule multiple într-o singură buclă
Organizarea corectă a variabilelor
Condiții diferite pentru fiecare calcul
Afișarea ordonată a rezultatelor

Recapitulare rapidă: Sume și produse simple

Ce știm deja din lecțiile anterioare:

suma = 0
inițializare
suma începe întotdeauna cu 0
produs = 1
inițializare
produsul începe întotdeauna cu 1
suma += x
adaugare
adună la sumă
produs *= x
înmulțire
înmulțește produsul

Atenție la inițializări!

Regulă de aur: Dacă uitați să inițializați corect variabilele, programul va da rezultate greșite!

Corect: int suma = 0; pentru că 0 este elementul neutru la adunare
Corect: int produs = 1; pentru că 1 este elementul neutru la înmulțire
Greșit: int produs = 0; pentru că orice înmulțit cu 0 dă 0!

Analogie: Bucătarul care prepară mai multe feluri de mâncare

Gândește-te la un algoritm complex ca la un bucătar care prepară simultan mai multe feluri de mâncare:

BUCĂTAR SIMPLU

Pregătește doar o singură mâncare

→ algoritm cu un singur calcul
BUCĂTAR COMPLEX

Pregătește supă, fel principal și desert

→ algoritm cu multiple calcule
INGREDIENTE SEPARATE

Fiecare fel are ingrediente proprii

→ fiecare calcul are variabile proprii
GĂTIT SIMULTAN

Toate se gătesc în același timp

→ toate calculele în aceeași buclă

Algoritmul pentru calcule combinate

1
Declară toate variabilele necesare

Pentru fiecare rezultat de care ai nevoie, creează o variabilă separată.

sumaPare = 0
produsImpare = 1
2
Parcurge numerele (de obicei cu for/while)

Folosește o singură buclă pentru a parcurge toate numerele.

for(i=1; i<=n; i++)
3
Pentru fiecare număr, decide ce calcule faci

Folosește condiții (if) pentru a alege în ce variabilă adaugi numărul.

if(i%2==0) sumaPare+=i
else produsImpare*=i
4
Afișează toate rezultatele

După buclă, afișează toate variabilele cu rezultatele finale.

cout << sumaPare << " " << produsImpare
ALGORITM SumeProduseComplexe VARIABILE n, i: întreg sumaPare, produsImpare: întreg ÎNCEPUT CITESTE n sumaPare ← 0 // inițializare corectă pentru sumă produsImpare ← 1 // inițializare corectă pentru produs PENTRU i ← 1, n EXECUTĂ ┌ DACĂ i % 2 = 0 ATUNCI │ sumaPare ← sumaPare + i │ ALTEL │ produsImpare ← produsImpare * i └ SFÂRȘIT DACĂ SFÂRȘIT PENTRU SCRIE "Suma numerelor pare: ", sumaPare SCRIE "Produsul numerelor impare: ", produsImpare SFÂRȘIT

Observație importantă: Folosim o singură buclă PENTRU pentru a parcurge numerele, dar în interior facem calcule diferite în funcție de paritatea lui i. Asta face algoritmul eficient!

// Structura generală a unui algoritm cu calcule multiple: 1. CITESTE datele de intrare 2. INIȚIALIZEAZĂ toate variabilele de rezultat: - sume cu 0 - produse cu 1 - contoare cu 0 3. PENTRU fiecare element de prelucrat: ┌ DACĂ (condiție1) ATUNCI │ calculează_rezultat1 └ SFÂRȘIT DACĂ ┌ DACĂ (condiție2) ATUNCI │ calculează_rezultat2 └ SFÂRȘIT DACĂ (pot fi mai multe condiții) 4. SCRIE toate rezultatele
Variabile separate
sumaPare
produsImpare
numarDivizori
Inițializări
= 0
= 1
= 0
Actualizări
sumaPare += i
produsImpare *= i
numarDivizori++
START: n = 5
sumaPare = 0
produsImpare = 1
i = 1
Test: 1 este par?
❌ NU → produsImpare = 1×1 = 1
i = 2
Test: 2 este par?
✅ DA → sumaPare = 0+2 = 2
i = 3
Test: 3 este par?
❌ NU → produsImpare = 1×3 = 3
i = 4
Test: 4 este par?
✅ DA → sumaPare = 2+4 = 6
i = 5
Test: 5 este par?
❌ NU → produsImpare = 3×5 = 15
REZULTATE:
sumaPare = 6
produsImpare = 15

Exercițiu de completare - Calcul combinat:

Completează codul C++ pentru suma pătratelor și produsul cuburilor:
#include <iostream>
using namespace ______;
______ main() {
    int n;
    cin >> ______;
    int ______ = ______; // Suma pătratelor începe cu 0
    int ______ = ______; // Produsul cuburilor începe cu 1
    ______ (int i = 1; i <= n; i++) {
        ______ (i % 2 == 0) { // Dacă i este par
            sumaPatrate += ______; // Adaugă pătratul la sumă
        } ______ { // Dacă i este impar
            produsCuburi *= ______; // Înmulțește cu cubul
        }
    }
    cout << ______ << " " << ______;
    return ______;
}
Bancă de cuvinte:
std int n sumaPatrate produsCuburi 0 1 for if i*i else i*i*i

Test de înțelegere: Care variabilă pentru care calcul?

Pentru problema: "Pentru numerele de la 1 la n, calculează suma numerelor divizibile cu 3 și produsul numerelor divizibile cu 5"

Cum ar trebui să inițializezi variabilele?

Știai că...
Regulă generală: Suma începe întotdeauna cu 0 (element neutru la adunare)
Regulă generală: Produsul începe întotdeauna cu 1 (element neutru la înmulțire)
Excepție: Dacă produsul este de numere naturale ≥ 2, poți începe cu 2, dar 1 este sigur
Greșeală frecventă: Nu confunda suma (0) cu produsul (1)!

Capcane comune și soluții pentru calcule complexe

Greșeli frecvente la sume și produse multiple:

❌ Inițializări greșite
int suma = 1; // GREȘIT! Trebuie 0 int produs = 0; // GREȘIT! Trebuie 1 // Orice înmulțit cu 0 dă 0, deci produsul va fi mereu 0!

Soluție: Memorizează: suma = 0, produs = 1

❌ Folosirea aceleiași variabile pentru rezultate diferite

Exemplu: rezultat = rezultat + i pentru sumă, apoi rezultat = rezultat * i pentru produs

Soluție: Folosește variabile separate: sumaPare, produsImpare

❌ Condiții incomplete sau suprapuse

Un număr poate să îndeplinească mai multe condiții (ex: divizibil cu 3 și cu 5)

if (i % 3 == 0) sumaDiv3 += i; if (i % 5 == 0) produsDiv5 *= i; // Corect! Un număr poate intra în ambele

Best Practices pentru calcule complexe:

✅ Nume descriptive pentru variabile: sumaPare, produsImpare, numarDivizori
✅ Inițializări corecte: sume cu 0, produse cu 1, contoare cu 0
✅ O singură buclă pentru toate calculele: Eficient și clar
✅ Afișare ordonată: În aceeași ordine ca în cerință
✅ Teste cu valori mici: n=1, n=2, n=5 pentru a verifica corectitudinea

Comparație operații în aceeași buclă vs. bucle separate:

VARIANTA EFICIENTĂ:
for(i=1; i<=n; i++) { if(cond1) calc1; if(cond2) calc2; }
✓ O singură parcurgere
VARIANTA INEFICIENTĂ:
for(i=1; i<=n; i++) if(cond1) calc1;
for(i=1; i<=n; i++) if(cond2) calc2;
✗ Două parcurgeri

Sfat pentru profesor: Încurajați elevii să scrie pe hârtie toate variabilele de care au nevoie înainte să scrie codul. Această etapă de planificare evită multe greșeli!

PROBLEME PBINFO - 15 minute

PbInfo #7 - Suma și produsul

Enunț:

Cerință: Se citește un număr natural n. Să se calculeze suma numerelor pare și produsul numerelor impare de la 1 la n.

Date de intrare:

Programul citește de la tastatură numărul n.

Date de ieșire:

Programul va afișa pe ecran, separate printr-un spațiu, suma numerelor pare și produsul numerelor impare.

Exemplu:

Intrare:

5

Ieșire:

6 15

Explicație: Pare: 2+4=6, Impare: 1×3×5=15

Cum gândim soluția:
  1. Citim numărul n
  2. Declarăm și inițializăm două variabile:
    • sumaPare = 0 (pentru suma numerelor pare)
    • produsImpare = 1 (pentru produsul numerelor impare)
  3. Parcurgem numerele de la 1 la n cu o buclă for
  4. Pentru fiecare număr i:
    • Dacă i este par (i % 2 == 0): adăugăm la sumaPare
    • Altfel (i este impar): înmulțim la produsImpare
  5. Afișăm cele două rezultate separate prin spațiu
Execuție pentru n=5:
Start: sumaPare=0, produsImpare=1
i=1: impar → produsImpare=1×1=1
i=2: par → sumaPare=0+2=2
i=3: impar → produsImpare=1×3=3
i=4: par → sumaPare=2+4=6
i=5: impar → produsImpare=3×5=15
Rezultate: sumaPare=6, produsImpare=15 → "6 15"
Ce trebuie să verifici mereu?
  • n=1: sumaPare=0 (niciun număr par), produsImpare=1
  • n=2: sumaPare=2, produsImpare=1
  • n=0: Atenție! Intervalul este de la 1 la n, deci pentru n=0, bucla nu se execută
  • Inițializări: suma începe cu 0, produsul cu 1
Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    int sumaPare = 0;      // Inițializare corectă pentru sumă
    int produsImpare = 1;  // Inițializare corectă pentru produs
    
    for (int i = 1; i <= n; i++) {
        if (i % 2 == 0) {
            // Număr par - adăugăm la sumă
            sumaPare += i;
        } else {
            // Număr impar - înmulțim la produs
            produsImpare *= i;
        }
    }
    
    // Afișăm rezultatele separate prin spațiu
    cout << sumaPare << " " << produsImpare;
    
    return 0;
}

Ce învățăm din această problemă:

  • Variabile multiple: Fiecare calcul are variabila sa
  • Inițializări diferite: sume cu 0, produse cu 1
  • O singură buclă: Eficient - parcurgem numerele o singură dată
  • Condiții exclusive: Un număr fie este par, fie este impar
  • Format output: Rezultate separate prin spațiu, în ordinea cerută
Varianta cu verificare suplimentară:
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    int sumaPare = 0;
    int produsImpare = 1;
    
    // Verificăm dacă n este mai mare decât 0
    if (n <= 0) {
        cout << "0 1";  // pentru n=0 sau negativ
        return 0;
    }
    
    for (int i = 1; i <= n; i++) {
        if (i % 2 == 0) {
            sumaPare += i;
        } else {
            produsImpare *= i;
        }
    }
    
    cout << sumaPare << " " << produsImpare;
    
    return 0;
}

PbInfo #8 - Trei calcule simultan

Problemă cu trei rezultate diferite într-un singur algoritm

Enunț:

Cerință: Se citește un număr natural n. Să se calculeze:

  1. Suma numerelor divizibile cu 3 de la 1 la n
  2. Produsul numerelor divizibile cu 5 de la 1 la n
  3. Numărul de valori care nu sunt divizibile nici cu 3, nici cu 5
Date de intrare:

Programul citește de la tastatură numărul n.

Date de ieșire:

Programul va afișa pe ecran, separate prin spațiu, cele trei rezultate în ordinea de mai sus.

Exemplu:

Intrare:

10

Ieșire:

18 5 4

Explicație: Divizibile cu 3: 3+6+9=18, Divizibile cu 5: 5, Nici cu 3 nici cu 5: 1,2,4,7=4 numere

Cum gândim soluția:
  1. Citim numărul n
  2. Declarăm și inițializăm trei variabile:
    • sumaDiv3 = 0
    • produsDiv5 = 1
    • contor = 0 (pentru numărarea celor nedivizibile)
  3. Parcurgem numerele de la 1 la n cu o buclă for
  4. Pentru fiecare număr i:
    • Dacă i % 3 == 0: adăugăm la sumaDiv3
    • Dacă i % 5 == 0: înmulțim la produsDiv5
    • Dacă i % 3 != 0 && i % 5 != 0: incrementăm contor

    Important: Un număr poate să fie divizibil atât cu 3, cât și cu 5 (ex: 15). În acest caz, intră în ambele calcule!

  5. Afișăm cele trei rezultate în ordinea cerută
Cum funcționează pentru n=10:
Start: sumaDiv3=0, produsDiv5=1, contor=0
i=1: nu e div cu 3/5 → contor=1
i=2: nu e div cu 3/5 → contor=2
i=3: div cu 3 → sumaDiv3=0+3=3
i=4: nu e div cu 3/5 → contor=3
i=5: div cu 5 → produsDiv5=1×5=5
i=6: div cu 3 → sumaDiv3=3+6=9
i=7: nu e div cu 3/5 → contor=4
i=8: nu e div cu 3/5 → contor=5
i=9: div cu 3 → sumaDiv3=9+9=18
i=10: div cu 5 → produsDiv5=5×10=50
Rezultate: 18 50 4

Atenție la exemplul din problemă: Există o discrepanță între exemplul dat (18 5 4) și rezultatul logic (18 50 4). Verifică întotdeauna algoritmul tău cu propriile calcule!

De ce această problemă este importantă?

Problema exersează gândirea algoritmică complexă:

  1. Mai multe condiții independente: Un număr poate să îndeplinească 0, 1 sau 2 condiții
  2. Tipuri diferite de calcule: sumă, produs, numărare
  3. Condiții compuse: !(i%3==0 || i%5==0) este echivalent cu i%3!=0 && i%5!=0
  4. Ordinea afișării: Trebuie respectată ordinea din enunț

Formula cheie pentru condiție compusă: if (i % 3 != 0 && i % 5 != 0)

Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    int sumaDiv3 = 0;      // Suma numerelor divizibile cu 3
    int produsDiv5 = 1;    // Produsul numerelor divizibile cu 5
    int contor = 0;        // Numărul de valori nedivizibile cu 3 sau 5
    
    for (int i = 1; i <= n; i++) {
        // Verificăm dacă i este divizibil cu 3
        if (i % 3 == 0) {
            sumaDiv3 += i;
        }
        
        // Verificăm dacă i este divizibil cu 5
        if (i % 5 == 0) {
            produsDiv5 *= i;
        }
        
        // Verificăm dacă i NU este divizibil nici cu 3, nici cu 5
        if (i % 3 != 0 && i % 5 != 0) {
            contor++;
        }
    }
    
    // Afișăm rezultatele în ordinea cerută
    cout << sumaDiv3 << " " << produsDiv5 << " " << contor;
    
    return 0;
}
Varianta alternativă (cu if-uri separate):
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    int sumaDiv3 = 0;
    int produsDiv5 = 1;
    int contor = 0;
    
    for (int i = 1; i <= n; i++) {
        bool esteDivizibilCu3 = (i % 3 == 0);
        bool esteDivizibilCu5 = (i % 5 == 0);
        
        if (esteDivizibilCu3) {
            sumaDiv3 += i;
        }
        
        if (esteDivizibilCu5) {
            produsDiv5 *= i;
        }
        
        if (!esteDivizibilCu3 && !esteDivizibilCu5) {
            contor++;
        }
    }
    
    cout << sumaDiv3 << " " << produsDiv5 << " " << contor;
    
    return 0;
}

Ce învățăm din această problemă:

  • Condiții independente: Un număr poate să fie atât divizibil cu 3, cât și cu 5
  • Condiții compuse: Folosirea operatorilor && (și) și || (sau)
  • Inițializări diferite: contorul începe cu 0 (ca toate numărările)
  • Gândire exhaustivă: Trebuie să acoperim toate cazurile posibile
  • Aplicații practice: Statistici multiple pe aceleași date
  • Verificarea calculelor: Testați întotdeauna algoritmul cu valori mici!

Pentru profesori: Această problemă este excelentă pentru a discuta despre "cazuri speciale". Întrebați elevii: "Ce se întâmplă dacă n=0? Dar dacă n=1? Cum gestionăm aceste cazuri?"

EXERCIȚII PRACTICE - 10 minute

Exercițiul Practic: Calcule multiple combinate

Sarcini de lucru

Completează următoarele sarcini pentru a-ți consolida cunoștințele despre sume și produse complexe

Sarcina 1: Analiză algoritm cu 3 rezultate

Analizează algoritmul pentru problema cu 3 calcule:

Pentru n=15, care numere intră în fiecare categorie și de ce? Câte numere sunt divizibile atât cu 3, cât și cu 5?

Soluție pentru Sarcina 1:

Analiza pentru n=15:

  • Divizibile cu 3: 3, 6, 9, 12, 15 → suma = 3+6+9+12+15 = 45
  • Divizibile cu 5: 5, 10, 15 → produs = 5×10×15 = 750
  • Nedivizibile cu 3 sau 5: 1, 2, 4, 7, 8, 11, 13, 14 → contor = 8
  • Numere divizibile și cu 3 și cu 5: 15 (un singur număr)

Observație importantă: Numărul 15 apare atât în suma divizibilelor cu 3, cât și în produsul divizibilelor cu 5. Acest lucru este corect, deoarece condițiile sunt independente. În problemele de acest tip, un număr poate să contribuie la mai multe calcule dacă îndeplinește mai multe condiții.

Verificare: 15 % 3 == 0 (adevărat) și 15 % 5 == 0 (adevărat), deci se execută atât sumaDiv3 += 15 cât și produsDiv5 *= 15.

Sarcina 2: Implementare în C++ pentru statistici complexe

Cerință: Implementează în C++ un program care citește un număr n și afișează: suma numerelor perfecte, produsul numerelor abundente, și numărul numerelor deficiente de la 1 la n.

Soluție pentru Sarcina 2:
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    int sumaPerfecte = 0;
    int produsAbundente = 1;
    int numarDeficiente = 0;
    
    // Parcurgem toate numerele de la 1 la n
    for (int i = 1; i <= n; i++) {
        int sumaDivizori = 0;
        
        // Calculăm suma divizorilor lui i (fără i însuși)
        for (int d = 1; d <= i/2; d++) {
            if (i % d == 0) {
                sumaDivizori += d;
            }
        }
        
        // Clasificăm numărul i
        if (sumaDivizori == i) {
            // Număr perfect
            sumaPerfecte += i;
        } else if (sumaDivizori > i) {
            // Număr abundant
            produsAbundente *= i;
        } else {
            // Număr deficient (inclusiv numerele prime)
            numarDeficiente++;
        }
    }
    
    cout << sumaPerfecte << " " << produsAbundente << " " << numarDeficiente << endl;
    
    return 0;
}

Explicații importante:

  • Buclă dublă: Pentru fiecare număr i, avem o buclă pentru divizori
  • Suma divizorilor: Calculăm suma divizorilor proprii (fără numărul însuși)
  • Clasificare exclusivă: Un număr poate fi doar perfect, abundant sau deficient
  • Numere prime: Sunt deficiente (suma divizorilor = 1 < numărul)
  • Teste recomandate:
  • n=10 → perfecte: 6 (suma=6), abundente: niciuna (produs=1), deficiente: 9
  • n=28 → perfecte: 6+28=34, abundente: 12,18,20,24 (produs=103680), deficiente: restul
  • n=1 → perfecte: 0, abundente: niciuna (produs=1), deficiente: 1

Descarcă toate exercițiile și soluțiile