Sunteți pe pagina 1din 22

Algoritmi care lucrează pe numere

(fără tablouri sau alte elemente structurate)

PB1 Determinarea cifrei minime a lui n


Să se realizeze o funcție recursivă cu un singur parametru (numărul n) pentru determinarea
cifrei minime a lui n, se va returna cifra minima.
Analiză – se scrie formula recursivă
n ,dacă n este format dint−o singură cifră
cifraMinima(n)=
{
min{n mod 10 , cifraMinima
n
10 ([ ])
, altfel

O altă variantă recursivă pentru determinarea cifrei minime este:

n , dacă n este format dintr−o singură cifră


cifraMinima( a 1 a 2 …´a n−1 a n) ¿ {
cifraMinima ( a1 a2 … min´ ⁡{an−1 , , an }) , altfel
Obs: În această variantă apelul recursiv se face pentru numărul obținut prin înlocuirea ultimelor două
cifre ale sale cu minimul dintre acestea.

Implementare C++

#include <iostream>
using namespace std;
int cifraMinima_V1(int n) {
if(n<=9) //caz in care n este format dintr-o singura cifra
return n;
int cifraMinima_restul_numarului = cifraMinima_V1(n / 10);
return (n % 10 < cifraMinima_restul_numarului ? n % 10 : cifraMinima_restul_numarului);
}

int cifraMinima_V2(int n){


if(n<=9) //caz in care n este format dintr-o singura cifra
return n;
int minim_ultimele_doua_cifre = n % 10;
int penultima_cifra = (n / 10) % 10;
if (penultima_cifra < minim_ultimele_doua_cifre)
minim_ultimele_doua_cifre = penultima_cifra;
return cifraMinima_V2((n/100) * 10 + minim_ultimele_doua_cifre);
}

1 / 22
PB2 Determinarea cifrei pare maxime a lui n
Să se realizeze o funcție recursivă cu un singur parametru (numărul n) pentru determinarea
cifrei pare maxime a lui n, se va returna cifra pară maximă sau -1, dacă n nu are cifre pare.
Analiză – se scrie formula recursivă

n , dacă e este format dintr−o singură cifră pară

{
1 , dacă n este format dintr−o singură cifră impară
n
cifraParaMaxima (n)= cifraParaMaxima ([ ])
10
, daca n mod 10 este impara

{
max n mod 10 , cifraParaMaxima ([ ])}
n
10
, daca n mod 10 este para

Implementare C++

#include <iostream>
using namespace std;
int cifraParaMaxima(int n) {
if(n<=9) {//caz in care n este format dintr-o singura cifra
if(n%2==0) return n;
else return -1;
}
int ultima_cifra = n % 10;
if (ultima_cifra % 2 != 0) return cifraParaMaxima(n / 10);
int cifraParaMaxima_restul_numarului = cifraParaMaxima(n / 10);
return (ultima_cifra > cifraParaMaxima_restul_numarului ? ultima_cifra : cifraParaMaxima_restul_numarului);
}

PB3 Determinarea numărului de apariții ale unei cifre în n


Scrieți un subprogram recursiv care determină numărul de aparitii ale unei cifre în
reprezentarea zecimală a numărului natural n.
Analiză – se scrie formula recursivă

1, daca n<10 si n=c

{
0 , daca n<10 sin ≠ c
n
aparitii (n , c)= 1+aparitii ( )
10
, c , daca n>c si n mod 10=c

n
aparitii ( )
10
, c , daca n> c si n mod 10 ≠ c

Implementare C++

#include <iostream>
using namespace std;
int aparitii(int n, int c) {
// daca n are o singura cifra returnez 1 daca cifra = c, 0 altfel
if (n < 10) return n == c;
//daca ultima cifra e c o adauga la numaratoare
else if (n % 10 == c) return 1 + aparitii(n / 10, c);
2 / 22
else return aparitii(n / 10, c);
}

PB4 Numărul obținut din n prin eliminarea cifrelor pare.


Scrieți o funcție recursivă care primește ca paramentru un număr natural n și returnează
numărul obținut din n prin eliminarea cifrelor pare.
Exemplu: Dacă n=4536597, atunci rez = 53597.
Analiză – se scrie formula recursivă
0 , daca n=0

elimCifrePare ( n )=

Implementare C++
{ elimCifrePare

elimCifrePare
n
([ ])
10
n
([ ])
10
, daca n numar par

∗10+n mod 10 , daca n numar impar

#include <iostream>
using namespace std;
int elimCifrePare(int n) {
if (n == 0) return 0;
else
if (n % 2 == 0) return elimCifrePare(n / 10);
else return elimifrePare(n / 10) * 10 + n % 10;
}

PB5 Calculează (ij)modulo k.


Fie i,j,k trei numere naturale, j>0,k>1. Să scrie un subprogram care returnează restul împărțirii
numărului (ij) la k, deci (ij)modulo k (iterativ şi recursiv).
Exemple:
(100100) modulo 7 = 2
(125199) modulo 999 = 800
(210) modulo 9 = 7 (1024 / 9 = 113 rest 7)
Analiză
- practic se înmulțesc resturile modulo k; nu e nevoie de calculul expresiei ij;
- se calculează la fiecare pas de înmulțire restul produsului (modulo k);
Aceasta deoarece se știe că: (a * b) mod c = (a mod c * b mod c) mod c
Atunci: ax mod c = (a mod c * ax-1 mod c) mod c

Pentru varianta recursivă, formula recursivă se deduce din formula anterioară astfel:
1, daca j=0
rest (i, j , k )=
{
( ( i mod k )∗rest ( i, j−1, k ) ) mod k
Implementare C++
//ITERATIV //RECURSIV
#include <iostream> #include <iostream>
using namespace std; using namespace std;
int Rest(int i, int j, int k) { int Rest(int i, int j, int k) {
int r = i % k; if (j == 0) return 1;
int rest = 1; return ((i % k) * Rest(i, j - 1, k)) % k;
while (j > 0) {
}
rest = (rest * r) % k; j--;
}
3 / 22
return rest;
}

PB6 Numere asemenea


Fie X,Y două numere naturale. Să scrie un subprogram care determină dacă două numere date
sunt asemenea, fără a folosi tablouri. (Două numere naturale sunt asemenea dacă au aceleaşi cifre:
2131 e asemenea cu 32211 pentru că mulțimea cifrelor este aceeași: {1,2,3}).
Analiză - ar trebui să vedem dacă fiecare cifra a lui X este în Y şi invers.
Vom face 2 subprograme:
- un subprogram care verifică dacă fiecare cifră a unui număr se află printre cifrele altui număr
- un subprogram care apelează apoi de 2 ori primul subprogram

Implementare C++
#include <iostream>
using namespace std;

bool CifreAinB(long a, long b) {


int copieB = b; // se retine o copie a lui B
while (a > 0){ // vom verifica daca fiecare cifra a lui A este in B
int ultima_cifra_A = a % 10;
while (copieB > 0 && ultima_cifra_A != copieB % 10)
copieB /= 10;
if (copieB == 0) // daca s-a ajuns la 0, cifra curenta a lui A nu este
return 0;
copieB = b; // se reinitializeaza copia cu numarul initial B
a /= 10; // se trece la urmatoarea cifra a lui A
}
return 1;
}
bool Asemenea(long x, long y) { // verifica dubla incluziune a cifrelor lui x si y.
return (CifreAinB(x, y) && CifreAinB(y, x));
}

PB7
Un domeniu pătrat (cu albastru), ca cel din figură trebuie
apărat. Domeniul e împărțit în pătrățele. Latura domeniului
este de n pătrățele, n≥7. Pe culoarele colorate patrulează 3
soldați, care încep patrularea din colțul stânga sus în același
moment (poziția inițială). În exemplul de mai jos avem n=9.
Cei 3 soldați (garda) se vor schimba cu alți 3 soldați în
momentul în care ajung în poziția inițială, simultan.
Soldații patrulează în sensul acelor de ceasornic fiecare cu
aceeași viteză constantă, și fiecare pe culoarul său.
Să se implementeze un program care determină numărul de
circuite complete pentru fiecare soldat (un circuit complet
este făcut de un soldat oarecare, pe același culoar până
ajunge în poziția inițială), pentru schimbarea gărzii.

4 / 22
S1 patrulează pe culoarul galben, S2 pe gri, S3 pe roșu. Albastrul este cetatea care trebuie apărată.

Analiză
-Considerăm doi soldați care patrulează circuite de lungimi diferite, măsurate în unități (o unitate este
un pătrățel). Un circuit are lungime L1, iar al doilea lungime L2 unități.
-Cei doi vor ajunge concomitent în punctul inițial după ce parcurg X = cmmmc(L1, L2) unități. Astfel,
primul va parcurge X/L1 circuite, iar al doilea X/L2.
-Aceeași idee se aplică pentru trei soldați.

1 2 3 4 5 6 2 22 23 24
1 2 3 4 7 1
2 13 14 15 16
12 5 8
0
11 6 9
1 24 17
10 9 8 7 10
9
12 11
1 23 18
8
41
25 26 22 43
21 44
20 45
19 46
42
25 26 27 28 27 7
1
1 15 14 13
36 29 28 4 37 38 39 40 47
35 30 29 06
34 33 32 31 30 3 48 41 48
3 35 34 33 32 31 9
6 3 47 42
8
6 3 46 45 44 43
1 7
6 49/61 50 51 5
0 2
5 60 5
9 3
5 59 5 49
8 4
5 58 57 56 5 50 Implementare C++
7 5 #include <iostream>
5 55 54 53 5 51
using namespace std;
6 2
int cmmmc(int a, int b){
if (a < b){
int aux = a;a = b;b = aux;
}
// cel mai mare numar se aduna repetat cu el insusi si se verifica divizibilitatea cu celalalt
int rez = a;
while (rez % b != 0) rez += a;
return rez;
}
//Descriere: Calculeaza numarul de circuite complete pentru fiecare soldat, pana la intalnire.
//Date: n – latura domeniului.
//Rezultate: c1, c2, c3 – numarul de circuite parcurse de catre cei trei soldati.

5 / 22
void circuite(int n, int& c1, int& c2, int& c3){
int l1 = 4 * (n - 1); // lungimea culoarului exterior
int l2 = 4 * (n - 3); // lungimea culoarului din mijloc
int l3 = 4 * (n - 5); // lungimea culoarului interior
int intalnire = cmmmc(cmmmc(l1, l2), l3); // cmmmc al lui l1, l2, l3
c1 = intalnire / l1;
c2 = intalnire / l2;
c3 = intalnire / l3;
}
int main(){
int n = 0;
cout << "Introduceti latura domeniului: ";
cin >> n;
int c1 = 0, c2 = 0, c3 = 0;
circuite(n, c1, c2, c3);
cout << "Soldatul S1 va face " << c1 << " circuite pana la intalnire." << endl;
cout << "Soldatul S2 va face " << c2 << " circuite pana la intalnire." << endl;
cout << "Soldatul S3 va face " << c3 << " circuite pana la intalnire." << endl;
return 0;
}
Observatie: Alternativ, se poate lua in considerare calculul cmmmc folosind cmmdc, astfel:
𝒄𝒎(𝒂,𝒃)=(𝒂∗𝒃)/𝒄𝒎𝒎𝒅𝒄(𝒂,𝒃)

Pb8 – Numere triunghiulare


Se citesc mai multe șiruri de numere naturale, fiecare
șir se termină cu valoarea -1, iar citirea tuturor șirurilor se
termină cu șirul vid. Se cere:
a) Pentru fiecare șir citit să se determine maximul dintre
numerele triangulare din șir.
b) Maximul dintre numerele triangulare existente în toate
șirurile citite.
Un număr x se numește triangular dacă există un număr n,
astfel încât x este egal cu suma primelor n nr naturale.

Implementare C++
#include <iostream>
using namespace std;

bool esteTriangular(int x) {
int n = 1, s = 0;
while (s <x) {
s = s + n;
n++;
}
if (s == x) return true;
return false;

6 / 22
}
//afiseaza maximul dintre numerele triangulare din fiecare sir citit, iar apoi afiseaza maximul global
void nrTriangulareMaximaleDinSir() {
int n, max, maxTriangular = -1;
cin >> n;
while (n > -1) {
max = -1;
while (n > -1) {
if (esteTriangular(n) && n > max) max = n;
cin >> n;
}
if (max > maxTriangular) maxTriangular = max;
cout <<"Maximul dintre numerele triunghiulare din sirul citit este "<< max;
cin >> n;
}
cout <<"Maximul dintre toate numerele triunghiulare din toate sirurile este "<<
maxTriangular;
}

Pb9-Numere piramidale
Sa se scrie o functie care
afiseaza primele k numere piramidale,
unde k este un nr natural specificat ca
parametru functiei.
Un număr x se numește piramidal
daca exista un numar natural n astfel
incat x poate fi scris ca suma
primelor n numere triangulare.

1+2+3+4+5=15 1+3+6+10=20
Pentru k=8 se va afisa: 1, 4, 10, 20, 35, 56, 84, 120, 165

Implementare C++
#include <iostream>
using namespace std;
void sirPiramidal(int k{
int s = 1, n = 2, nrPiramidal = 1;
for (int i = 0; i <k; i++) {
cout << nrPiramidal <<", ";
s = s + n;
n = n + 1;
nrPiramidal = nrPiramidal + s;
}
}
Pb10 - Secvențe 101(binar)
Fie un număr n, se definește gradul numărului n ca fiind numărul de secvențe "101" din
reprezentarea binară a acestuia. De exemplu, numărul 21 are gradul 2 (reprezentarea binară a lui 21
este 10101). Pentru un șir s citit de la tastatură să se determine grupul de numere de grad k.
7 / 22
Analiză: - o posibilă rezolvare poate utiliza un vector de 32 de elemente (daca elementele șirului sunt
numere naturale de tipul intreg reprezentarea binară a unui intreg are 32 de biți, dimensiunea unui
intreg este 4 octeți).
Exemple:
Date de intrare Date de ieșire
1 (k) numere de grad 1:
7 5, 13, 29
5 5(2)= 101
13 13(2)= 1101
21 29(2)= 11101
29
25
0
2 (k)
13 numere de grad 2:
5 21, 45, 360
21
56 21(2)= 10101
45 45(2)= 10101
360 360(2)= 101101000
37
0

Implementare C++
#include <iostream>
using namespace std;
const int NRBITI = 32;
int BINAR[NRBITI] = {0}; //toate elementele vectorului BINAR se initializeaza cu 0
void resetBinar(){
for (int i = 0; i < NRBITI; ++i)
BINAR[i] = 0;
}
// reprezint un numar in baza doi, n - numarul natural de reprezentat in baza doi,
// returnez: numarul de cifre din reprezentarea binara
int calculReprezBinar(int n){
resetBinar();
for (int i = 0; n > 0; i++) {
BINAR[i] = n % 2;
n = n / 2;
}
return i+1;
}
// reprezint un numar in baza doi, versiunea II folosind operatii pe biti
// n - numarul natural de reprezentat in baza doi
// returnez: numarul de cifre din reprezentarea binara
int calculReprezBinar2(int n){
resetBinar();
int i = 0;
while (n) {
BINAR[i] = n & 1;
n >>= 1;
i++;
}
return i;
}
8 / 22
// calcul determina gradul unui numar (numarul de secvente 101 din reprezentarea binara)
// n - numarul natural pentru care trebuie determinat gradul
// returnez: gradul numarului
int determinaGrad(int n){
int grad = 0;
int nrCifre = 0;
nrCifre = calculReprezBinar2(n);
for (int i = nrCifre; i >= 2; i--) {
if(BINAR[i]==1 && BINAR[i-1]==0 && BINAR[i-2]==1)
grad++;
}
return grad;
}
int main() {
int k, numar = 1;
// se citeste gradul cautat
cin >> k;
// sirul s va stoca numerele de grad k
int s[100] = {0};
int i = 0;
// citirea numerelor se termina cu citirea lui 0
while (numar) {
cin >> numar;
if (k == determinaGrad(numar)) {
s[i] = numar;
i++;
}
}
cout << "numere de grad " << k << " :" << endl;
for (int y = 0; y < i; ++y) {
cout << s[y] << " ";
}
return 0;
}

O abordare MAI EFICIENTĂ poate fi imaginată prin izolarea celor mai puțin semnificativ trei
biți din reprezentarea binară și verificarea dacă sunt o secvență 101, după care se deplasează la stânga
cu una sau două poziții (în funcție de rezultatul comparației cu (101)2 = (5)10 ).

Implementare C++

#include <iostream>
using namespace std;
int determinaGrad2(int n){
int grad = 0;
while (n) {//se izoleaza cei mai putin semnificativ 3 biti si se verifica daca sunt o secventa 101
if ((n&7) == 5) { //7 (in baza 2) = 111, 5(in baza 2) = 101
grad++;
n >>= 2;
} else
n >>= 1;
}
return grad;
}
int main() {
9 / 22
int k, numar = 1;
// se citeste gradul cautat
cin >> k;
// citirea numerelor se termina cu citirea lui 0
while(numar) {
cin >> numar;
if (k == determinaGrad2(numar)) {
cout << "numarul " << numar << " are gradul " << k << endl;
}
}
return 0;
}

Pb11 - Numere zâmbărețe


Un număr n este "zâmbăreț" dacă duce la 1 după o secvență de pași unde în fiecare pas numărul
este înlocuit cu suma pătratelor cifrelor ce formează numărul. Sa se scrie un program care citeste mai
multe numere pana la citirea numarului 0 si determină câte numere "zâmbărețe" s-au citit.
Exemplu: 19 este "zâmbăreț"
pas_1: 1+9^2=82
pas_2: 64+4=68
pas_3: 36+64=100
pas_4: 1+0+0=1

Implementare C++
#include <iostream>
using namespace std;
int sumPatrate(int n){
int suma = 0;
while (n) {
suma += (n % 10) * (n % 10);
n /= 10;
}
return suma;
}
bool eNumarZambaret(int n){
int nr1, nr2;
nr1 = nr2 = n; // initializare numere cu n
//un numar NU este zambaret daca pe parcursul iteratiilor atinge aceeasi valoare succesiv
do {
nr1 = sumPatrate(nr1);
nr2 = sumPatrate(sumPatrate(nr2));
} while (nr1 != nr2);
return (nr1 == 1); // daca ambele numere sunt 1, return true
}
int main() {
int contor = 0;
int numar = 1;
while (numar) {
cin >> numar;
if (eNumarZambaret(numar)) {
cout << "numarul " << numar << " este zambaret" << endl;
contor++;
}
cout << "Am citit " << contor << " numere zambarete" << endl;
10 / 22
return 0;
}
Exemple:
Date de intrare si rezultat
23
numarul 23 este zambaret
45
56
46
49
numarul 49 este zambaret
19
numarul 19 este zambaret
100
numarul 100 este zambaret
11
0
Am citit 4 numere zambarete

PB12 – Numere pietene


Să se scrie un subprogram care să afișeze perechile de numere naturale „prietene” dintr-un
interval dat [a,b], a, b – numere naturale, a < b. Două numere naturale x şi y sunt „prietene” dacă suma
divizorilor lui x este egală cu suma divizorilor lui y. Pentru un număr, se vor considera toți divizorii,
inclusiv 1 și numărul însuși.
Analiză: - vom scrie un
Date de intrare Date de ieșire
subprogram care verifică daca x
si y din [a,b] au 1, 20 6, 11 aceeași sumă s a
divizorilor. 10, 17
Avem nevoie şi 14, 15 de un
subprogram care 15, 25 15, 23 determină suma
divizorilor. Vom 16, 25 realiza acest
subprogram cu 1, 10 - cea mai bună
complexitate, 100, 140 102, 110 adică O( √ n).
Exemple 104, 116
114, 135
115, 119
132, 140
1023, 1050 1030, 1035

Implementare C++
long sumDiv(long n) {
long S = n + 1; //initializarea sumei S cu n+1 (divizorii improprii)
long d = 2;
for (d = 2; d*d<n; d++) //se verifica pentru d=2,3,...,radical(n)-1
11 / 22
if (n%d == 0) S += d + n / d; //se aduna factorii complementari
if (d*d == n) S += d; //daca n este patrat perfect se mai aduna d
return S; //d, atentie la iesire din for d>=radical(n)
}

O variantă recursivă a acestui subprogram:


long SumDivRec(long n, long d){ //e nevoie si de d, la apel d=2
if (d*d>n) return 1 + n; //la iesire se inlocuieste apelul cu n+1
//daca n este patrat perfect
if (d*d == n) return d + SumDivRec(n, d + 1);
//se verifica pentru d=2..radical(n)
//se aduna factorii complementari
if (n%d == 0) return d + (n / d) + SumDivRec(n, d + 1);
return SumDivRec(n, d + 1); //daca d nu e divizor
}
long sumDiv(long n) {
return SumDivRec(n, 2);
}

void AfisPrietene(long a, long b){


for(long x=a; x<b; x++)
for(long y=a+1;y<=b;y++)
if(SumaDiv(x)==SumDiv(y)) cout<<x<<" si "<<y<<” prietene \n";
}

Pb13 – Rădăcina pătrată cu precizie epsilon


Dat fiind un număr real x, să se determine rădăcina pătrată r a acestuia, cu precizia epsilon.
Analiză: - se va folosi metoda înjumătățirii intervalului: pornind de la un interval inițial pentru
rădăcina pătrată, se selectează iterativ subintervalul în care se află rădăcina, până când se ajunge la o
lungime maximă a intervalului mai mică decât precizia cerută. Precizia epsilon poate fi 10-k = 0.0...1 cu
(k-1) de zero (adică cu k zecimale exacte). Exemplu epsilon: epsilon=10-3=0.001.
Exemple:
Date de intrare Date de ieșire
5, 0.01 2.23145
5, 0.0001 2.23606
100, 0.0000001 10
100, 0.1 10.0098
2, 0.01 1.41797

Implementare C++
void citesteNumarSiPrecizie(double& x, double& eps){
cout << "Introduceti numarul real si apoi precizia: ";
cin >> x >> eps;
}
double determinaRadacinaPatrataIterativ(double x, double eps){
double dreapta = x;
double stanga = 0;
double mij = (dreapta + stanga) / 2;
while (abs(dreapta - stanga) > eps) {
if (mij * mij > x) dreapta = mij;
else stanga = mij;
mij = (dreapta + stanga) / 2;

12 / 22
}
return mij;
}
double determinaRadacinaPatrataRec(double x, double eps, double stanga, double dreapta){
double mij = (dreapta + stanga) / 2;
if (abs(dreapta - stanga) < eps) return mij;
if (mij * mij > x)
return determinaRadacinaPatrataRec(x, eps, stanga, mij);
return determinaRadacinaPatrataRec(x, eps, mij, dreapta);
}
double determinaRadacinaPatrataRecursiv(double x, double eps){
return determinaRadacinaPatrataRec(x, eps, 0, x);
}
int main(){
double x = 0, eps = 0;
citesteNumarSiPrecizie(x, eps);
cout << "Iterativ: ";
cout << "Radacina patrata a numarului " << x << ", cu precizia " << eps << " este: " <<
determinaRadacinaPatrataIterativ(x, eps) << endl;
cout << endl;
cout << "Recursiv: ";
cout << "Radacina patrata a numarului " << x << ", cu precizia " << eps << " este: " <<
determinaRadacinaPatrataRecursiv(x, eps) << endl;
return 0;
}

Pb14 – Secvență + poziție


Fie șirul X = (1, 2, 3, 2, 2, 5, 2, 2, 3, 3, 3, 7, 2, 2, 3, 3, 3, 2, 2, 5, 5, 5, 5, 5, ...), obținut din
secvența numerelor naturale, în care numerele compuse sunt înlocuite cu divizorii lor primi, fiecare
divizor d fiind scris de d ori. Scrieți un algoritm care determină valoarea elementului de pe poziția k,
fără a păstra șirul în memorie (k – număr natural). Indexarea șirului începe de la 0.
Exemple:
Date de intrare Date de ieșire
1 2
8 3
11 7
20 5
30 13
34 7
35 7
77 11

Implementare C++
#include <iostream>
using namespace std;
int citesteNumar() {
int n = 0;
cout << "Introduceti un numar natural: "; cin >> n;
return n;
}
bool prim(int n) {
if (n < 2) return false; // numerele mai mici ca 2 nu sunt prime
if (n == 2) return true; // 2 este prim
if (n % 2 == 0) return false; // numerele pare nu sunt prime
for(int div = 3; div * div <= n; d+=2) // verificare pentru n impar
13 / 22
if (n % div == 0) return false; // iesire n nu e prim
return true; // la finalul lui for n e prim
}
// gaseste, pentru numarul n, primul divizorul prim dupa div. Daca un astfel de divizor nu exista,
// se returneaza -1
int divizorPrimUrmator(int n, int div) {
if (prim(n)) return -1;
int i = div + 1;
while ((!prim(i) || (n % i != 0)) && i != n)
i++;
if (i == n) return -1;
return i;
}
//determina numarul din sirul X (format dupa cum se specifica in enunţul problemei), de la pozitia poz
int determinaNumarDeLaPozitie(int poz) {
if (poz < 3) return poz + 1;
int rezultat = 0;
int numarCurentInSecventa = 3;
int pozitieCurenta = 2;
while (poz > pozitieCurenta) {
numarCurentInSecventa++;
if (prim(numarCurentInSecventa)){ // daca numarul este prim, pozitia va creste cu 1
pozitieCurenta += 1;
rezultat = numarCurentInSecventa;
} else { // se iau pe rand divizorii primi ai numarului
int divUrm = divizorPrimUrmator(numarCurentInSecventa, 1);
while (poz > pozitieCurenta && divUrm != -1) {
pozitieCurenta += divUrm; // valoarea divUrm va aparea de divUrm
//ori in sir, deci se pot sari divUrm pozitii
rezultat = divUrm; // toate aceste pozitii vor contine valoarea divUrm
divUrm = divizorPrimUrmator(numarCurentInSecventa, divUrm);
}
}
}
return rezultat;
}
int main() {
/*for (int i = 0; i < 100; i++)
cout << i << " " << determinaNumarDeLaPozitie(i) << endl;*/
int poz = citesteNumar();
cout << "Numarul din sirul X de pe pozitia " << poz << " este: " <<
determinaNumarDeLaPozitie(poz) << ".";
system("pause");
return 0;
}

14 / 22
Probleme tip grilă

1. Se considera subalgoritmul F care primeste parametrul n, n numar natural.


int F (int n){
if (n<10) return n;
int u = n % 10;
int r = F(n d/ 10);
if (u<r) return u;
return r;
}
Care este rezultatul executiei subalgoritmului F?
a) Cea mai mare cifră a lui n
b) Cea mai mică cifră a lui n
c) Cea mai mare cifră pară a lui n
d) Cea mai mică cifră pară a lui n

2. Se consideră subalgoritmii următori. Alegeți subalgoritmii care interschimbă valorile a şi b.


a) void F (int a, int b){ b) void F (int a,int b){
a=a-b; a=a+b;
b=b+a; b=a-b;
a=b-a; a=a-b;
} }
c) void F (int a, int b){ d) void F (int a, int b){
a=a div b; a=a*b;
b=a*b; b=a div b;
a=b div a; a=a div b;
} }
e) void F (int a, int b){
b=b-a;
b=a*b;
a=b;
}

