Sunteți pe pagina 1din 9

Limbajului C++ - Suport de curs pentru clasele 9-11, profil matematica-informatica

prof.informatica Gabriela Gligor

Probleme de baza Instructiuni C++ 1.Eliminarea cifrelor unui numar.


Enunt: Se citeste un numar de la tastatura.Sa se afiseze toate cifrele din numar. I. Partea teoretica Rezolvarea problemei se bazeaza pe eliminarea succesiva a ultimei cifre din numar cat timp mai exista cifre in numar. Deoarece in limbajul C++ sunt definiti operatorii matematici / si %,se observa ca din punct de vedere matematic: i. restul impartirii la 10 a unui numar reprezinta exact ultima cifra din acel numar Ex: n=1354 => r = n%10 = 4 ii. catul impartirii la 10 a unui numar reprezinta numarul initial din care s-a taiat ultima cifra. Ex: n=1354 => c = n/10 = 135 Deci din observatiile i. si ii. =>afisarea cifrelor unui numar este posibila in C++ parcurgand in mod repetitiv cele doua etape: 1.afisarea ultimei cifre 2.ajustarea numarului (prin eliminarea ultimei cifre). Obs: Momentul de oprire al algoritmului este cand numarul n devine 0 (n=0). II. Pasii algoritmului Pas1. daca n!=0 atunci pas 2 altfel pas3 Pas 2. scrie n%10 n=n/10 pas1 Pas 3. stop. ex: n=1354 ? da pas1. n=1354 =>n!=0 => scrie n%10 (4) ? da n=n/10 (n=135) pas 2. n=135 => n!=0 => scrie n%10 (5) ? da n=n/10 (n=13) pas3. n=13 => n!=0 => scrie n%10 (3) ? da n=n/10 (n=1) pas 4. n=1 => n!=0 => scrie n%10 (1) ? nu n=n/10 (n=0) pas 5. n=0 => n!=0 => stop. III. Secventa de program while (n!=0) { cout<<n%10; n = n/10; } //while (n) //afiseaza ultima cifra //reactualizeaza n eliminand ultima cifra deja afisata

23

Limbajului C++ - Suport de curs pentru clasele 9-11, profil matematica-informatica

prof.informatica Gabriela Gligor

2. Divizorii proprii ai unui numar


Enunt: Se da un numar n.Sa se afiseze toti divizorii proprii ai sai. I. Partea teoretica Definitie: Se numesc divizori proprii ai unui numar n,toti divizorii acestuia cu exceptia lui 1 si n. Din def. => Intervalul in care vom cauta divizorii lui n este [2,n-1]. (1) Ex: n=12 => divizorii proprii sunt {2,3,4,6} => toti divizorii proprii sunt <= n/2.(2) n/2 n

0 1 2 3 4 5 6 ..12 Din (1) si (2) => intervalul de cautare al divizorilor proprii ai lui n este [2,n/2]. Algoritmul consta in: -parcurgerea intervalului [2,n/2] cu ajutorul unui contor i si -verificarea fiecarei valori i daca este divizor sau nu al lui n II. Pasii algoritmului pas1. i = 2 pas2. daca i<=n/2 atunci pas3 altfel pas5 pas3. daca n%i = = 0 atunci scrie i pas4 altfel pas4 pas4. i=i+1 pas2 pas5.stop Ex: n=12
? da ? da

p1. i=2 => i<=n/2 => n%i= =0 => scrie i (2) 2 6 12 2 i=i+1 (i=3)
? da ? da

p2. i=3 => i<=n/2 => n%i= =0 => scrie i (3) 3 6 12 3 i=i+1 (i=4)
? da ? da

p3. i=4 => i<=n/2 => n%i= =0 => scrie i (4) 4 6 12 4 i=i+1 (i=5)
? da ? nu

p4. i=5 => i<=n/2 => n%i= =0 => i=i+1 (i=6)


5 ? 6 da 12 5 ? da

p5. i=6 => i<=n/2 => n%i= =0 => scrie i (6) 6 6 12 6 i=i+1 (i=7)
nu

p6. i=7 =>i<=n/2 => stop.


