Sunteți pe pagina 1din 7

1. Verificarea dacă un număr divide alt număr.

În acest caz pentru a verifica dacă m se divide cu n trebuie să


calculăm restul împărţirii cu rest a lui m la n. Dacă acesta este 0 înseamnă că m se divide cu n ,altfel nu.
Pentru aceasta utilizăm în algoritm o linie în care scriem :
if(m%n = =0)
{….}
Ex : Scrieţi o secvență ce poate fi utilizată pentru a testa dacă numărul a se divide cu numărul b , unde valori
pentru a şi b se citesc de la tastatură.
Rezolvare: cin>>a>>b;
if(a%b = =0) cout<<”a se divide cu b”;
else cout<<”a nu se divide cu b”;
2. Pentru a calcula suma unor elemente
În cazul unor probleme în care ni se cere să calculăm suma unor elemente, trebuie în mod obligatoriu să
utilizăm o variabilă s iniţializată cu 0(termenul neutru de la adunare), iar apoi la s vom aduna câte un
element , reţinând valoarea sumei tot în s.
Adică trebuie să avem :
s=0;
…………
s=s+element;
Ex. Pentru a calcula suma primelor n numere naturale vom scrie scrie secvența:
cin>>n;
s=0;
for(i=1;i<=n;i++) s=s+i;
cout<<s;
3. Pentru a calcula produsul unor elemente
În cazul unor probleme în care ni se cere să calculăm produsul unor elemente, trebuie în mod obligatoriu
să utilizăm o variabilă p iniţializată cu 1(termenul neutru de la înmulţire), iar apoi vom înmulţi valoarea lui p
cu valoarea elementului actual , reţinând valoarea produsului tot în p.
Adică trebuie să avem :
p=1;// deoarece 1 este termenul neutru pentru operația matematică de înmulțitre
…………
p=p*element;
Ex. Pentru a calcula suma primelor n numere naturale vom scrie secvența:
cin>>n;
p=1;
for(i=1;i<=n;i++) p=p*i;
cout<<p;
4. Parcurgerea unui interval
Pentru a parcurge un interval [a;b] avem secvența:
for(i=a;i<=b;i++)
{........................
// se prelucrează i conform cerinței din enunț
}
5. Verificarea faptului că o valoare se află într-un interval
Pentru a verifica dacă o valoare i se află în intervalul [a;b] avem secvența:
if(i>=a&&i<=b)
// se consideră că i este în interval și se prelucrează conform enunțului
6. Probleme care operează asupra cifrelor unui număr
Există o serie de probleme în care trebuie să acţionăm asupra cifrelor unui număr natural, cum ar fi
calculul sumei cifrelor sale. În acest caz avem nevoie de fiecare cifră a numărului pe rând. Pentru acesta
aflăm iniţial valoarea ultimei cifre aflând restul împărţirii numărului la 10. Ulterior scăpăm de cifra
prelucrată atribuind numărului valoarea restului împărţirii lui la 10 peste N. Cele două operaţii se repetă
până la epuizarea tuturor cifrelor numărului, adică până ce acesta devine 0. Pentru un număr natural n din
astfel de probleme nu poate lipsi modulul:
while(n>0){cif=n%10;
n=n/10;
// operațiile cerute
}
Obs:
1) Există cazuri în care numărul iniţial ne mai trebuie pentru alte operaţii. În acest caz, înainte de a prelua
cifrele acestuia trebuie mai întâi să facem o copie a acestuia, pentru a prelucra cifrele ei şi nu ale
numărului original.
2) Algoritmul prelucrează cifrele numărului începând cu cifra de pe poziţia unităţilor, şi continuă
prelucrarea prin eliminarea în pemanenţă a ultimei cifre a ceea ce a mai rămas din număr.
De exemplu a calcula suma cifrelor unui număr natural avem secvența :
cin>>n;
s=0;
while(n>0){cif=n%10;
s=s+cif;
n=n/10;
}
cout<<s;
Unde s este suma cifrelor numărului natural n. Valoarea iniţială a acesteia este 0, ulterior aflând cate o cifră
a numărului pe care o adăugăm la fiecare pas la valoarea sumei.
O altă problemă constă în obținerea oglinditului ( răsturnatului ) unui număr natural.
Pentru această problemă avem secvența:
cin>>n;
og=0;
while(n>0){cif=n%10;
og=og*10+cif;
n=n/10;
}
Dacă se cere să verificăm dacă un număr este palindrom, atunci verificăm dacă og are aceeași valoare ca
numărul inițial n. Avem secvența:
cin>>n;cn=n;
og=0;
while(cn>0){cif=cn%10;
og=og*10+cif;
cn=cn/10;
}
if(n==og)//se execută instrucțiunile pentru n palindrom
Pentru a construi un alt număr ce are aceleași cifre cu originalul și în aceeași ordine, dar luăm în
considerare doar anumite cifre avem secvența:
cin>>n;
nrn=0;// numărul nou se inițializează cu 0, deoarece nu există
p=1;// se pornește de la 10 la puterea 0
while(n>0){cif=n%10;
n=n/10;
if(/*cif este bun de adăugat la noul număr conform enunțului*/)
{nrn=nrn+p*cif;
p=p*10;}
}
//în acest moment nrn reține cifrele cerute din n conform enunțului
7. Găsirea celui mai mare element dintr-o mulţime de elemente
O altă problemă constă în determinarea celui mai mare element dintr-o mulţime de elemente date. În
cazul unor astfel de probleme trebuie să utilizăm o variabilă max iniţializată cu valoarea primului element al
mulţimii. Ulterior se compară valoarea lui max cu fiecare dintre celelalte elemente, iar dacă vreun element
are valoarea mai mare ca a lui max atunci max va reţine valoarea elementului respectiv. Avem:
maxi=primul element;
while(mai există elemente){
if(maxi < elementul curent) maxi=elementul curent;}
Ex. Secvența ce determină cea mai mare cifră a unui număr natural n este:
cin>>n;
maxi=n%10;
n=n/10;
while(n>0){ c= n%10;
n= n/10;
if(maxi< c) maxi=c;
}
cout<<maxi;
8. Găsirea celui mai mic element dintr-o mulţime de elemente
O altă problemă constă în determinarea celui mai mic element dintr-o mulţime de elemente date. În cazul
unor astfel de probleme trebuie să utilizăm o variabilă min iniţializată cu valoarea primului element al
mulţimii. Ulterior se compară valoarea lui min cu fiecare dintre celelalte elemente, iar dacă vreun element
are valoarea mai mică decât cea a lui min atunci min va reţine valoarea elementului respectiv. Avem:
mini=primul element;
while(mai există elemente){
if(mini > elementul curent) mini=elementul curent;}
Ex. Să determinăm cea mai mică cifră a unui număr natural n
cin>>n;
mini=n%10;
n=n/10;
while(n>0){ c= n%10;
n= n/10;
if(mini>c) mini=c;
}
cout<<mini;
9. Probleme în care trebuie să numărăm elemente ce îndeplinesc o condiţie
În cazul unor probleme în care ni se cere să numărăm câte elemente îndeplinesc o anumită condiţie,
trebuie în mod obligatoriu să utilizăm o variabilă nr iniţializată cu 0(la început nu am găsit nici un element),
iar apoi la dacă vom găsi un element care satisface condiţia vom creşte valoarea lui nr cu o unitate.
Adică trebuie să avem :
nr=0;
…………
if(condiţie)
nr++;
Ex. Număraţi câte cifre pare are un număr natural n a cărui valoare se citeşte de la tastatură:
cin>>n;
nr=0;
while(n>0){c=n%10;
n=n/10;
if(c%2 = =0) nr++;}
cout<<nr;
Este posibil să nu trebuiască să fie îndeplinită o anumită condiţie, ca în exemplul de mai jos de unde dispare
condiția pentru creșterea valorii nr.
Ex. Număraţi câte cifre are un număr natural n a cărui valoare se citeşte de la tastatură:
cin>>n;
nr=0;
while(n>0){c=n%10;
n=n/10;
nr++;}
cout<<nr;
10. Probleme în care trebuie să verificăm dacă este îndeplinită o condiţie sau nu
În cazul unor probleme în care ni se cere să verifică dacă este îndeplinită sau nu o condiţie de către anumite
elemente, trebuie în mod obligatoriu să utilizăm o variabilă ok de tip logic iniţializată cu adevărat(se
presupune iniţial că relaţia este îndeplinită), iar apoi verificăm dacă fiecare element satisface într-adevăr
condiţia. Dacă întâlnim un element ce nu satisface condiţia ok devine fals.
Adică trebuie să avem :
ok=1;// presupunem că e îndeplinită condiția pentru toate elementele
…………
while(mai există elemente){
……………………
if(există un element ce nu satisface relaţia din enunț) ok=0;// nu mai îndeplinesc toate elementele condiția
…………..
}
Ex. Se citeşte un număr natural n strict mai mare decât 1. Verificaţi dacă toate cifrele sale sunt impare.
cin>>n;
ok=1;
while(n>0){c=n%10;
n=n/10;
if(c%2==0)ok=0;
}
if(ok= =1) cout<<”n este prim”;
else cout<<”n nu este prim”;
11. Divizibilitate, numere prime
Să se verifice dacă numărul întreg n este prim sau nu. Se testează, mai întâi dacă el este 0 sau 1. Apoi se
împarte n la toate numerele d până la jumătatea lui n. Dacă în intervalul [2, n/2] există un divizor d, atunci
numărul nu este prim, altfel este prim. Faptul că numărul este prim sau nu, se va memora folosind variabila
logică prim.
cin>>n;
if(n<2) prim=0;
else prim=1;
for(d=2;d<=n/2;d++)
if(n%d= =0) prim=0;
if(prim= =1) cout<<”numărul este prim”;
else cout<<”numărul nu este prim”;
12. Algoritmul lui Euclid
Este utilizat pentru calculul cmmdc a două numere naturale. În C++, se prezintă sub forma:
cin>>a>>b;
if(a>b){d=a;
i=b;}
else{d=b;
i=a;}
while(i>0){r=d % i;
d=i;
i=r;}
cout<< d;
La sfârşitul execuţiei algoritmului valoarea lui d va avea valoarea cmmdc al celor două numere. Această
variantă a algoritmului lui Euclid se numeşte şi algoritmul lui Euclid prin împărţiri repetate.
Există şi o variantă a algoritmului lui Euclid ce utilizează scăderi repetate, aceasta prezentându-se sub
forma:
cin>>a>>b;
while(a!=b)
if(a>b)a=a-b;
else b=b-a;
cout<<a;
La sfârşitul execuţiei acestui algoritm ambele variabile vor avea valoarea egală cu cmmdc-ul celor două
numere.
Observaţie: Algoritmii pot fi utilizaţi şi pentru a testa dacă două numere sunt prime între ele sau nu. Dacă
numerele sunt prime între ele cmmdc va avea valoarea 1.
13. Şirul lui Fibonacci
Este un şir de numere întregi a1, a2, a3, . . . definit în felul următor:
a1=1, a2=1, an=an-1 + an-2, pentru orice n3.
O astfel de definiţie, în care un anumit termen se construieşte din termeni anterior determinaţi, se numeşte
definiţie recurentă. Pentu a determina al n-lea termen al şirului lui Fibonacci, va trebui să determinăm toţi
termenii până la n-1 inclusiv. Vom folosi trei variabile: t2, t1, t, corespunzătoare termenilor an-2, an-1 şi an.
cin>>n;
if(n= =1 || n= =2) t=1;
else{
t2=1;
t1=1;
i=2;
while(i<n){t=t2+t1;
t2=t1;
t1=t;
i=i+1;}
}
cout<<”Termenul cerut este :”<<t;
14. Citirea și prelucrarea unui șir de n valori
Se citește numărul n de valori, apoi se citește pa rând câte o valoare în x ce se prelucrează. Avem secvența:
cin>>n;
for(i=1;i<=n;i++)
{........................
cin>>x;
// se prelucrează x conform cerinței din enunț
}
15. Citirea și prelucrearea unui șir de valori ce se termină cu introducerea unei valori 0
Se citește o primă valoarea, apoi cât timp nu s-a ajuns la o valoare 0, se prelucrează valoarea curentă și se
citește din nou x oentru următorul pas.
cin>>x;
while(x!=0)
{........................
// se prelucrează x conform cerinței din enunț
cin>>x;
}