3. Se consideră subalgoritmul calcul (n), n număr natural.


int calcul(int n){
n = 50;
i = 3;
while(i<= n) {
i = i+5;
}
return i;
15 / 22
}
Care este valoarea returnată după execuția subalgoritmului?
a) 50
b) 53
c) 48
d) 90

4. Se consideră subalgoritmul F care are un parametru n, n număr natural.


int F(int n) {
if (n<10) {
if( n % 2== 0) return n;
else return -1;
}
if (n % 2=0) return n % 10;
else return -1;
int u = n % 10;
int m = F(n d/ 10);
if (u>m) return u;
else return m;
}
Care este rezultatul executiei subalgoritmului?
a) Returneaza cea mai mare cifră a lui n, sau -1
b) Returneaza cea mai mare cifră pară a lui n, sau -1
c) Returneaza cea mai mare cifră a lui n
d) Returneaza cea mai mică cifră pară a lui n, sau -1

5. Ce valori vor avea a, b şi k la sfârşitul secvenţei de instructiuni?


int a=20, b=70, k=0;
if(a<b) {
b*=a; a=b/a; b/=a;
}
while(a>=b){ a-=b;k+=2;
}
a) 70,70,5
b) 70,20,2
c) 70,20,6
d) 10,30,4
e) 10,20,6

