Școala Româno-Britanică
Modulul 5 Clasa a X-a | C++

Ora 5: CMMDC recursiv - algoritmul lui Euclid

Ce vei învăța astăzi: Algoritmul lui Euclid (metoda de calcul a CMMDC prin resturi succesive), definiția recursivă a CMMDC și aplicații precum fracțiile ireductibile (fracții care nu mai pot fi simplificate)

Rezultat practic: Scrii funcția recursivă cmmdc în C++ și o aplici în probleme de divizibilitate (Competența 4.5)

Competența 4.5 Săptămâna 27

Înainte de a începe

De ce contează? CMMDC este algoritmul cel mai folosit în problemele de divizibilitate, iar varianta recursivă a lui Euclid este foarte eficientă și apare des la teste.

Ce știi deja?

Din ora 4, știi de ce varianta recursivă simplă a lui Fibonacci este lentă? Poți găsi divizorii comuni ai lui 12 și 18?

Ideea-cheie: Algoritmul lui Euclid: cmmdc(a, b) = cmmdc(b, a % b), cu cazul de bază b == 0 care întoarce a.
SINTEZĂ TEORETICĂ ȘI EXEMPLE GHIDATE

Ce vei învăța astăzi?

După această lecție vei implementa algoritmul lui Euclid recursiv pentru calculul celui mai mare divizor comun (CMMDC) și vei folosi CMMDC în probleme practice precum fracțiile ireductibile.

Algoritmul lui Euclid
Definiția recursivă: cmmdc(a, b) = cmmdc(b, a % b)
Cazul de bază: b == 0
Aplicații: fracții ireductibile

Algoritmul lui Euclid

Definiție: CMMDC a două numere naturale este cel mai mare număr care le divide pe amândouă. Algoritmul lui Euclid se bazează pe proprietatea: cmmdc(a, b) = cmmdc(b, a % b) (unde a % b este restul împărțirii lui a la b), iar când b devine 0, rezultatul este a.

Forma recursivă: cmmdc(a, b) = b == 0 ? a : cmmdc(b, a % b).

Urmărirea pentru cmmdc(48, 18)
48 1848 % 18 = 12
18 1218 % 12 = 6
12 612 % 6 = 0
6 0cazul de bază: rezultatul este 6

Funcția CMMDC recursivă în C++

Algoritm cmmdc(a, b): dacă b == 0 atunci returnează a altfel returnează cmmdc(b, a % b)
Program C++ - CMMDC recursiv
#include <iostream>
using namespace std;

int cmmdc(int a, int b)
{
    if (b == 0)
        return a;
    return cmmdc(b, a % b);
}

int main()
{
    int a, b;
    cout << "a b = ";
    cin >> a >> b;
    cout << cmmdc(a, b);
    return 0;
}

Observă: funcția este foarte scurtă și elegantă; fiecare apel reduce rapid valorile, deoarece restul este întotdeauna mai mic decât împărțitorul.

Aplicație: fracții ireductibile

Simplificarea unei fracții

O fracție a/b se simplifică împărțind atât numărătorul, cât și numitorul la cmmdc(a, b). Fracția obținută se numește ireductibilă.

Exemplu: fracția 48/18 se simplifică cu cmmdc = 6, rezultând 8/3.

Program C++ - fracție ireductibilă
#include <iostream>
using namespace std;

int cmmdc(int a, int b)
{
    if (b == 0)
        return a;
    return cmmdc(b, a % b);
}

int main()
{
    int a, b, d;
    cin >> a >> b;
    d = cmmdc(a, b);
    cout << a / d << " " << b / d;
    return 0;
}

Exercițiu de completare

Completează enunțul despre CMMDC cu cuvintele potrivite:

CMMDC a două numere este cel mai mare număr care le ______ pe amândouă. Algoritmul lui Euclid folosește proprietatea cmmdc(a, b) = cmmdc(b, a ______ b). Cazul de ______ este atins când b = 0, iar rezultatul este ______. O fracție se numește ireductibilă când este simplificată cu ______.

