Numere prime și verificarea primalității
După ce am învățat despre divizori și multipli, următorul pas natural este să studiem numerele prime.
Numerele prime apar foarte des în:
- probleme de matematică;
- algoritmică de bază;
- criptografie;
- exerciții de concurs.
Ce este un număr prim?
Un număr natural n este prim
dacă are exact doi divizori:
1n
Exemple:
2este prim (divizori:1, 2);3este prim (divizori:1, 3);5este prim (divizori:1, 5).
Ce este un număr neprim (compus)?
Un număr este compus dacă are mai mult de doi divizori.
Exemple:
4are divizorii1, 2, 4-> compus;6are divizorii1, 2, 3, 6-> compus;12are mai mulți divizori -> compus.
Caz important: 0 și
1
0nu este prim;1nu este prim.
Așadar, primul număr prim este 2.
Hint: când verifici primalitatea, primul
test corect este if (n < 2).
Verificarea primalității - soluția simplă (ineficientă)
Ideea:
- numărăm câți divizori are
nîntre1șin; - dacă are exact
2, numărul este prim.
int n;
cin >> n;
int cnt = 0;
for (int d = 1; d <= n; d++) {
if (n % d == 0) {
cnt++;
}
}
if (cnt == 2) {
cout << "Prim";
} else {
cout << "Neprim";
}Input:
13Output:
PrimDe ce este ineficientă?
Pentru fiecare număr verificăm toate valorile până la
n, deci pentru numere mari este lentă.
Verificarea primalității - soluția eficientă
Observație:
Dacă n are un divizor diferit de 1
și n, atunci unul dintre divizori este cel mult
sqrt(n).
Asta înseamnă că nu trebuie să verificăm până la
n, ci doar până la:
d * d <= n
De ce e suficient d * d <= n?
Dacă n este compus, atunci se poate scrie
n = a * b, cu a >= 2 și
b >= 2.
Nu putem avea ambele numere mai mari decât
sqrt(n), pentru că atunci produsul ar fi mai mare
decât n.
Deci cel puțin un divizor este <= sqrt(n),
iar dacă nu găsim niciunul în acel interval, numărul este
prim.
int n;
cin >> n;
if (n < 2) {
cout << "Neprim";
} else {
bool prim = true;
for (int d = 2; d * d <= n; d++) {
if (n % d == 0) {
prim = false;
break;
}
}
if (prim) {
cout << "Prim";
} else {
cout << "Neprim";
}
}Input:
25Output:
NeprimExplicație pentru
n = 25
- verificăm
d = 2-> nu divide; - verificăm
d = 3-> nu divide; - verificăm
d = 4-> nu divide; - verificăm
d = 5-> divide (25 % 5 == 0); - ne oprim ->
25este neprim.
Afișarea numerelor
prime până la n
Putem verifica fiecare număr de la 2 la
n cu metoda eficientă.
int n;
cin >> n;
for (int x = 2; x <= n; x++) {
bool prim = true;
for (int d = 2; d * d <= x; d++) {
if (x % d == 0) {
prim = false;
break;
}
}
if (prim) {
cout << x << " ";
}
}Input:
20Output:
2 3 5 7 11 13 17 19Greșeli frecvente
1. Considerăm că
1 este prim
Greșit: 1 are un singur divizor, nu doi.
2. Pornim verificarea de
la d = 1
Dacă începi de la 1, condiția
n % 1 == 0 este mereu adevărată și nu ajută la
testul de primalitate.
În varianta eficientă pornim de la d = 2.
3. Nu oprim bucla după ce găsim divizor
Dacă am găsit un divizor, știm deja că numărul este neprim.
break face programul mai rapid.
Ce să reții
- Un număr prim are exact doi divizori:
1și el însuși. 0și1nu sunt prime.- Verificarea până la
neste corectă, dar lentă. - Verificarea până la
sqrt(n)este mult mai eficientă. - Pentru probleme practice, metoda cu
d * d <= neste recomandată.