6. Care este efectul execuției subalgoritmului SP (n), n număr natural?


void SP(long n) {
for (int i = 2; i <= n; i++){
int c = 0;
while (!(n%i)) {
n /= i;
c += 1;

16 / 22
}
if (c) cout << i << ” ” << c << endl;
}
}
a) Afişează perechi de numere prime (n≥2).
b) Afişează numerele prime până la n (n≥2).
c) Afişează factorii primi ai lui n (n≥2).
d) Afişează factorii primi ai lui n şi puterile lor (n≥2).
e) Subprogramul nu afişează nimic, dacă n<2.
7. Care este efectul execuției următoarei secvențe de instrucțiuni?
citeşte a,b {numere întregi}
x 1
cât_timp (a>0)şi(b>0) execută
dacă (a mod 10)<(b mod 10) atunci x0
sfDaca
a [a/10]
b [b/10]
sfCat_timp
dacă (x=1) şi (b=0) atunci scrie ”DA”
altfel scrie ”NU”
sfDaca
a) Afişează „DA” pentru perechi de numere strict pozitive.
b) Afişează „NU” pentru perechi de numere strict negative.
c) Afişează „DA” dacă a<b.
d) Afisează „DA” dacă fiecare cifră a lui a este mai mare sau egala cu cifra corespondentă a lui b
(unităţi, zeci, etc.) şi numarul cifrelor lui b este mai mic sau egal cu numarul cifrelor lui a daca a,b>0.
e) Afişează „DA” pentru a=34, b=12