7 6

III. Secventa de program for(i=2;i<=n/2;i++) if (n%i = = 0) cout<<i<< ; //se parcurge cu i intervalul [2,n/2] //se verifica daca i este divizor al lui n

24

Limbajului C++ - Suport de curs pentru clasele 9-11, profil matematica-informatica

prof.informatica Gabriela Gligor

3. Numar prim
Enunt. Se da un numar n .Sa se afiseze un mesaj corespunzator daca numarul este prim sau nu. I. Partea teoretica Definitie: un numar este prim daca si numai daca are ca divizori pe 1 si el insusi. din def. => ca un numar este prim daca nu are nici un divizor propriu => nu exista nici un divizor oricare ar fi i [2,n/2]. Stim ca orice numar este un produs de 2 factori n=n1*n2 unde n1,n2 [2,n/2]=>deoarece este suficient sa gasim un divizor, adica n1 ca sa demonstram ca n nu e prim=> ca nu e necesar sa parcurgem tot intervalul [2,n/2]=>intervalul de cautare a unui divizor va fi intervalul corespunzator divizorului n1 adica [2, n ].

De ce [2, n ] ? Ex: fie n=6 => Cazuri 6= 2*3 , n1=2 n2=3 6=3*2 , n1=3 n2=2
2

n1

n2

n/2

n=6

Atunci cand n1=n2 => n=n12 => n1= n

Rezolvarea problemei: Parcurgem cu un contor i intervalul [2, n ] in speranta ca nu vom gasi nici un divizor=>Intrebarea ar fi :ce se intampla daca totusi gasesc un divizor? =>avem nevoie de o variabila logica ok cu care sa punem in evidenta daca am gasit sau nu un divizor=> initial ok=1 (adica presupunem ca n este prim) si daca vom gasi cel putin un divizor atunci ok=0 (adica presupunerea facuta initial ca n este prim este falsa). (1) Din (1) => ca daca gasim cel putin un divizor deja stim ca n nu mai este prim =>numai are rost sa parcurgem restul intervalului
=> conditia de cautare a primului divizor este: i <= n && ok= = 1. II. Pasii algoritmului pas1. ok=1, i=2 pas2 pas2. daca i <= n && ok=1 =>pas3 altfel pas6 pas3. daca n mod i=0 =>pas4 altfel pas5 pas4. ok=0 =>pas5 pas5. i=i+1 =>pas2 pas6.daca ok=0 scrie nu e nr. prim altfel scrie nr. e prim Ex1: n=12
2
12 12 2

da

da

p1. ok=1,i=2 => i <= n && ok=1=> n%i=0 => ok=0,i=i+1(3) p2. ok=0, i=3 => i <= n && ok=1=> ok=0=> scrie nu este nr.prim da
3 12

Ex2: n=13

13

13 2 da nu

p1. ok=1,i=2 => i <= n && ok=1=> n%i=0 => i=i+1(3)


3 13 da 13 3 nu

p2. ok=1, i=3 => i <= n && ok=1=> n%i=0 =>i=i+1(4)


4 13 nu nu

p3. ok=1, i=4 => i <= n && ok=1=> ok=0 => scrie nr. prim III. Secventa de program for (i=2,ok=1; i<= n && ok; i+ +) //se parcurge cu contorul i intervalul [2, n ] cat timp nu s-a gasit nici un divizor if (n%i = = 0) // se verifica daca i este divizor ok=0; //daca este i divizor atunci presupunerea facuta (ok=1) ca n este prim devine falsa adica ok=0 if(ok) // daca nu s-a gasit nici un divizor(ok=1),deci presupunerea ca n este prim a ramas adevarata cout<<nr.prim; else cout<<nr. nu e prim;

25

Limbajului C++ - Suport de curs pentru clasele 9-11, profil matematica-informatica

prof.informatica Gabriela Gligor

4. C.m.m.d.c. (Algoritmul lui Euclid)


Enunt: Fiind date doua numere naturale sa se calculeze c.m.m.d.c. al acestora. I. Partea teoretica

