5807 divizibilitate si numere prime

12
Divizibilitate şi numere prime Consideraţii teoretice Probleme propuse Soluţiile problemelor propuse Capitolul 7 7.1. Consideraţii teoretice Un capitol deosebit de interesant în teoria numerelor este cel de divizibilitate. Un număr dat a este divizibil cu un alt număr dat b, dacă restul împărţirii întregii a numărului a la numărul b este egal cu zero. În matematică există criterii de divizibilitate care ne permit verificarea rapidă a divizibilităţii unui număr cu altul. De exemplu, un număr este divizibil cu 2 dacă are ultima cifră pară. Orice număr este divizibil cu 1 şi cu el însuşi. Aceşti divizori se numesc divizori triviali (improprii). Dacă un număr nu are alţi divizori în afară de cei triviali, atunci spunem că numărul respectiv este număr prim (de exemplu 5, 13, 29). În programare, vom verifica divizibilitatea cu ajutorul operatorului mod: ... dacă a mod b = 0 atunci b este divizor al lui a altfel b nu este divizor al lui a sfârşit dacă ... Şi acum să rezolvăm câteva probleme uşoare legate de divizibilitate şi stabilirea primalităţii unui număr. Relativ la divizibilitatea numerelor întregi, există multe probleme interesante. Vom rezolva câteva dintre ele, care pun în evidenţă anumite proprietăţi interesante ale divi- zorilor, proprietăţi care sunt în acelaşi timp utile pentru rezolvarea eficientă a proble- melor de informatică.

Upload: mircea-sabau

Post on 30-Nov-2015

303 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: 5807 Divizibilitate Si Numere Prime

Divizibilitate şi numere prime Consideraţii teoretice Probleme propuse Soluţiile problemelor propuse

Capitolul

7 7.1. Consideraţii teoretice Un capitol deosebit de interesant în teoria numerelor este cel de divizibilitate. Un număr dat a este divizibil cu un alt număr dat b, dacă restul împărţirii întregii a numărului a la numărul b este egal cu zero. În matematică există criterii de divizibilitate care ne permit verificarea rapidă a divizibilităţii unui număr cu altul. De exemplu, un număr este divizibil cu 2 dacă are ultima cifră pară. Orice număr este divizibil cu 1 şi cu el însuşi. Aceşti divizori se numesc divizori triviali (improprii). Dacă un număr nu are alţi divizori în afară de cei triviali, atunci spunem că numărul respectiv este număr prim (de exemplu 5, 13, 29).

În programare, vom verifica divizibilitatea cu ajutorul operatorului mod: ... dacă a mod b = 0 atunci b este divizor al lui a altfel b nu este divizor al lui a sfârşit dacă ...

Şi acum să rezolvăm câteva probleme uşoare legate de divizibilitate şi stabilirea primalităţii unui număr. Relativ la divizibilitatea numerelor întregi, există multe probleme interesante. Vom rezolva câteva dintre ele, care pun în evidenţă anumite proprietăţi interesante ale divi-zorilor, proprietăţi care sunt în acelaşi timp utile pentru rezolvarea eficientă a proble-melor de informatică.

Page 2: 5807 Divizibilitate Si Numere Prime

7. Divizibilitate şi numere prime 69 7.2. Probleme propuse 7.2.1. Divizori Un număr este divizor al unui număr dat n, dacă restul împărţirii întregi a numărului n la acel număr este egal cu 0. Determinaţi toţi divizorii numărului dat.

Date de intrare Se dă un număr natural n. Date de ieşire Se vor afişa divizorii numărului pe o singură linie, separaţi prin câte-un spaţiu. Restricţii şi precizări • 2 ≤ n ≤ 10000; • Datele de intrare sunt considerate corecte. Exemplu Intrare n=20

Ieşire 1 2 4 5 10 20

Explicaţie Numerele de la ieşire împart exact numărul n = 20.

7.2.2. Numere prime Un număr n este prim, dacă nu are alţi divizori decât pe cei triviali (pe 1 şi pe el în-suşi). Precizaţi dacă un număr natural dat este sau nu număr prim. Date de intrare Se dă un număr natural n. Date de ieşire În funcţie de proprietatea numărului se va afişa textul 'Numarul este prim.' sau 'Numarul nu este prim.', după caz. Restricţii şi precizări • 2 ≤ n ≤ 10000. Exemple Intrare n=147 n=13

Ieşire 'Numarul nu este prim.' 'Numarul este prim.'

Page 3: 5807 Divizibilitate Si Numere Prime