8. Care este efectul executiei urmatoarei secvente de instrucţiuni pentru şirul: 5, 24, 5, 25, 5, 26,
0?
citeşte x {x natural}
nr0
s0
cât_timp x≠0 executã
nrnr+1
dacã nr mod 2=0 atunci
ss+x mod 10
sfDaca
citeşte x
sfCat_timp
scrie s, nr

a) Afişează 0 0.
b) Afişează 15 6.
c) Afişează 10 9.
d) Afişează 10 6.
e) Afişează suma ultimelor cifre ale numerelor de rang (indice) par din şir si numarul de numere
nenule citite.

17 / 22
9. Se consideră următoarea secvență de instrucțiuni.
citeşte n,c {n, natural>0, c cifra}
z0
cât_timp n mod 10=c execută
n [n/10]
zz+1
sfCat_timp
scrie z
a) Afişează 3 pentru n=123 şi c=3;
b) Afişează 2 pentru n=12003 şi c=0;
c) Afişează 1, pentru n=c=1;
d) Afişează 4, pentru n=1277771 şi c=7
e) Afişează 3, pentru n=12555 şi c=5.

10. Fie subalgoritmul g(a,b), unde a si b sunt numere naturale nenule:


Subalgoritmul g(a,b):
dacǎ (a=b) atunci returneaza a;
SfDacǎ
Dacǎ (a>b) atunci g(a-b,b);
altfel g(a,b-a);
sfDacǎ
SfSubalgoritm
Precizați de câte ori se autoapeleaza subalgoritmul g în următoarea secvență de instructiuni:
a4
b3
z  g(x, y)
a) de 4 ori
b) de 3 ori
c) de o infinitate de ori
d) niciodată