Enunt(Algoritmul lui Euclid): Se executa impartiri succesive pana cand restul devine 0. C.m.m.d.c. este ultimul impartitor obtinut.Initial deimpartitul si impartiorul sunt numerele citite, apoi deimpartitul devine impartitorul din impartirea anterioara, iar impartitorul devine restul din impartirea anterioara.
II. Pasii algoritmului si Secventa de program Se disting 4 cazuri: Caz 1. a>b Ex: a=30 b=14 I. 30: 14 = 2 28 --=2 p1. d=a(30) i=b(14) r=d%i=2 d=i(14) i=r(2) II. 14: 2 = 7 14 ---=0 p2. d=14 i=2 r=d%i=0 => c.m.m.d.c.=2

Secventa de program corespunzatoare: d=a; i=b; while(d%i!=0) { r=d%i; d=i; i=r; } cout<<cmmdc=<<i; Caz 2. a<b Ex: a=14 b=30 I. 14: 30 = 0 0 --=14 II. 30: 14 = 2 28 ---=2 III. 14: 2 = 7 => c.m.m.d.c.=2 14 ---=0 for(d=a, i=b; d%i !=0; r=d%i, d=i, i=r); cout<<cmmdc=<<i;

p1. d=a(14) p2. r=d%i=2 p3. d=14 i=b(30) d=i(14) i=2 r=d%i=14 i=r(2) r=d%i=0 d=i(30) i=r(14) Obs: Se observa ca acest caz este similar cu caz1(a>b) cu deosebirea ca apare un pas suplimentar care are ca efect inversarea valorilor din a si b. Deci caz 2 se reduce la caz 1 dupa ce se efectueaza o impartire suplimentara.=> secventa de program de la cazul 1 este valabila si pentru cea de la cazul 2. Caz 3. a=0 b0 Ex: a=0 b=14 Se stie din matematica, ca c.m.m.d.c.(0,b)=b (cmmdc dintre 0 si orice numar diferit de 0 este acel numar). Ne propunem sa verificam daca algoritmul lui Euclid rezolva aceasta situatie.

26

Limbajului C++ - Suport de curs pentru clasele 9-11, profil matematica-informatica

prof.informatica Gabriela Gligor

I. 0: 14 = 0 0 --=0

=> c.m.m.d.c.=14

p1. d=a(0) i=b(14) r=d%i=0 Se observa ca acest caz particular este rezolvat cu succes de algoritm=> secventa de program de la cazul 1 este aplicabila si in acest caz. Caz 4. a 0 b=0 Ex: a=14 b=0 Se stie din matematica, ca: cmmdc(a,0) este a (1) Oare algoritmul lui Euclid rezolva acest caz particular? I. 14: 0 = imposibil => aparent algoritmul este impracticabil DAR.. Conform teoriei matematice cmmdc(14,0) ar trebui sa fie 14 adica deimpartitul. Presupunem ca a=28 b=14 I. 28:14= 2 II. 14:0=imposibil 28 cmmdc ---=0 p1. d=a(28) i=b(14) r=d%i=0 d=i(14) i=0 Teoretic Euclid spune ca algoritmul se incheie atunci cand restul devine 0 si cmmdc este impartitorul=> daca vom forta algoritmul cu inca un pas se observa ca se ajunge tocmai la cazul 4 in care deimpartitul este tocmai cmmdc=>deci regula matematica cmmdc(a,0)=a este indeplinita => algoritmul lui Euclid rezolva si cazul4. Deci algoritmul lui Euclid rezolva toate cazurile cu conditia sa aducem le aducem pe toate pana la cazul 4=>conditia de oprire a algoritmului va fi ca impartitorul sa fie zero(restul din impartirea precedenta pentru cazurile 1,2,3), iar deimpartitul(impartitorul din impartirea precedenta) va fi cmmdc. Secventa de program valabila oricare ar fi a si b este: d=a; i=b; while(i!=0) { r=d%i; d=i; i=r; } cout<<cmmdc=<<d; for(d=a, i=b; i !=0; r=d%i, d=i, i=r); cout<<cmmdc=<<d;

5. C.m.m.d.c. (Functia recursiva)