70 7. Divizibilitate şi numere prime 7.2.3. Număr perfect Un număr n este „perfect” dacă este egal cu suma divizorilor săi, mai puţin el însuşi. Determinaţi toate numerele perfecte mai mici sau egale cu un număr natural n dat. Date de intrare Se dă un număr natural n, citit de la tastatură. Date de ieşire Numerele perfecte mai mici sau egale cu n, se vor scrie pe o singură linie, separate prin spaţiu. Restricţii şi precizări • 1 ≤ n ≤ 10000. Exemplu Intrare n=50

Ieşire 6 28

Explicaţie 6 = 1 + 2 + 3 28 = 1 + 2 + 4 + 7 + 14

7.2.4. Din nou numere prime Să se determine toate numerele prime din intervalul [a, b].

Date de intrare Se dau a şi b, două numere naturale. Date de ieşire Numerele prime din intervalul [a, b] se vor scrie în ordine crescătoare, separate prin câte un spaţiu. Restricţii şi precizări • 1 ≤ a < b ≤ 10000. Exemplu Intrare a=3 b=10

Ieşire 3 5 7

Explicaţie Numerele prime din intervalul [3, 10] sunt: 3 5 7

Timp de execuţie: 1 secundă

Page 4: 5807 Divizibilitate Si Numere Prime

7. Divizibilitate şi numere prime 71 7.2.5. Descompunerea în factori primi Se dă n număr natural. Să se realizeze descompunerea în factori primi a acestui număr. Pentru fiecare factor prim care apare în descompunerea numărului se va preciza şi factorul de multiplicitate (puterea la care apare factorul în descompunere). Date de intrare Se dă un număr natural n. Date de ieşire Pe fiecare linie se vor afişa câte două valori, prima reprezentând factorul care apare în descompunere, iar cea de a doua reprezentând multiplicitatea factorului respectiv. Restricţii şi precizări • 2 ≤ n ≤ 2000000000; • Datele de intrare sunt considerate corecte. Exemplu Intrare n=20

Ieşire 2 2 5 1

Explicaţie 20 = 22 * 5.

Timp de execuţie: 1 secundă/test 7.2.6. Zerouri în coadă Se dă un număr natural n. Număraţi câte zerouri are factorialul acestui număr la sfârşi-tul său. Date de intrare Se dă un număr natural n. Date de ieşire Se va afişa un număr natural, reprezentând numărul zerourilor de la sfârşitul factoria-lului numărului dat. Restricţii şi precizări • 2 ≤ n ≤ 2000000000; • datele de intrare se consideră corecte. Exemple Intrare n=120

Ieşire 28

Explicaţie 120! are 28 de zerouri la sfârşit

Timp de execuţie: 1 secundă/test

Page 5: 5807 Divizibilitate Si Numere Prime

72 7. Divizibilitate şi numere prime 7.2.7. Conjectura lui Goldbach O conjcetură este o afirmaţie pe care o face cineva, fără să poată să demonstreze rigu-ros valabilitatea afirmaţiei sale şi pentru care nu putem demonstra nici noi contrariul, chiar dacă am dori să o facem. Conjectura lui Goldbach afirmă că orice număr natural par şi mai mare decât 2 se poate descompune ca o sumă de două numere prime. Scrieţi un program pentru testa-rea valabilităţii acestei afirmaţii. Date de intrare Se dă numărul natural n, citit de la tastatură. Date de ieşire Se va afişa o pereche de numere prime a căror sumă este egală cu numărul dat. Restricţii şi precizări • 4 ≤ n ≤ 10.000; • datele de intrare sunt întotdeauna corecte; • numărul 1 nu este număr prim. Exemplu Intrare n=50

Ieşire 3 + 47 sau 7 + 43 sau 13 + 37 sau 19 + 31 sau 23 + 27

Explicaţie Oricare dintre perechile de numere prime date pe coloana de ieşire este o soluţie a problemei, deoarece însumând cele două valori obţinem valoarea dată pentru n (50).

Timp de execuţie: 1 secundă/test 7.3. Soluţiile problemelor rezolvate 7.3.1. Divizori Orice număr natural dat are ca şi divizori triviali pe numărul 1 şi pe el însuşi. Toţi cei-lalţi divizori se află între 2 şi [n/2] (în Pascal (n div 2)). Prin urmare, vom proceda astfel: • afişăm 1; • parcurgem mulţimea numerelor naturale începând cu 2 şi terminând cu n div 2:

dacă o valoare din acestea împarte exact numărul n, atunci o vom afişa; • la sfârşit afişăm şi numărul n.

Page 6: 5807 Divizibilitate Si Numere Prime