Majoritatea problemelor simple se prezintă ca o sumă de mai multe probleme dintre cele prezentate anterior.
16. Determinarea tuturor factorilor primi ai unu număr natural n
d=2;
while(n>1){
if(n%d==0){p=0;
while(n%d==0){p++; n=n/d;}
// în acest moment d este un divisor prim, iar puterea la care acesta apare în descompunerea lui n
}
d++;
}

Metoda backtracking
Prezentare
Acesta metodă se utilizează pentru rezolvarea unor probleme ale căror soluţii se prezintă sub forma unui
vector x=x1,x2,....,xn,cu x1M1, x2M2, xnMn. Mulţimile M1, M2 ,.......,Mn sunt finite şi elementele lor se
află într-o relaţie de ordine bine stabilită.
Având în vedere că ne interesează toate soluţiile problemei, o modalitate ar fi să generăm produsul
cartezian al mulţimilor M1 *M2 *.........*Mn ,iar de aici să ne alegem soluţiile prin verificare directă. Dacă
acest lucru poate fi realizat în cazul în care problema are puţine soluţii candidat ,pentru probleme a căror
mulţime de soluţii candidat este foarte mare acest lucru este practic imposibil datorită timpului foarte mare
de execuţie al algoritmului.
O altă modalitate constă în utilizarea unei stive care să conţină pe fiecare nivel al său câte un element al
unei posibile soluţii, fiecare element fiind ales din câte o mulţime în aşa fel încât să se obţină la un moment
dat o soluţie parţială a problemei. În momentul în care se obţine utilizând această modalitate o soluţie a
întregii probleme aceasta va fi afişată şi se va trece la căutarea următoarei soluţii. Deşi şi în acest caz timpul
necesar obţinerii soluţiilor este foarte mare, totuşi el este mai mic decât în cazul produsului cartezian.
Concret se alege un element x1M1 care este valid şi se plasează pe primul nivel al stivei… Considerând
generată o soluţie parţială a problemei x1, x2,…, xk vom căuta să adăugăm pe stivă conform metodei descrise
un element xk+1Mk+1. Există două posibilităţi:
a) Există un element xk+1Mk+1 astfel încât x1, x2,…, xk,xk+1 să fie o soluţie parţială a problemei. În acest
caz se verifică dacă x1, x2,…, xk,xk+1 reprezintă o soluţie a întregii probleme, caz în care se va afişa
soluţia. Dacă nu se consideră generată soluţia până la nivelul k+1 şi se trece conform algoritmului la
alegerea unui element xk+2Mk+2.
b) Nu există nici un element xk+1Mk+1 astfel încât x1, x2,…, xk,xk+1 să fie o soluţie parţială a problemei. În
acest caz se consideră generată soluţia x1, x2,…, xk-1 şi se coboară la nivelul k, căutându-se un alt
element care să poată fi o soluţie parţială, începând cu succesorul lui xkMk ales înainte.
Algoritmul se încheie odată ce au fost epuizate toate elementele lui M1.
Recursivitate
Spunem despre o entitate că este definită recursiv dacă pentru definirea ei se apelează la o altă entitate de
acelaşi tip. Concret despre un algoritm spunem că este recursiv dacă pe parcursul execuţiei sale se
autoapelează. Un proces recursiv este finit atunci când încheierea sa se face după un număr finit de operaţii
executate.
Orice algoritm recursiv se poate considera că are două componente una în care se efectuează anumite
prelucrări urmate de apelul recursiv şi o condiţie de terminare a recursivităţii, adică un caz pentru care se
încheie procesul recursiv. Pentru a se ajunge la condiţia de încheiere a procesului recursiv este necesar ca
parametrii ce apar în cadrul apelului recursiv să tindă spre valorile care sunt tratate în condiţia de încheiere.
Există două tipuri de recursivitate:
1. Recursivitate directă
În acest caz există un singur subprogram care se apelează în mod recursiv.
2. Recursivitate indirectă( mutual recursivitate )
În acest caz există cel puţin două subprograme care se apelează unul pe celălalt în mod recursiv. Adică
dacă avem de exemplu două subprograme A şi B, A îl apelează pe B, iar B îl apelează pe A în mod repetat.
Ambele subprograme au o structură recursivă.
Trebuie ştiut că în momentul apelului recursiv toate variabilele globale şi locale utilizate în subprogramul
recursiv se salvează pe stiva pusă la dispoziţie de compilator. Excepţie fac parametrii formali ai
subprogramului care sunt transmişi prin referinţă, valorile acestora nefiind salvate. Pe lângă aceste valori se
mai salvează pe stivă şi o adresă de revenire în subprogram, adică adresa instrucţiunii ce se va executa
imediat după revenirea din apelul recursiv.
Un algoritm recursiv ni-l putem imagina ca acţionând în două etape: în prima efectuează toate operaţiile
până în momentul apelului recursiv, salvând valorile obţinute pe stivă în momentul apelului recursiv.
Această etapă se poate considera că ţine până în momentul în care s-a ajuns la condiţia de încheiere a
algoritmului, rezolvându-se şi acest caz. În a doua etapă se revine cu valorile obţinute în momentul în care s-
a ajuns la condiţia de încheiere şi coboară nivel cu nivel până se goleşte stiva, efectuându-se la fiecare pas
operaţiile care au mai rămas de efectuat din subprogramul respectiv. Doar după terminarea celor două etape
se obţine rezultatul final pentru o astfel de problemă.
Un algoritm recursiv este mare consumator de resurse, deoarece salvează pe parcursul execuţiei sale
foarte multe valori pe stivă. De aceea se recomandă utilizarea unui algoritm recursiv doar în cazurile în
cazurile în care nu se cunoaşte o altă modalitate de rezolvare a problemei sau în cazurile în care modalitatea
alternativă mu este elegantă sau este foarte complicată.
Un tip de probleme recursive întâlnite în ultimii anii la examene constau în evaluarea rezultatului
apelului unui subprogram recursiv utilizând anumite valori ca parametrii de pornire. În acest caz se scriu pas
cu pas relaţiile dintre termenii consecutivi ai apelului recursiv până se ajunge la valoarea care se obţine
pentru cazul de terminare a recursivităţii. Cu valoarea obţinută se revine pas cu pas efectuându-se calcule
până se ajunge la valoarea corespunzătoare nivelului cerut.
De exemplu, pentru problema:
int f(int n)
{if(n= =1) return 2;
else return 3*f(n-1);}
Ce valoare se obţine pentru n=4?
Rezolvare:
Se scriu relaţiile:
f(4)=3*f(3);
f(3)=3*f(2);
f(2)=3*f(1)=3*2=6;
Apoi se revine nivel cu nivel până se ajunge la valoarea lui n=4.
Adică f(3)=3*f(2)=3*6=18;
f(4)=3*f(3)=54;
Deci rezultatul care se obţine este 54.

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