Documente Academic
Documente Profesional
Documente Cultură
Capitolul
i acum s rezolvm cteva probleme uoare legate de divizibilitate i stabilirea primalitii unui numr. Relativ la divizibilitatea numerelor ntregi, exist multe probleme interesante. Vom rezolva cteva dintre ele, care pun n eviden anumite proprieti interesante ale divizorilor, proprieti care sunt n acelai timp utile pentru rezolvarea eficient a problemelor de informatic.
69
Explicaie
Numerele de la ieire mpart exact numrul n = 20.
70
Explicaie 6=1+2+3 28 = 1 + 2 + 4 + 7 + 14
71
Explicaie 20 = 22 * 5.
72
73
{ nc nu am gsit nici un divizor } { generm toi divizorii posibili ai lui n, ncepnd cu 1 } { restul mpririi ntregi al lui n la divizor }
pentru divizor=1,n execut dac rest[n/divizor] = 0 atunci nr_divizori nr_divizori + 1 sfrit dac sfrit pentru dac nr_divizori=2 atunci scrie Numarul este prim. altfel scrie Numrul nu este prim. sfrit dac sfrit algoritm
Numrul mpririlor n varianta 1 de rezolvare este n, indiferent de proprietatea numrului. Vom ncerca s reducem acest numr, utiliznd o structur cu numr necunoscut de pai. Interpretarea definiiei se va oglindi n algoritm i n felul urmtor: mprim numrul, pornind de la 2, pn cnd gsim un divizor. Dac primul divizor astfel gsit este numrul dat, rezult c numrul este prim.
Algoritm Prim_varianta2: citete n divizor 2
{ dac primul divizor mai mare dect 2 este chiar numrul dat }
scrie Numarul este prim.
74
altfel scrie Numrul nu este prim. sfrit algoritm
Ne dm seama c numrul se mparte de multe ori inutil. Numrul mpririlor se poate reduce observnd c dac ntre 2 i n/2 nu exist nici un divizor, atunci numrul cu siguran nu mai are alt divizor, deci este prim. Dar numrul mpririlor se poate reduce n continuare. Dac numrul nu are divizori pn la radicalul lui, nu va avea nici n continuare. Avnd n vedere c n nu se modific n corpul ciclului, trebuie evitat (re)calcularea radicalului la fiecare reluare a structurii repetitive.
Algoritm Prim_varianta3: citete n prim adevrat { variabil boolean; presupunem c numrul este prim } divizor 2 { generm divizorii posibili ncepnd cu 2 } radical [ n ] ct timp (divizor radical) i prim execut: dac rest[n/divizor] = 0 atunci prim fals altfel divizor divizor + 1 sfrit dac sfrit ct timp dac prim atunci scrie Numrul este prim. altfel scrie Numrul nu este prim. sfrit dac sfrit algoritm
{ cutm divizori pn la rdcina ptrat a lui n } { dac am gsit un divizor } { rezult c n nu este prim }
Numerele pare se mpart toate cu 2, deci nu sunt prime. Rezult imediat o posibil mbuntire a algoritmului n sensul c numerele pare se pot pune deoparte de la nceput. Da, dar 2 este prim... Dac am rezolvat cazul numerelor pare la nceputul algoritmului, nu mai are sens s efectum mpriri cu numere pare (un numr impar nu va avea nici un divizor numr par). Rezult urmtoarea variant n care divizori vor fi numerele impare mai mari dect 3. Pentru ca algoritmul s funcioneze corect i pentru n = 1, trebuie tratat separat i acest caz.
75
radical [ n ] ct timp (divizor radical) i prim execut: dac rest[n/divizor] = 0 atunci prim fals altfel divizor divizor + 2 { divizorii posibili sunt numere impare } sfrit dac sfrit ct timp sfrit dac sfrit dac dac prim atunci scrie Numrul este prim. altfel scrie Numrul nu este prim. sfrit dac sfrit algoritm
76
Observaie Timpul de execuie al acestui algoritm poate fi mbuntit dac verificai mai nti dac nu cumva numrul dat este prim (caz n care nu poate fi descompus), iar atunci cnd cutai divizori noi ai numrului inei cont de faptul c singurul numr prim par este 2 deci, ncepnd cu d = 3 am putea parcurge din 2 n 2 mulimea numerelor naturale.
77
78
Evident, soluia anterioar este ineficient din punct de vedere al timpului de execuie pentru valori foarte mari ale numrului n. Ne putem gndi la o soluie mai eficient folosind o numrare direct pentru determinarea factorului de multiplicitate al unui anumit factor prim n numrul n!. S observm c exist [n/2] multipli de 2, [n/4] multipli de 4 etc. La ce ne folosete aceast observaie? Vom determina foarte rapid factorul de multiplicitate al lui 2 n cadrul lui n!. Fiecare multiplu de 2 va trebui s-l numrm o singur dat, multiplii de 4 i vom numra de dou ori, multiplii de 8 de trei ori .a.m.d. Numrarea se oprete pentru o valoare a puterii lui 2 care depete numrul n dat, deoarece contribuia lui 2nr pentru 2nr > n este nul n calculul factorului de multiplicitate. Iat un exemplu: determinarea multiplicitii lui 2 n cadrul lui 20!
fm2 = [20/2] + [20/4] + [20/8] + [20/16] = 10 + 5 + 2 + 1 = 18
Dac nu credei, calculai manual! S realizm descrierea n pseudocod a acestei variante de abordare a problemei:
Algoritmul MultiplicitatenFactorial2: citete n fm2 0 { iniializm cu zero factorul de multiplicitate } factor 2 { ncepem prin a contabiliza multiplii de 2 } ct timp factor n execut: { adunm la multiplicitate numrul de multiplii ai lui factor } fm2 fm2 + [n/factor]
n aceast variant putei remarca dou aspecte: simplitatea implementrii, care este aspectul cel mai evident; eficiena implementrii: pentru n = 100, de exemplu, n prima variant, numrul de reluri ale structurii repetitive externe este egal cu 50, n timp ce n aceast a doua variant structura repetitiv din algoritm se reia doar de 6 ori. Pentru valori i mai mari ale numrului n, mbuntirea vitezei de execuie este i mai dramatic.
79
O soluie a problemei va fi orice pereche k, n k (k + (n k) = n) pentru care ambele valori sunt numere prime. Deoarece nu ne intereseaz toate soluiile problemei, vom utiliza urmtoarea strategie pentru gsirea rapid a perechii de numere: pornim de la k = 3 i testm dac numrul k este prim, respectiv dac este prim numrul n k; dac nu am gsit o soluie a problemei, k k + 2 i relum verificarea.