7. Divizibilitate şi numere prime 73 7.3.2. Numere prime Pornim de la definiţia numărului prim. „Un număr prim are exact doi divizori: pe 1 şi pe el însuşi.” Prima idee de a rezolva problema ar putea să se bazeze pe această definiţie. Vom număra divizorii numărului, împărţindu-l pe rând cu toate numerele începând cu 1 şi terminând cu el însuşi. La sfârşit, vom afişa răspunsul solicitat, testând numărul divi-zorilor. Algoritm Prim_varianta1: citeşte n nr_divizori ← 0 { încă nu am găsit nici un divizor } { generăm toţi divizorii posibili ai lui n, începând cu 1 } pentru divizor=1,n execută { restul împărţirii întregi al lui n la divizor } dacă rest[n/divizor] = 0 atunci nr_divizori ← nr_divizori + 1 { mărim contorul (divizorul) } sfârşit dacă sfârşit pentru dacă nr_divizori=2 atunci { dacă numărul divizorilor este 2 (1 şi n ) atunci numărul este prim } scrie Numarul este prim. altfel scrie Numărul nu este prim. sfârşit dacă sfârşit algoritm Numărul împărţirilor în varianta 1 de rezolvare este n, indiferent de proprietatea numărului. Vom încerca să reducem acest număr, utilizând o structură cu număr necu-noscut de paşi. Interpretarea definiţiei se va oglindi în algoritm şi în felul următor: îm-părţim numărul, pornind de la 2, până când găsim un divizor. Dacă primul divizor ast-fel găsit este numărul dat, rezultă că numărul este prim. Algoritm Prim_varianta2: citeşte n divizor ← 2 { pornim de la valoarea 2 şi ne oprim când ajungem la primul divizor } cât timp rest[n/divizor] ≠ 0 execută: divizor ← divizor + 1 sfârşit cât timp dacă divizor = n atunci { dacă primul divizor mai mare decât 2 este chiar numărul dat } scrie Numarul este prim.

Page 7: 5807 Divizibilitate Si Numere Prime

74 7. Divizibilitate şi numere prime altfel scrie Numărul nu este prim. sfârşit algoritm Ne dăm seama că numărul se împarte de multe ori inutil. Numărul împărţirilor se poate reduce observând că dacă între 2 şi n/2 nu există nici un divizor, atunci numărul cu siguranţă nu mai are alt divizor, deci este prim. Dar numărul împărţirilor se poate reduce în continuare. Dacă numărul nu are divizori până la radicalul lui, nu va avea nici în continuare. Având în vedere că n nu se modifică în corpul ciclului, trebuie evitată (re)calcularea radicalului la fiecare reluare a structurii repetitive. Algoritm Prim_varianta3: citeşte n prim ← adevărat { variabilă booleană; „presupunem” că numărul este prim } divizor ← 2 { generăm divizorii posibili începând cu 2 } radical ← [ n ] cât timp (divizor ≤ radical) şi prim execută: { căutăm divizori până la rădăcina pătrată a lui n } dacă rest[n/divizor] = 0 atunci { dacă am găsit un divizor } prim ← fals { rezultă că n nu este prim } altfel divizor ← divizor + 1 sfârşit dacă sfârşit cât timp dacă prim atunci scrie Numărul este prim. altfel scrie Numărul nu este prim. sfârşit dacă sfârşit algoritm Numerele pare se împart toate cu 2, deci nu sunt prime. Rezultă imediat o posibilă îmbunătăţire a algoritmului în sensul că numerele pare se pot pune „deoparte” de la în-ceput. Da, dar 2 este prim... Dacă am rezolvat cazul numerelor pare la începutul algoritmului, nu mai are sens să efectuăm împărţiri cu numere pare (un număr impar nu va avea nici un divizor nu-măr par). Rezultă următoarea variantă în care divizori vor fi numerele impare mai mari decât 3. Pentru ca algoritmul să funcţioneze corect şi pentru n = 1, trebuie tratat separat şi acest caz.

Page 8: 5807 Divizibilitate Si Numere Prime

