Probleme rezolvate pe categorii
Divizibilitate
Înainte de probleme Tiparul problemelor de divizibilitate
Problemele de divizibilitate s-au dat la examenul de Definitivat în 2024 și la bacalaureat în 2023. În problemele din tabelul de mai jos se cere un subprogram care lucrează pe un singur număr sau pe o pereche de numere, iar programul principal aplică subprogramul tuturor numerelor citite.
| Problema | Ce face subprogramul | Ce face programul |
|---|---|---|
| k-perechi de numere consecutive (Definitivat 2024) | numără divizorii unui număr | numără perechile de numere consecutive cu câte k divizori |
| Număr abundent (bacalaureat 2023) | calculează suma divizorilor | compară raportul S(n)/n cu rapoartele numerelor mai mici |
| Un număr par scris ca sumă de două numere prime | verifică dacă un număr este prim | scrie un număr par ca sumă de două numere prime |
| Numerele prime găsite cu suma divizorilor proprii | calculează suma divizorilor proprii | afișează în ordine crescătoare numerele prime |
| Perechi de numere prime între ele | calculează cel mai mare divizor comun | afișează perechile de numere prime între ele |
| Numerele prime în ordine inversă citirii | verifică dacă un număr este prim | afișează numerele prime în ordine inversă citirii |
| Fracții ireductibile și numitorul comun | calculează cel mai mare divizor comun | simplifică fracții și calculează numitorul comun |
| Numerele perfecte dintr-un fișier | verifică dacă un număr este perfect | afișează descrescător numerele perfecte |
Prelucrările de bază de mai jos se scriu de fiecare dată la fel.
Divizorii unui număr
Un număr natural d este divizor al lui n dacă restul împărțirii lui n la d este 0, adică
n % d == 0. Divizorii lui n se grupează în perechi: dacă d este divizor, atunci și n/d este
divizor. Pentru n = 36:
| d | 1 | 2 | 3 | 4 | 6 |
|---|---|---|---|---|---|
| n/d | 36 | 18 | 12 | 9 | 6 |
Din fiecare pereche, divizorul mai mic este cel mult egal cu rădăcina pătrată a lui n. De aceea divizorii se caută numai pentru d de la 1 până când d·d depășește n, iar pentru fiecare divizor găsit se numără și perechea lui, n/d. Când n este pătrat perfect, d și n/d sunt egali pentru d = 6, iar divizorul se numără o singură dată. Lui 36 îi corespund astfel 9 divizori.
Pentru n = 10⁶, căutarea până la rădăcina pătrată face 1000 de împărțiri, în loc de 500 000 cât ar face căutarea până la n/2.
Divizorii proprii ai lui n sunt divizorii diferiți de 1 și de n. Divizorii 1 și n se numesc improprii.
Numărul prim
Un număr natural este prim dacă este mai mare decât 1 și are exact doi divizori: 1 și el însuși. Pentru verificare se caută un divizor d cu 2 ≤ d și d·d ≤ n:
- dacă se găsește un astfel de divizor, numărul nu este prim;
- dacă nu se găsește niciunul, numărul este prim.
Numerele 0 și 1 nu sunt prime și se tratează separat, la începutul subprogramului.
Cel mai mare divizor comun
Cel mai mare divizor comun al numerelor a și b, notat (a, b) sau cmmdc(a, b), este cel mai mare număr natural care îl divide atât pe a, cât și pe b. Dacă cmmdc(a, b) = 1, numerele a și b sunt prime între ele.
Algoritmul lui Euclid cu împărțiri se bazează pe faptul că orice divizor comun al lui a și b divide și restul împărțirii lui a la b. Pașii algoritmului sunt:
- se calculează r, restul împărțirii lui a la b;
- a primește valoarea lui b, iar b primește valoarea lui r;
- cât timp b este diferit de 0, se reia de la primul pas;
- la oprire, cmmdc este valoarea lui a.
Pentru a = 504 și b = 60:
| a | b | r = a % b |
|---|---|---|
| 504 | 60 | 24 |
| 60 | 24 | 12 |
| 24 | 12 | 0 |
| 12 | 0 | — |
Cel mai mare divizor comun este 12.
Algoritmul lui Euclid cu scăderi se bazează pe faptul că divizorii comuni ai lui a și b divid și diferența lor. Cât timp a ≠ b, din numărul mai mare se scade numărul mai mic; la oprire, a = b este cmmdc. Varianta cu scăderi face mai mulți pași: pentru 1000 și 1 face 999 de scăderi, iar varianta cu împărțiri face un singur pas.
Cel mai mic multiplu comun
Cel mai mic multiplu comun al numerelor nenule a și b, notat [a, b] sau cmmmc(a, b), este cel mai mic număr natural nenul care se divide atât cu a, cât și cu b. Între cele două valori există relația:
cmmdc(a, b) · cmmmc(a, b) = a · b
deci cmmmc(a, b) = a · b / cmmdc(a, b). Pentru 504 și 60, cmmmc = 504 · 60 / 12 = 2520.
Descompunerea în factori primi
Orice număr natural n ≥ 2 se scrie ca produs de numere prime, fiecare la o anumită putere, iar scrierea este unică. Pentru n = 880:
Problema 1 · Definitivat 2024 · Subiectul I.3 · 15 puncte k-perechi de numere consecutive
Cerința este rezolvată și pe pagina subiectului: k-perechi de numere consecutive.
Ce cere problema
Două numere consecutive, i și i + 1, formează o k-pereche dacă amândouă au exact k divizori. În intervalul [22, 80], pentru k = 4:
| Perechea | Divizorii primului număr | Divizorii celui de-al doilea număr |
|---|---|---|
| 26 și 27 | 1, 2, 13, 26 | 1, 3, 9, 27 |
| 33 și 34 | 1, 3, 11, 33 | 1, 2, 17, 34 |
| 34 și 35 | 1, 2, 17, 34 | 1, 5, 7, 35 |
| 38 și 39 | 1, 2, 19, 38 | 1, 3, 13, 39 |
| 57 și 58 | 1, 3, 19, 57 | 1, 2, 29, 58 |
Intervalul este delimitat de x și y, care pot fi date în orice ordine: în primul exemplu x = 80 și y = 22. Ambele numere ale perechii trebuie să fie în interval, deci primul număr al perechii merge de la capătul mic până la capătul mare minus 1.
Programul și descrierea metodei
În stânga sunt subprogramul și programul principal, așa cum se scriu pe foaia de examen. În dreapta este metoda de rezolvare, descrisă în limbaj natural, cu pașii așezați pe niveluri după structura programului.
#include <iostream>
#include <fstream>
using namespace std;
/* Numarul divizorilor lui n: divizorii se cauta
pana la radacina patrata, cu perechea lor n/d. */
int nrDiv(int n) {
int nr = 0;
for (int d = 1; d * d <= n; d++)
if (n % d == 0) {
nr++; // divizorul d
if (d != n / d)
nr++; // divizorul n/d
}
return nr;
}
Subprogramul nrDiv(n)
- nr pornește de la 0
- pentru d de la 1, cât timp d·d ≤ n
- dacă d îl divide pe n
- se numără divizorul d
- dacă n/d este diferit de d, se numără și divizorul n/d
- dacă d îl divide pe n
- se returnează nr
Pentru n = 27 se găsesc 1 cu perechea 27 și 3 cu perechea 9, deci se returnează 4. Căutarea face cel mult 1000 de pași, deoarece 1000 · 1000 = 10⁶.
int main() {
ifstream f("def2024.in");
int k, x, y;
f >> k >> x >> y;
f.close();
if (x > y) { // capetele, in ordine
int aux = x;
x = y;
y = aux;
}
int nr = 0;
int dCurent = nrDiv(x); // divizorii lui i
for (int i = x; i < y; i++) {
int dUrm = nrDiv(i + 1); // divizorii lui i+1
if (dCurent == k && dUrm == k)
nr++;
dCurent = dUrm;
}
cout << nr;
return 0;
}
Programul principal
- se citesc din fișier k, x și y
- dacă x > y, valorile lui x și y se interschimbă, astfel încât intervalul să fie [x, y]
- dCurent primește numărul divizorilor lui x
- pentru i de la x la y − 1
- dUrm primește numărul divizorilor lui i + 1
- dacă dCurent și dUrm sunt egale cu k, i și i + 1 formează o k-pereche și se numără
- dCurent primește dUrm: numărul i + 1 devine primul număr al perechii următoare
- se afișează numărul perechilor
Fiecare număr din interval trece o singură dată prin nrDiv.
Problema 2 · Bacalaureat 2023 · Subiectul III.1 · 10 puncte Număr abundent
Ce cere problema
S(i) este suma tuturor divizorilor lui i, inclusiv 1 și i. Pentru numerele de la 1 la 8:
| i | Divizorii | S(i) | S(i)/i |
|---|---|---|---|
| 1 | 1 | 1 | 1 |
| 2 | 1, 2 | 3 | 1.5 |
| 3 | 1, 3 | 4 | 1.33 |
| 4 | 1, 2, 4 | 7 | 1.75 |
| 5 | 1, 5 | 6 | 1.2 |
| 6 | 1, 2, 3, 6 | 12 | 2 |
| 7 | 1, 7 | 8 | 1.14 |
| 8 | 1, 2, 4, 8 | 15 | 1.87 |
Numărul n este abundent dacă raportul lui este strict mai mare decât raportul fiecărui număr mai mic. Pentru 6, raportul 2 este mai mare decât toate rapoartele din rândurile de deasupra. Pentru 8, raportul 1.87 este mai mic decât raportul lui 6.
Rapoartele nu se calculează cu împărțiri, deoarece valorile reale pot fi rotunjite. Ambele numere sunt pozitive, deci inegalitatea S(n)/n ≤ S(k)/k se scrie echivalent S(n) · k ≤ S(k) · n.
Programul și descrierea metodei
În stânga sunt subprogramul și programul principal, scrise în C++. În dreapta este metoda de rezolvare, descrisă în limbaj natural, cu pașii așezați pe niveluri după structura programului.
Problema 3 · Exercițiu Un număr par scris ca sumă de două numere prime
Ce cere problema
Pentru fiecare număr par mai mare decât 2 se caută două numere prime cu suma egală cu el. Se încearcă a = 2, 3, 4, … până când atât a, cât și n − a sunt prime:
| n | a încercat | n − a | Ambele prime? |
|---|---|---|---|
| 18 | 2 | 16 | nu, 16 nu este prim |
| 18 | 3 | 15 | nu, 15 nu este prim |
| 18 | 4 | 14 | nu, 4 nu este prim |
| 18 | 5 | 13 | da: 18 = 5 + 13 |
| 4 | 2 | 2 | da: 4 = 2 + 2 |
Numerele impare din fișier nu se prelucrează. Pentru toate numerele pare cu cel mult 4 cifre există o astfel de scriere, deci căutarea se oprește întotdeauna.
Programul și descrierea metodei
În stânga sunt subprogramul de la punctul a) și programul principal de la punctul b). În dreapta este metoda de rezolvare, descrisă în limbaj natural, cu pașii așezați pe niveluri după structura programului.
Problema 4 · Exercițiu Numerele prime găsite cu suma divizorilor proprii
Ce cere problema
Divizorii proprii ai lui n sunt divizorii lui diferiți de 1 și de n. Un număr prim nu are divizori proprii, deci suma lor este 0:
| n | Divizorii proprii | Suma | Este prim? |
|---|---|---|---|
| 4 | 2 | 2 | nu |
| 103 | — | 0 | da |
| 59 | — | 0 | da |
| 23 | — | 0 | da |
| 79 | — | 0 | da |
| 3 | — | 0 | da |
| 1003 | 17, 59 | 76 | nu |
Suma este 0 și pentru 0 și 1, care nu sunt prime. De aceea un număr n este prim dacă n > 1 și suma
divizorilor lui proprii este 0. Numerele prime se afișează în ordine crescătoare: 3 23 59 79 103.
Programul și descrierea metodei
În stânga sunt subprogramul de la punctul a) și programul principal de la punctul b). În dreapta este metoda de rezolvare, descrisă în limbaj natural, cu pașii așezați pe niveluri după structura programului.
Problema 5 · Exercițiu Perechi de numere prime între ele
Ce cere problema
Două numere sunt prime între ele dacă cel mai mare divizor comun al lor este 1. Se verifică fiecare pereche de numere de pe al doilea rând. Câteva perechi din exemplu:
| Perechea | Divizorii primului | Divizorii celui de-al doilea | cmmdc | Prime între ele? |
|---|---|---|---|---|
| 4 și 9 | 1, 2, 4 | 1, 3, 9 | 1 | da |
| 4 și 10 | 1, 2, 4 | 1, 2, 5, 10 | 2 | nu |
| 9 și 10 | 1, 3, 9 | 1, 2, 5, 10 | 1 | da |
| 10 și 15 | 1, 2, 5, 10 | 1, 3, 5, 15 | 5 | nu |
În pereche, numărul mai mic se scrie primul, deoarece enunțul cere a < b. Două numere egale nu formează o pereche cu a < b, deci nu se afișează.
Programul și descrierea metodei
În stânga sunt subprogramul de la punctul a) și programul principal de la punctul b). În dreapta este metoda de rezolvare, descrisă în limbaj natural, cu pașii așezați pe niveluri după structura programului.
Problema 6 · Exercițiu Numerele prime în ordine inversă citirii
Ce cere problema
Numerele din fișier se împart în prime și neprime:
| Numărul citit | 12 | 6 | 7 | 5 | 4 | 2 | 9 | 11 |
|---|---|---|---|---|---|---|---|---|
| Este prim? | nu | nu | da | da | nu | da | nu | da |
Numerele prime formează, în ordinea citirii, șirul 7 5 2 11. În ordine inversă se afișează
11 2 5 7. În fișier sunt 4 numere neprime, deci pe rândul al doilea se afișează 4.
Programul și descrierea metodei
În stânga sunt subprogramul și programul principal. În dreapta este metoda de rezolvare, descrisă în limbaj natural, cu pașii așezați pe niveluri după structura programului.
Problema 7 · Exercițiu Fracții ireductibile și numitorul comun
Ce cere problema
O fracție se aduce la forma ireductibilă împărțind numărătorul și numitorul la cel mai mare divizor comun al lor:
| Fracția citită | cmmdc | Forma ireductibilă |
|---|---|---|
| 12/36 | 12 | 1/3 |
| 49/70 | 7 | 7/10 |
| 35/40 | 5 | 7/8 |
| 25/70 | 5 | 5/14 |
| 1/3 | 1 | 1/3 |
Numitorul comun al fracțiilor ireductibile este cel mai mic multiplu comun al numitorilor din ultima coloană a tabelului, adică 840. Cel mai mic multiplu comun se calculează din cel mai mare divizor comun: cmmmc(a, b) = a / cmmdc(a, b) · b.
Programul și descrierea metodei
În stânga sunt subprogramul de la punctul a) și programul principal de la punctul b). În dreapta este metoda de rezolvare, descrisă în limbaj natural, cu pașii așezați pe niveluri după structura programului.
Problema 8 · Exercițiu Numerele perfecte dintr-un fișier
Ce cere problema
Un număr natural este perfect dacă este egal cu suma divizorilor săi diferiți de el însuși:
| n | Divizorii mai mici decât n | Suma | Este perfect? |
|---|---|---|---|
| 6 | 1, 2, 3 | 6 | da |
| 7 | 1 | 1 | nu |
| 28 | 1, 2, 4, 7, 14 | 28 | da |
| 14 | 1, 2, 7 | 10 | nu |
Tot perfecte sunt 496 și 8128. Primul număr din fișier, 6, arată câte numere urmează.
Programul și descrierea metodei
În stânga sunt subprogramul și programul principal. În dreapta este metoda de rezolvare, descrisă în limbaj natural, cu pașii așezați pe niveluri după structura programului.
#include <iostream>
#include <fstream>
using namespace std;
/* Returneaza n daca n este perfect, 0 altfel. */
int perfect(int n) {
if (n < 2)
return 0;
int s = 1; // divizorul propriu 1
for (int d = 2; d * d <= n; d++)
if (n % d == 0) {
s = s + d;
if (d != n / d)
s = s + n / d;
}
if (s == n)
return n;
return 0;
}
Subprogramul perfect(n)
- 0 și 1 nu sunt perfecte: se returnează 0
- s pornește de la 1, deoarece 1 este divizor al oricărui n ≥ 2
- pentru d de la 2, cât timp d·d ≤ n
- dacă d îl divide pe n
- d se adună la s
- dacă n/d este diferit de d, se adună și n/d
- dacă d îl divide pe n
- dacă s este egal cu n, se returnează n; altfel se returnează 0
Căutarea începe de la 2, deci divizorul n, pereche a lui 1, nu se adună.
int v[301];
int main() {
ifstream f("nr17.txt");
int n, x, k = 0;
f >> n;
for (int i = 1; i <= n; i++) {
f >> x;
if (perfect(x) != 0) {
k++;
v[k] = x;
}
}
f.close();
if (k == 0) {
cout << "NU EXISTA";
return 0;
}
/* ordonare descrescatoare */
for (int i = 1; i < k; i++)
for (int j = i + 1; j <= k; j++)
if (v[i] < v[j]) {
int aux = v[i];
v[i] = v[j];
v[j] = aux;
}
for (int i = 1; i <= k; i++)
cout << v[i] << " ";
return 0;
}
Programul principal
- se citește n, numărul de valori din fișier
- pentru fiecare dintre cele n valori x
- dacă
perfect(x)este diferit de 0, k crește cu 1 și x se memorează înv[k]
- dacă
- dacă k este 0, se afișează
NU EXISTAși programul se încheie - vectorul se ordonează descrescător
- pentru fiecare poziție i, se compară v[i] cu fiecare element de după el
- dacă un element de după el este mai mare, cele două se interschimbă
- se afișează elementele vectorului
Problema 9 · Exercițiu Divizorii unui număr în ordine crescătoare
Ce cere problema
Divizorii lui 12 se grupează în perechi d și 12/d:
| d | 1 | 2 | 3 |
|---|---|---|---|
| 12/d | 12 | 6 | 4 |
Divizorii din primul rând sunt mai mici decât rădăcina pătrată a lui 12 și cresc. Perechile lor, din al doilea rând, scad. Ordinea crescătoare se obține astfel:
- se afișează divizorii d din primul rând, de la stânga la dreapta;
- se afișează perechile n/d, de la dreapta la stânga.
Când n este pătrat perfect, rădăcina lui este divizor fără pereche și se afișează între cele două
grupe. Pentru 36 se afișează 1 2 3 4, apoi 6, apoi 9 12 18 36.
Programul și descrierea metodei
În stânga este programul. În dreapta este metoda de rezolvare, descrisă în limbaj natural, cu pașii așezați pe niveluri după structura programului.
Problema 10 · Exercițiu Descompunerea în factori primi
Ce cere problema
Orice număr natural n ≥ 2 se scrie ca produs de numere prime la anumite puteri. Pentru câteva valori:
| n | Descompunerea | Ce se afișează |
|---|---|---|
| 20 | 2² · 5¹ | 2^2, 5^1 |
| 90 | 2¹ · 3² · 5¹ | 2^1, 3^2, 5^1 |
| 880 | 2⁴ · 5¹ · 11¹ | 2^4, 5^1, 11^1 |
| 7 | 7¹ | 7^1 |
Divizorii primi se afișează în ordine crescătoare, separați prin virgulă și spațiu.
Programul și descrierea metodei
În stânga sunt subprogramul și programul principal. În dreapta este metoda de rezolvare, descrisă în limbaj natural, cu pașii așezați pe niveluri după structura programului.
#include <iostream>
using namespace std;
/* Afiseaza factorii primi ai lui n, cu puterile lor. */
void descompunere(int n) {
int primul = 1; // 1 cat timp nu s-a afisat nimic
for (int d = 2; d * d <= n; d++) {
int p = 0;
while (n % d == 0) {
n = n / d;
p++;
}
if (p > 0) {
if (primul == 0)
cout << ", ";
cout << d << "^" << p;
primul = 0;
}
}
if (n > 1) { // a ramas un factor prim
if (primul == 0)
cout << ", ";
cout << n << "^1";
}
}
Subprogramul descompunere(n)
- primul are valoarea 1 cât timp nu s-a afișat niciun factor
- pentru d de la 2, cât timp d·d ≤ n
- p, puterea lui d, pornește de la 0
- cât timp d îl divide pe n, n se împarte la d și p crește cu 1
- dacă p > 0
- dacă s-a afișat deja un factor, se afișează virgula și spațiul
- se afișează d, semnul
^și p - primul devine 0
- dacă n > 1, valoarea rămasă este un factor prim, la puterea 1
- se afișează, precedată de virgulă dacă nu este primul factor
Un divizor d găsit astfel este prim: factorii primi mai mici decât el au fost deja eliminați din n.
int main() {
int n;
cin >> n;
descompunere(n);
return 0;
}
Programul principal
- se citește n
- se apelează subprogramul
descompunere(n)
Materialul acesta se citește pe educamp.ro și nu se tipărește.
S-a încheiat minutul de citit liber.
Vezi problemele rezolvate ca și cursant
Lista categoriilor, cu problemele date la examen în fiecare, se citește gratuit și integral. Pentru a citi rezolvările, te înscrii la cursul de pregătire.
Te înscrii, alegi în cont când începe cursul și plătești prima lună prin transfer bancar. Pentru a vedea mai întâi ce probleme s-au dat, poți reveni la lista categoriilor.
Acces la suportul de curs
25 RON / lună, fără ședințe
Ce cuprinde:
- Acces la toate lecțiile disponibile
- Suport de curs pentru tematica științifică și metodică
- Exemple, explicații și exerciții
- Acces la materialele noi adăugate pe platformă
- Posibilitatea de a adresa întrebări