Enunt: Fiind date doua numere naturale sa se calculeze c.m.m.d.c. al acestora. I. Partea teoretica Se da functia matematica: cmmdc(a-b,b) , a>b a sau b , a=b cmmdc(a,b-a) , a<b

cmmdc(a,b)=

ex: a=12 b=18 cmmdc(12,18)=cmmdc(12,6)=cmmdc(6,6)=6 => cmmdc=6.

27

Limbajului C++ - Suport de curs pentru clasele 9-11, profil matematica-informatica

prof.informatica Gabriela Gligor

Rezolvarea problemei presupune scaderi repetate fie din a (daca a>b) fie din b(daca b>a) pana cand a=b moment in care algoritmul se termina => cmmdc va fi a sau b(a=b).Cazurile particulare a=0,b0 si a0,b=0 se trateaza separat de algoritm. II. Pasii algoritmului pas1. daca a=b pas5 altfel pas 2 pas2. daca a>b pas 3 altfel pas 4 pas3. a=a-b pas1 pas4. b=b-a pas1 pas5. scrie a (b) Ex: a=12 b=18 12 18 nu 12 18 nu p1. a=12, b=18 => a=b=> a>b => b=b-a=6
12 6

nu

12

6 da

p2.a=12,b=6 =>a=b => a>b => a=a-b=6


6 6 da

p3.a=6,b=6=>a=b=> scrie cmmdc=a=6 =>stop. III. Secventa de program if (a= =0 || b= =0) //daca a=0 sau b=0 cmmdc este suma lor(cazurile particulare) cout<<cmmdc=<<a+b; else { while(a!=b) // cat timp ab se executa algoritmul if (a>b) a- =b; else b- =a; cout<<cmmdc=<<a; }

6. Descompunerea unui numar in factori primi


Enunt: Fiind dat un numar, sa se afiseze factorii primi din descompunerea acestuia. I. Partea teoretica Prin factori primi ai unui numar intelegem toti divizorii primi ai acelui numar. Conform algoritmilor invatati anterior ar trebui sa parcurgem intervalul [2,n/2] al divizorilor proprii ai unui numar n dat din care sa afisam doar acei divizori care sunt si primi=>fiecare posibil divizor trebuie sa indeplineasca 2 conditii: - sa fie divizor - sa fie prim Metoda este ineficienta drept urmare sa ne amintim cum determinam matematic factorii primi ai unui numar!!!!! Ex: n=180=22*32*51 factorii primi [2,180] 180 2 90 2 45 3 15 3 5 5 1 stop Metoda consta in impartiri repetate la factorii primi gasiti ceea ce face ca toti multiplii acestora sa fie eliminati dintre posibilii divizori ai numarului dat. Acest avantaj face ca posibilii divizori sa fie doar numere prime.Un avantaj major al acestei metode este ca primii posibili divizori , 2 si 3, sunt numere prime. Rezolvarea problemei presupune: - parcurgerea intervalului de posibili divizori cu un contor i incepand de la 2,primul numar prim, cat timp numarul ramas pentru descompunere este diferit de 1. - identificarea divizorului prim si afisarea acestuia - impartirea repetata a numarului la divizorul prim gasit excluzandu-se astfel din intervalul [2,n/2] divizorii multipli ai acelui divizor.

28

Limbajului C++ - Suport de curs pentru clasele 9-11, profil matematica-informatica

prof.informatica Gabriela Gligor

II. Pasii algoritmului pas1. i=2 pas2. daca n!=1 atunci pas3 altfel pas6 pas3. daca n%i= =0 atunci scrie i =>pas4 altfel pas5 pas4. daca n%i= =0 atunci n=n/i =>pas4 altfel pas5 pas5. i=i+1 =>pas2 pas6.stop Ex: n=180 180 da 180 2 da 180 2 da 180 2 da 90 2 da 90 2 45 2 nu p1. i=2,n=180 => n!=1 => n%i= =0 => scrie 2 =>n%i= =0 => n=n/i=90=> n%i= =0 => n=n/i=45=> n%i= =0 => i=i+1=3
da 45 3 da 45 3 da 45 3 da 15 3 da 15 3 5 3 nu