7. Divizibilitate şi numere prime 75 Algoritm Prim_varianta4: citeşte n dacă n = 1 atunci { 1 nu este prim prin definiţie } prim ← fals altfel dacă n este par atunci { singurul număr prim par este 2 } prim ← n = 2 altfel prim ← adevărat divizor ← 3 { primul divizor posibil este 3 } radical ← [ n ] { căutăm divizori până la rădăcina pătrată } cât timp (divizor ≤ radical) şi prim execută: dacă rest[n/divizor] = 0 atunci prim ← fals altfel divizor ← divizor + 2 { divizorii posibili sunt numere impare } sfârşit dacă sfârşit cât timp sfârşit dacă sfârşit dacă dacă prim atunci scrie Numărul este prim. altfel scrie Numărul nu este prim. sfârşit dacă sfârşit algoritm 7.3.3. Număr perfect Pentru fiecare număr având valoarea între 1 şi n se va calcula suma divizorilor săi. Dacă această sumă este egală cu numărul, atunci se va afişa numărul respectiv. Atenţie De fiecare dată (pentru fiecare număr analizat) este necesară reiniţializarea varia-bilei de însumare s, pentru a se efectua corect suma divizorilor numărului. 7.3.4. Din nou numere prime Practic, problema este o extindere a problemei 2. Pentru fiecare număr natural, având valoarea între a şi b se verifică dacă este sau nu număr prim. Dacă da, atunci acesta va fi afişat pe ecran, urmat de un spaţiu.1

1 În clasa a 9-a vom învăţa şi alte modalităţi de a genera numere prime.

Page 9: 5807 Divizibilitate Si Numere Prime

76 7. Divizibilitate şi numere prime 7.3.5. Descompunerea în factori primi Rezolvarea problemei presupune două etape de calcul: • se determină un divizor prim al numărului (determinarea factorului prim); • se efectuează numărul maxim de împărţiri posibile ale numărului de descompus cu

acel divizor, numărându-se câte împărţiri s-au efectuat pentru factorul respectiv (determinarea factorului de multiplicitate).

Execuţia algoritmului se încheie atunci când numărul a devenit egal cu 1. De fiecare dată, contorul pentru factorul de multiplicitate trebuie să fie readus la zero. Nu va trebui să efectuăm pentru fiecare divizor găsit verificarea faptului că acesta este prim din următorul motiv: dacă am efectuat numărul maxim de împărţiri la 2, în-seamnă că valoarea rămasă nu va mai fi divizibilă cu nici un număr multiplu de 2. La fel se întâmplă cu împărţirea de numărul maxim de ori la numărul 3 ş.a.m.d. Deci, atunci când pentru valoarea rămasă găsim un divizor, cu siguranţă acesta este şi număr prim. În pseudocod, algoritmul descris mai sus se scrie astfel: Algoritmul DescompunereFactoriPrimi; citeşte n d ← 2 { primul factor prim posibil să apară în descompunere } cât timp n > 1 execută: { cât timp n mai conţine factori primi } cât timp rest[n/d] ≠ 0 execută: { căutăm un nou factor prim } d ← d + 1 sfârşit cât timp fm ← 0 {apoi stabilim multiplicitatea acestui nou factor prim} cât timp rest[n/d] = 0 execută: n ← [n/d] fm ← fm + 1 sfârşit cât timp scrie d,' ',fm { afişăm rezultatul obţinut conform cerinţei din enunţ } sfârşit cât timp sfârşit algoritm Observaţie Timpul de execuţie al acestui algoritm poate fi îmbunătăţit dacă verificaţi mai întâi dacă nu cumva numărul dat este prim (caz în care nu poate fi descompus), iar atunci când căutaţi divizori noi ai numărului ţineţi cont de faptul că singurul număr prim par este 2 deci, începând cu d = 3 am putea parcurge din 2 în 2 mulţimea numerelor natu-rale.

Page 10: 5807 Divizibilitate Si Numere Prime