11. Fie variabilele booleene a, b și c cu valorile de adevǎr TRUE, TRUE și FALSE.


Evaluați expresia: NOT a OR NOT b AND c

12. Se consideră subalgoritmul calcul, cu parametrul natural n.


Subalgoritmul Calcul (n):
Dacǎ (n=0) atunci returneazǎ 0;
SfDacǎ
Dacǎ n mod 2=1 atunci returneazǎ calcul (n div 10);
SfDacǎ
returneazǎ calcul(n div 10)*10 + n mod 10;
SfSubalgoritm
Pentru care dintre valorile parametrului n subalgoritmul va returna valoarea 246?
a) 23457 b) 234567 c) 24769 d) 294576

13. Se considera subalgoritmul prim(n,d), n si d - numere naturale nenule, care verifica daca
numarul n este prim.
Subalgoritmul prim(n, d):
18 / 22
dacǎ (n<2) atunci returneazǎ 0;
sfDacǎ
dacǎ d=1 atunci returneazǎ 1;
sfDacǎ
Dacǎ (n mod d=0) atunci returneazǎ 0;
sfDacǎ
returneazǎ prim
Cum ar trebui efectuat apelul pentru ca subalgoritmul sǎ returneze rǎspunsul corect:
a) Prim(n,n)
b) Prim(n,1)
c) Prim(n,n/2)
d) Prim(n/2,2)