p2. i=3,n=45 => n!=1 => n%i= =0 => scrie 3 =>n%i= =0 => n=n/i=15=> n%i= =0 => n=n/i=5=> n%i= =0 => i=i+1=4
da 5 4 nu

p3. i=4,n=5 => n!=1 => n%i= =0 => i=i+1=5


da 5 5 da 5 5 da 5 5 1 5 nu

p4. i=5,n=5 => n!=1 => n%i= =0 => scrie 5 => n%i= =0 => n=n/i=1=> n%i= =0 =>i=i+1=6
nu

p5.i=6,n=1 => n!=1 => stop.

III. Secventa de program for(i=2; n!=1; i++) // se parcurg divizorii lui n ,incepand de la primul numar prim(2),cat timp acesta se mai poate descompune if (n%i= =0) //daca i este divizor atunci se afiseaza si se imparte succesiv numarul la el eliminandu-se astfel toti multipli lui { cout<<i<< ; while (n%i= =0) n/=i; }

7. Conversia din baza 10 in baza q .


Enunt: Se citeste de la tastatura un numar natural n si un numar q, q [2,9]. Sa se afiseze reprezentarea lui n in baza q.
I. Partea teoretica

Enunt(Algoritmul lui Euclid)- Conversia unui numar n, in baza q, presupune impartirea repetata a lui n la q pana cand catul impartirii este 0. Noul numar nq, obtinut din conversia numarului n in baza q, este alcatuit din resturile obtinute in urma impartirilor repetate luate in ordinea inversa realizarii lor(nq=rk-1rk-2..r1r0) unde k-numarul de cifre din nq.
Ex: n(10) nq(q) n=13 q=2 cf.Algoritmului lui Euclid =>

=> nq= r3r2r1r0 =1101(2) Rezolvarea problemei consta in: - impartirea repetata a lui n la q pana cand catul(ce va deveni noul n) este 0. - construirea progresiva a lui nq(de la pas la pas). Obs.1.La fiecare pas dupa impartire catul obtinut din impartirea curenta va deveni in pasul urmator noua valoare a lui n. 2.Se necesita a se determina o formula de calcul a lui nq. 3.Initial nq=0.

29

Limbajului C++ - Suport de curs pentru clasele 9-11, profil matematica-informatica

prof.informatica Gabriela Gligor

II. Pasii algoritmului


13 da 13 2

pas1.n=13, q=2,nq=0 => n!=0 => nq=r0=1 , n=n/q=6


6 da 0 1 0 1 0 6 2

pas2.n=6,q=2,nq=r0=1 => n!=0 => nq=r1r0=r1*10+r0=r1*10+nq=01 , n=n/q=3


3 da 1 0 1 1
2

0 1

1
2

pas3.n=3,q=2,nq= r1r0=1 => n!=0 => nq= r2r1r0=r2*10 + r1r0=r2*10 +nq=101 , n=n/q=1
1 da 1 1 0 1 1
3

1 0 1

1
3

101

1 2

pas4.n=1,q=2,nq= r2r1r0=101 => n!=0 => nq= r3r2r1r0= r3 *10 + r2r1r0= r3 *10 +nq=1101 , n=n/q=0
nu

pas5.n=0,q=2,nq= r3r2r1r0=1101 => n!=0 =>scrie 1101 Nota: 1.Se observa ca formula de calcul a lui nq este:

nq=r*10i-1+nq
unde i [1,k] k- numarul de cifre a lui nq(numarul de impartiri) . r- al i-lea rest obtinut din impartirea lui n la q.

2.Pentru a putea calcula in mod eficient 10k vom folosi o variabila p in care se vor calcula in mod iterativ (de la un pas la altul) puterile lui 10. Initial p=1(100) iar formula de calcul a lui p va fi: p=p*10 =>formula de calcul a lui nq este:

nq=r*p+nq
Algoritmul pe pasi este: p1.nq=0,p=1 p2.daca n!=0 atunci p3 altfel p4 p3.nq=n%q *p + nq n=n/q p=p*10 => p2 p4.scrie nq III. Secventa de program nq=0; //initial nq=0 p=1; //initial p=1=100 while(n!=0) { nq=n%q+nq; n=n/q; p=p*10; //creste puterea pentru pasul urmator // p=10k+1=10k*10 } cout<< nq; for(nq=0,p=1 ; n!=0 ; nq=n%q*p+nq, n/=q, p*=10) ; cout<< nq;

8. Conversia din baza q in baza 10


Enunt: Se citeste de la tastatura un numar nq care este reprezentarea unui numar in baza q, q [2,9]. Sa se afiseze numarul in baza 10, corespunzator celui citit. I. Partea teoretica Orice numar nq in baza q se poate transforma in baza 10 folosind urmatoarea fomula:

nq= rk-1rk-2..r1r0 = rk-1*qk-1+ rk-2*qk-2+ rk-3*qk-3+.+ r2*q2+ r1*q1+ r0*q0 =


unde k-numarul de cifre din nq. Ex: nq=10101 => n=1 *24+ 0*23+ 1*22+ 0*21+ 1*20 =16+ 0+ 4+ 0+ 1=21 Deci: 10101(2) 21(10)

30

Limbajului C++ - Suport de curs pentru clasele 9-11, profil matematica-informatica

prof.informatica Gabriela Gligor

Obs. 1. Calculul numarului in baza 10 se poate face iterativ(pas cu pas) prin calculul unei sume de termeni. 2. Fiecare termen al sumei este alcatuit dintr-o cifra a numarului nq si o putere a lui q. 3. Deoarece cifrele lui nq se pot obtine prin algoritmul de eliminare a cifrelor => primul termen din suma va fi : r0*q0 => formula generala de calcul a lui n va fi :

n=ri-1*qi-1 +n
unde i [1,k] , k-numarul de cifre din nq 4. Calculul puterii lui q ( qk-1=q*qk-2 ) se va face tot iterativ folosind o variabila p astfel: p=q0=1(initial) p=p*q (in caz general) => formula generala de calcul a lui n va fi :

n=ri-1*p +n
unde i [1,k] , k-numarul de cifre din nq
Rezolvarea problemei consta in:-extragerea fiecarei cifre din nq cat timp nq!=0 si -calculul sumei, prin adaugarea noului termen Nota: La fiecare pas se aduna un termen de forma : ri-1*p , unde p=q II. Pasii algoritmului p1. p=1,n=0 p2.daca nq!=0 atunci p3 altfel p4 p3.n=nq%10*p+n p=p*q nq=nq/10 =>p2 p4. scrie n Ex: nq=10101 da 1 1 0 pas1.nq=10101, n=0, p=20=1 => nq!=0 => n=nq%10*p+n=1,
da 0 2 1 1 2

i-1

si ri-1 cifra extrasa de pe pozitia i din nq.

p=p*q=1*2=21,
2 2

nq=nq/10=1010 nq=nq/10=101 nq=nq/10=10 nq=nq/10=1

pas2.nq=1010, n=1,p=21 => nq!=0 => n=nq%10*p+n=0*21+1=1, p=p*q=21*2=22,


da 1 4 1 4 2

pas3.nq=101, n=1,p=22 => nq!=0 => n=nq%10*p+n=1*22+1=5, p=p*q=22*2=23,


da 0 8 5 8 2

pas4.nq=10, n=5,p=23 => nq!=0 => n=nq%10*p+n=0*23+5=5,


da 1 16 5

p=p*q=23*2=24,
16 2

pas5.nq=1, n=5,p=24 => nq!=0 => n=nq%10*p+n=1*24+5=21, p=p*q=24*2=25, nq=nq/10=0


nu

pas6.nq=0, n=21,p=2 => nq!=0 => scrie 21 III. Secventa de program n = 0; //initial n=0 p = 1; //initial p=20=1 while(nq!=0) { n = nq%10 * p + n; //se calculeaza n ca o suma p * = q; //creste puterea p nq / =10; //se elimina ultima cifra din nq } cout<< n; for(n=0,p=1; nq!=0 ; n=nq%10*p+n, p*=q, nq/=10) ; cout<< n;

31

S-ar putea să vă placă și