7. Divizibilitate şi numere prime 77 7.3.6. Zerouri în coadă Cu siguranţă că aveţi deja prima idee: calculăm n! şi apoi determinăm numărul de ci-fre egale cu zero de la sfârşitul numărului. Matematic este corect şi posibil, deşi ar lua destul de mult timp. Vă reamintesc însă că a calcula n! înseamnă a calcula 1 ⋅ 2 ⋅...⋅ n. Cum procedaţi dacă n = 1000000? Dar dacă n = 2000000000 (limita maximă din enunţ)? Nici nu vreau să mă gândesc ce efort de calcul va trebui să depuneţi . Este necesară o altă idee de rezolvare. Faptul că numărul are un zero la sfârşit se poate traduce prin aceea că numărul este divizibil cu 10. Dar 10 = 2 ⋅ 5. Şi numerele 2 şi 5 sunt prime între ele (adică, au cel mai mare divizor comun egal cu 1). Deci, ar fi o idee mai bună să determinăm factorul de multiplicitate al numărului 2, respectiv al nu-mărului 5, în descompunerea lui n!. Numărul de zerouri de la sfârşitul factorialului va fi egal cu numărul maxim de perechi (2 ⋅ 5) care se pot forma. Iar acest număr este egal cu minimul dintre factorul de multiplicitate al lui 2 şi factorul de multiplicitate al lui 5. Apare acum o altă problemă. Cum să determinăm factorul de multiplicitate al lui 2 sau 5 într-un număr pe care nu-l cunoaştem? Iată o primă soluţie: parcurgem mulţimea valorilor de la 2 la n şi, pentru fiecare multiplu de 2 determinăm factorul de multiplici-tate al lui 2 în descompunerea acelui multiplu. Procedăm la fel cu valoarea 5. În plus, atenţie; nu reiniţializăm factorul de multiplicitate al lui 2 pentru fiecare nouă valoare contorizată. Vă dăm în cele ce urmează descrierea în pseudocod a algoritmului care determină factorul de multiplicitate al lui 2 în n! conform celor de mai sus: Algoritmul MultiplicitateÎnFactorial1: citeşte n fm2 ← 0 { iniţializăm cu zero factorul de multiplicitate } k ← 2 cât timp k ≤ n execută: aux ← k { determinăm contribuţia factorului k la multiplicitatea lui 2 } cât timp rest[aux/2] = 0 execută: fm2 ← fm2 + 1 aux ← [aux/2] sfârşit cât timp { ne vom deplasa din 2 în 2, deoarece ne interesează numai numerele pare } k ← k + 2 sfârşit cât timp scrie fm2 sfârşit algoritm

Page 11: 5807 Divizibilitate Si Numere Prime

78 7. Divizibilitate şi numere prime Evident, soluţia anterioară este ineficientă din punct de vedere al timpului de exe-cuţie pentru valori foarte mari ale numărului n. Ne putem gândi la o soluţie mai eficientă folosind o numărare directă pentru deter-minarea factorului de multiplicitate al unui anumit factor prim în numărul n!. Să observăm că există [n/2] multipli de 2, [n/4] multipli de 4 etc. La ce ne foloseşte această observaţie? Vom determina foarte rapid factorul de multiplicitate al lui 2 în ca-drul lui n!. Fiecare multiplu de 2 va trebui să-l numărăm o singură dată, multiplii de 4 îi vom număra de două ori, multiplii de 8 de trei ori ş.a.m.d. Numărarea se opreşte pentru o valoare a puterii lui 2 care depăşeşte numărul n dat, deoarece contribuţia lui 2nr pentru 2nr > n este nulă în calculul factorului de multiplicitate. Iată un exemplu: determinarea multiplicităţii lui 2 în cadrul lui 20! fm2 = [20/2] + [20/4] + [20/8] + [20/16] = 10 + 5 + 2 + 1 = 18 Dacă nu credeţi, calculaţi manual! Să realizăm descrierea în pseudocod a acestei variante de abordare a problemei: Algoritmul MultiplicitateÎnFactorial2: citeşte n fm2 ← 0 { iniţializăm cu zero factorul de multiplicitate } factor ← 2 { începem prin a contabiliza multiplii de 2 } cât timp factor ≤ n execută: { adunăm la multiplicitate numărul de multiplii ai lui factor } fm2 ← fm2 + [n/factor] { apoi trecem la următorul factor, în cazul nostru înmulţim cu 2 } factor ← factor*2 sfârşit cât timp scrie fm2 sfârşit algoritm În această variantă puteţi remarca două aspecte: • simplitatea implementării, care este aspectul cel mai evident; • eficienţa implementării: pentru n = 100, de exemplu, în prima variantă, numărul de

reluări 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 numărului n, îmbunătăţirea vitezei de execuţie este şi mai dramatică.

7.3.7. Conjectura lui Goldbach Conform enunţului, numărul n este număr par deci, se poate scrie sub forma 2 + (n – 2) numai dacă este egal cu 4 (4 = 2 + 2 şi 2 este număr prim). Orice alt număr par va trebui să fie scris ca o pereche de numere prime impare, deoarece (n – 2) va fi număr par mai mare decât 2 deci, neprim.

Page 12: 5807 Divizibilitate Si Numere Prime

7. Divizibilitate şi numere prime 79 O soluţie a problemei va fi orice pereche k, n – k (k + (n – k) = n) pentru care am-bele valori sunt numere prime. Deoarece nu ne interesează toate soluţiile problemei, vom utiliza următoarea strategie pentru găsirea rapidă a perechii de numere: • pornim de la k = 3 şi testăm dacă numărul k este prim, respectiv dacă este prim

numărul n – k; • dacă nu am găsit o soluţie a problemei, k ← k + 2 şi reluăm verificarea.