14. Se considera urmǎtoarele expresii logice:


1) (true && true) || false
2) (false && true) || true
3) (false && true) || false || true
4) (5 > 6 || 4 > 3) && (7 > 8)
5) !(7 > 6 || 3 > 4)
Care dintre expresii au valoare de adevar TRUE?
a) 1, 5
b) 1,2,5
c) 2,4
d) 1,2,3

15. Se consideră subalgoritmul ghici(n), unde n este un număr natural.


Subalgoritmul ghici (n):
f  0, k  0;
pentru c  0;9; executa
x  n; k  0;
cat_timp (x>0) executa
daca (x mod 10 = c) atunci
k  k+1;
sfDaca
x  x div 10;
sfCat_timp
daca (k>f) atunci
f  k;
sfDaca
sfPentru
returneaza f;
SfSubalgoritm
Sa se determine rezultatul returnat de executarea subalgorimtului:
a) Numǎrul de cifre al numǎrului n
b) Frecventa fiecǎrei cifre din reprezentarea zecimala a numǎrului n
c) Numarul de aparitii ale cifrei cu frecventa maxima in reprezentarea zecimala a numarului n
d) Cifra maxima din reprezentarea zecimala anumarului n

16. Ce va afișa următoarea secvență de program, dacă se citesc în această ordine numerele: 194,
121, 782?
citeşte x (număr natural)
n=0
┌cât timp x≠0 execută
│ y=x; c=0

