Documente Academic
Documente Profesional
Documente Cultură
Metoda naivă – presupune parcurgerea intervalului [1,n] și testarea fiecărui număr din interval dacă este
divizor a lui n. Această metodă are o complexitate O(n).
Implementare C++
int k=0;
for(int d=1;d<=n;d++){
if(n%d==0) k++;
}
cout<<”nr. de divizori=”<<k;
Obs: putem reduce intervalul de căutare la [2,n/2] ținând cont de faptul că niciun divizor a lui n nu se
găsește în intervalul [n/2+1,n-1], iar inițial stabilim k=2 (divizorii improprii) pentru n>=2.
Metoda optimizată
Dacă d este divizorul lui n se poate observa că și n/d este divizor a lui n deoarece d * (n/d) = n.
În acest fel putem stabili direct doi divizori.
Exemplu 1: Exemplu 2:
n=42 n=36
d n/d d n/d
2 21 2 18
3 14 3 12
6 7 4 9
7 6 6 6
14 3 9 4
21 2 12 3
18 2
În exemplul 1 observăm că în prima jumătate avem aceeași dizivori ca și în a doua jumătate, dar în altă
ordine. Totodată divizorii din prima jumătate sunt toți divizorii proprii ai lui n.
În prima jumătate se respectă relația d <= n/d . Dacă înmulțim ambii membri ai inegalității cu d vom avem
d*d <= n . Extragem radical din ambii membri ai inegalității și obținem d <= √𝑛. Observăm că este suficient
să parcurgem intervalul [2, √𝑛], ceea ce duce la o complexitate a algoritmului O(√𝒏).
În exemplul 2 se observă că în cazul numerelor pătrate perfecte avem un număr impar de dizivori, cazul d*d
= n trebuie tratat separat.
Implementarea în C++:
int k=2,d;
if(n==1){
cout<<n;
return 0;
}
for(d=2; d*d<n; d++){
if(n%d == 0){
k+=2;
}
}
if(d*d == n){
k++;
}
cout<<k;
OBS: Zero se divide cu orice număr diferit de zero. Zero are un număr infinit de divizori.
Ciurul lui Eratostene este un algoritm clasic folosit pentru determinarea tuturor numerelor prime mai mici
sau egale cu un număr natural dat n.
Algoritm
1) Se scrie pe o foaie o listă cu toate numerele naturale de la 2 la n.
2) Se caută în listă primul număr care nu a fost tăiat (și pe care încă nu l-am folosit).
3) Se taie de pe foaie toți multiplii numărului ales mai înainte, cu excepția lui.
4) Dacă încă nu am ajuns la finalul listei căutând numere netăiate, se revine la pasul 2.
Exemplu: n=16
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
x X x x x x x x x
Implementare
Reținem un vector sieve (ciur în engleză), de tip bool, cu semnificația sieve[i] == true dacă numărul i nu este
prim, iar false dacă i este prim. Am ales codificarea pe dos pentru că în C++ vectorii globali sunt automat
inițializați cu 0, și n-are rost să mai facem o parcurgere pentru a-l schimba pe 0 în 1. Cum numerele 0 și 1 nu sunt
nici prime, nici compuse, le vom marca de la început cu true: sieve[0] = sieve[1] = true;.
Apoi, alegem primul număr cu valoarea false din vectorul sieve, și marcăm multiplii săi cu true. Repetăm acest
proces până când toate numerele neprime din sieve vor fi marcate cu true.
Implementare C++
sieve[0] = sieve[1] = true;
for (int i = 2; i <= n; i++) // Parcurgem vectorul sieve.
if (!sieve[i]) // Dacă numărul curent este prim,
for (int j = 2 * i; j <= n; j += i) // parcurgem multiplii săi
sieve[j] = true; // și îi marcăm drept numere compuse.
În cazul avem de calculat numărul de divizori pentru mai multe numere dintr-un interval finit de numere
naturale se recomandă folosirea unui vector caracteristic în care se reține numărul de divizori ai fiecărui număr
din interval.
Mecanismul prin care se identifică numerele prime specific Ciurului lui Eratostene poate fi folosit și la
determinarea altor rezultate. De exemplu, vrem să aflăm pentru un n dat (nu prea mare) câți divizori are fiecare
număr natural din intervalul [1,n].
Pentru acesta, vom construi un vector v, în care v[x] reprezintă numărul de divizori ai lui x. Pentru a construi
acest vector, vom parcurge numerele de la 1 la n, și pentru fiecare număr x vom identifica multiplii săi. Pentru
fiecare y multiplu al lui x vom incrementa valoarea lui v[y].
Implementarea C++
Probleme propuse:
1) Se dă un șir de n numere naturale nenule. Determinați pentru fiecare număr din șir care este cel mai
mare divizor impar al său.[ Divizori impari – pbinfo]
2) Se dă un şir format din n numere naturale nenule. Aflaţi cel mai mic număr natural, diferit de 1, care
divide un număr maxim de numere din şir. [divizor112 - pbinfo]
3) Gigel a descoperit un nou joc. Jocul are n nivele și la fiecare nivel îți dă câte un număr natural x.
Pentru a trece nivelul trebuie să calculezi câți divizori are numărul x. Scrieți un program care să
permită terminarea jocului prin trecerea celor n nivele în ordinea în care sunt date. [joc2020 - pbinfo]
Bibliografie:
1) Arta programarii calculatoarelor, volumul 1. Algoritmi fundamentali, Autor Donald E.
Knuth, Editura Teora, 2000
2) Programarea in limbajul C/C++ pentru liceu : Programarea in limbajul C/C++ pentru liceu,
Emanuela Cerchez, Marinel-Paul Serban, Editura Polirom, 2005
3) https://www.geeksforgeeks.org/sieve-of-eratosthenes/
4) www.pbinfo.ro