Bancă de cuvinte:
divide % bază a cmmdc

Exercițiu de completare

Completează funcția cmmdc din codul C++:
______ cmmdc(int a, int b)
{
    if (b == ______)
        ______ a;
    return cmmdc(b, a ______);
}
Bancă de cuvinte:
int 0 return % b

Test de înțelegere

Test rapid - CMMDC:

1. Cazul de bază al algoritmului lui Euclid este:

2. cmmdc(48, 18) are valoarea:

3. Fracția 48/18 simplificată devine:

Ai grijă la: ordinea parametrilor la apelul recursiv - cmmdc(b, a % b), nu cmmdc(a % b, b), altfel obții rezultate greșite.

Aprofundare

De ce funcționează algoritmul lui Euclid? Orice divizor comun al lui a și b divide și restul a % b, deci mulțimea divizorilor comuni ai perechii (a, b) este identică cu cea a perechii (b, a % b). Reducând mereu perechea, ajungem la (cmmdc, 0), unde răspunsul este evident. Resturile descresc strict, deci algoritmul se termină după un număr mic de pași (logaritmic).

CMMMC prin CMMDC. Cel mai mic multiplu comun se calculează direct cu formula cmmmc(a, b) = (a / cmmdc(a, b)) * b. Împărțirea înainte de înmulțire evită depășirea tipului de date.

Fracții ireductibile. O fracție a / b se simplifică împărțind numărătorul și numitorul la cmmdc(a, b). Astfel se obține forma ireductibilă, folosită la rezolvarea problemelor cu fracții.

Cazuri particulare.

  • cmmdc(a, 0) = a pentru orice a ≥ 0, inclusiv cmmdc(0, 0) tratat separat (rezultat 0).
  • Pentru a < b, primul pas realizează cmmdc(b, a) prin schimbare implicită de poziții, deci algoritmul funcționează fără sortare prealabilă.
  • Pentru numere negative se ia valoarea absolută, deoarece CMMDC este definit doar pentru numere naturale.
APLICARE ȘI REZOLVARE DE PROBLEME

PbInfo - CMMDC

Enunț:

Cerință: Se citesc două numere naturale a și b. Să se afișeze cel mai mare divizor comun al lor, folosind un subprogram recursiv.

Date de intrare:

Programul citește de la tastatură numerele a și b.

Date de ieșire:

Programul va afișa pe ecran valoarea cmmdc(a, b).

Restricții și precizări:

1 ≤ a, b ≤ 2.000.000.000.

Exemplu:

Intrare:

48 18

Ieșire:

6
Cum gândim soluția:
  1. Definim funcția cmmdc(a, b)
  2. Cazul de bază: dacă b == 0, întoarcem a
  3. Altfel întoarcem cmmdc(b, a % b)
  4. În main citim a și b și afișăm rezultatul
Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;

int cmmdc(int a, int b)
{
    if (b == 0)
        return a;
    return cmmdc(b, a % b);
}

int main()
{
    int a, b;
    cin >> a >> b;
    cout << cmmdc(a, b);
    return 0;
}

Ce învățăm: algoritmul lui Euclid este foarte eficient, deoarece resturile scad rapid.

PbInfo - Fracții ireductibile

Enunț:

Cerință: Se citesc două numere naturale a și b (numărătorul și numitorul unei fracții). Să se afișeze fracția simplificată la forma ireductibilă, folosind cmmdc calculat recursiv.

Date de intrare:

Programul citește de la tastatură numerele a și b.

Date de ieșire:

Programul va afișa numărătorul și numitorul simplificați, separați printr-un spațiu.

Restricții și precizări:

1 ≤ a, b ≤ 2.000.000.000, b nenul.

Exemplu:

Intrare:

48 18

Ieșire:

8 3
Cum gândim soluția:
  1. Definim funcția recursivă cmmdc(a, b)
  2. În main citim a și b
  3. Calculăm d = cmmdc(a, b)
  4. Afișăm a / d și b / d
Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;

int cmmdc(int a, int b)
{
    if (b == 0)
        return a;
    return cmmdc(b, a % b);
}

int main()
{
    int a, b, d;
    cin >> a >> b;
    d = cmmdc(a, b);
    cout << a / d << " " << b / d;
    return 0;
}

Ce învățăm: CMMDC-ul este util în practică pentru simplificarea fracțiilor.

EXERCIȚII PRACTICE

Exercițiul Practic: CMMDC în practică

Sarcini de lucru

Rezolvă sarcinile următoare despre CMMDC

Sarcina 1: CMMDC a trei numere

Cerință: Scrie un program C++ care citește trei numere și afișează cmmdc al lor, folosind funcția recursivă cmmdc. Rezultatul este cmmdc(cmmdc(a, b), c). Pentru 24, 36, 60 rezultatul este 12.

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

int cmmdc(int a, int b)
{
    if (b == 0)
        return a;
    return cmmdc(b, a % b);
}

int main()
{
    int a, b, c;
    cin >> a >> b >> c;
    cout << cmmdc(cmmdc(a, b), c);
    return 0;
}

Verifică: cmmdc(24, 36) = 12, iar cmmdc(12, 60) = 12.

Sarcina 2: CMMMC

Cerință: Folosind proprietatea cmmmc(a, b) = a * b / cmmdc(a, b), scrie un program C++ care afișează cel mai mic multiplu comun a două numere. Pentru 12 și 18, cmmmc este 36.

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

int cmmdc(int a, int b)
{
    if (b == 0)
        return a;
    return cmmdc(b, a % b);
}

int main()
{
    int a, b;
    cin >> a >> b;
    cout << (long long)a * b / cmmdc(a, b);
    return 0;
}

Scrie pe caiet

Titlul lecției

CMMDC recursiv - algoritmul lui Euclid. A cincea lecție din Modulul 5 îți arată cum se calculează cel mai mare divizor comun cu o funcție recursivă elegantă.

Definiția lecției

CMMDC a două numere naturale este cel mai mare număr care le divide pe amândouă. Algoritmul lui Euclid se bazează pe proprietatea cmmdc(a, b) = cmmdc(b, a % b): restul împărțirii înlocuiește perechea de numere, iar valorile scad rapid. Cazul de bază este b == 0, când rezultatul este a. Fiecare apel reduce valorile, deoarece restul este întotdeauna mai mic decât împărțitorul. CMMDC se folosește pentru simplificarea fracțiilor, calculul CMMMC și problemele de divizibilitate. Algoritmul este foarte rapid: numărul de pași este logaritmic în raport cu valorile de intrare.

Definiții esențiale

Algoritmul cheie - pseudocod

Algoritm cmmdc(a, b): dacă b == 0 atunci returnează a altfel returnează cmmdc(b, a % b)

Algoritmul cheie - cod C++

Program C++ - CMMDC recursiv
#include <iostream>
using namespace std;

int cmmdc(int a, int b)
{
    if (b == 0)
        return a;
    return cmmdc(b, a % b);
}

int main()
{
    int a, b;
    cout << "a = ";
    cin >> a;
    cout << "b = ";
    cin >> b;
    cout << cmmdc(a, b);
    return 0;
}

Greșeli comune de evitat

Exemplu practic

Scenariu real: vrei să împarți în mod egal 48 de prăjituri și 18 sucuri între invitați, fără rest. CMMDC(48, 18) = 6, deci pot fi 6 invitați. Funcția recursivă rezolvă calculul:

Program C++ - CMMDC (exemplu practic)
int cmmdc(int a, int b)
{
    if (b == 0)
        return a;
    return cmmdc(b, a % b);
}

Apelul cmmdc(48, 18) întoarce 6.

Sfaturi practice și trucuri