19 / 22
│ ┌cât timp y>0 execută
│ │ ┌dacă y%10>c atunci
│ │ │ c=y%10
│ │ └■
│ │ y=y/10
│ └■
│ n=n*10+c
│ citeşte x
└■
scrie n
17. Care este valoarea afişată pentru x=-2 şi m=9?
citeşte x ,m
{x întreg, m natural}
y1
┌ cât timp m>0 exec
│┌ dacă m%2 =0
││ atunci
││ m [m/2]; xx*x
││ altfel
││ mm-1;yy*x
│└■
└■
scrie y

18. Ce face secvența:


int f(char* str){
if (*str == '\0') return 0;
else return 1 + f(str + 1);
}

19. Ce face secvența:


int f(int n) {
if (n == 0) return 0;
else return (n % 2 + 10 * f(n / 2));
}
20. Ce va afișa algoritmul pseudocod de mai jos pentru două numere naturale nenule a și b?
S-a notat cu x%y restul împărțirii numerelor întregi x și y.
citeşte a,b
c1
cât-timp a * c % b ≠ 0 execută
cc+1
sfarsit-cat-timp
scrie a*c
b
a) a
b) cel mai mic multiplu comun
c) cel mai mare divizor comun
d) a*b

21. Se consideră funcția de mai jos, care primește ca parametru un număr natural.
int f(int a){
20 / 22
int x = a % 10;
if (x == a)
if (x % 2 == 0) return a;
else return 0;
if (x % 2 == 0) return 10 * f((int)(a/10)) + x;
return f((int)(a/10));
}

I. De câte ori se apelează funcția pentru a = 253401976?


a) de 3 ori
b) de 9 ori
c) de 6 ori
d) de 7 ori
II. Care este rezultatul funcției pentru a = 253401976?
a) 206
b) 53019
c) 2406
d) 0

22. Știind că variabilele a și i sunt întregi, stabiliți ce reprezintă valorile afișate de algoritmul de
mai jos.
a  10
pentru i  1,6 execută
scrie [a/7]
a  a % 7 * 10
sfârşit pentru

a. primele 6 zecimale ale lui 1/7


b. primele 7 zecimale ale lui 1/6
c. primele 6 cifre ale lui 10/7
d. primele 7 zecimale ale lui 10/6

21 / 22
Răspunsuri

1 b
2 a, b, d
3 b
4 b
5 e
6 d, e
7 b, d, e
8 b, e
9 c, e
10 b
FALS
(se tine cont de
11 prioritatea
operatorilor)

12 b, c, d
13 c
14 d
15 c
16 928
-512
17
calculeaza lungimea
18
unui șir de caractere
transformă un numar
19
în baza doi
20 b
21-I b
21-II c
22 c

22 / 22

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