Documente Academic
Documente Profesional
Documente Cultură
Șiruri recurente
Prezentarea șirului lui Fibonacci pleacă de la următoarea problema propusă în anul 1202 în capitolul
XII al „Cărții abacului” :
O pereche de iepuri este pus într-un spațiu total închis de un zid. Cate perechi de iepuri se vor
obține într-un an din aceasta pereche daca se știe ca in fiecare luna, fiecare pereche da naștere
unei noi perechi de iepuri care devin productivi începând cu următoarea luna.
Algoritmul pentru generarea termenilor șirului lui Fibonacci este un exemplu clasic de algoritm
pentru definirea recurentă a termenului unui șir.
Șirului Fibonacci este format din termeni definiți prin recurență, astfel:
f1=1
f2=1
f3= f1+ f2
…………
fn= fn-2+ fn-1
Pentru generarea primilor n termini ai șirului lui Fibonacci (n>3), se vor genera repetat termenii de
rang i ai șirului, cu 3< i<n. Se vor folosi trei variabile de memorie: f1 pentru fi-2, f2 pentru fi-1 și f pentru
termenul curent fi.
După fiecare generare a unui termen se vor actualiza valorile din variabilele f1 şi f2.
Observatie:
g0=0, gi= 2i-1 pentru 0<i<k , gn= gn-1+gn-2+ …+ gn-k pentru n>=k .
Vom lua o variabila (i) in care sa număram de cate ori afișam un număr din sir, iar după fiecare
afișare vom face f=f1+f2 si vom deplasa (f2=f1, f1=f)
#include <iostream>
using namespace std;
Lecția 3. Siruri recurente. Baze de numerație. Operatii pe biti. Centrul de Excelenta Vaslui
Prof. Nicu Vlad-Laurențiu
int main(){
int n, f1=1, f2=1, f;
cin >> n;
if(n==1)
cout << "1";
else{
cout << "1 1 ";
for(int i=3;i<=n;++i){
f = f1+f2;
cout << f << " ";
f2 = f1;
f1 = f;
}
}
return 0;
}
int main()
{
int n, f1=1, f2=1, f;
cin >> n;
while(f1+f2<n)
{
f=f1+f2;
f2=f1;
f1=f;
}
cout<<f;
return 0;
}
Vom caută cel mai mare număr din șirul lui Fibonacci mai mic sau egal cu numărul n, după care îl
vom afișa si după vom scădea din n numărul din sir.
#include <bits/stdc++.h>
using namespace std;
int main()
{
long long f1,f2,f,n,i,x;
cin>>n;
while(n!=0)
{
f1=f2=f=1;
Lecția 3. Siruri recurente. Baze de numerație. Operatii pe biti. Centrul de Excelenta Vaslui
Prof. Nicu Vlad-Laurențiu
while(f<=n)
{
f=f1+f2;
f1=f2;
f2=f;
}
cout<<f1<<' ';
n=n-f1;
}
return 0;
}
Alte șiruri
Șirul lui Lucas
Numerele Lucas sunt definite asemenea numerelor Fibonacci: fiecare termen al seriei Lucas fiind
egal cu suma celor doi termeni anteriori; ceea ce diferă sunt termenii inițiali ai seriei: L[n]=L[n-
1]+L[n-2], unde L[0]=2 și L[1]=1.
0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767,
65535, 131071, 262143,
Să se scrie un program care pentru un număr natural n, afișează primele n(n<40) numere
Mersenne.
#include <iostream>
using namespace std;
int n,i;
long long x;
int main()
{
cin>>n;
for(i=0;i<n;i++)
{
x=(2<<i)-1;
cout<<x<<" ";
}
return 0;
}
Lecția 3. Siruri recurente. Baze de numerație. Operatii pe biti. Centrul de Excelenta Vaslui
Prof. Nicu Vlad-Laurențiu
Număr Fermat
𝑛
Un număr de forma Fn=22 + 1 se numește număr Fermat. Daca Fn este număr prim atunci
ele se numește număr prim Fermat.
Să se scrie un program care, afișează primele 6 numere Fermat.
#include <iostream>
#include <cmath>
using namespace std;
int n,i;
long long x;
int main()
{
for(i=0;i<6;i++)
{
x=pow(2,pow(2,i))+1;
cout<<x<<" ";
}
return 0;
}
Până în prezent se cunosc doar 3 perechi (n,m) de astfel de numere: (4,5), (5,11) și (7,71).
Și într-adevăr:
4! + 1 = 25 = 52
5! + 1 = 121 = 112
7! +1 = 5041 = 712.
#include <fstream>
#include<cmath>
using namespace std;
ofstream fout("date.out");
int i,n,k,nr;
int fact(int n)
{
int p=1;
Baze de numerație
Oamenii sunt obișnuiți să folosească numerele în baza 10, adică să folosească sistemul
de numerație zecimal. Un număr scris în baza 10 va avea cifrele 0, 1, 2, …, 9 – resturile
posibile la împărțirea cu 10. Știm deja că există sistemul de numerație binar, în baza 2.
Cifrele sunt 0 și 1 – resturile posibile la împărțirea cu 2.
Există oare și alte baze de numerație? Răspunsul este afirmativ, orice număr
natural b mai mare decât 1 poate fi considerat bază de numerație, iar cifrele folosite în
baza b sunt 0, 1, 2, …, b-1. În contextul computerelor sunt utilizate frecvent
bazele 10, 2, 8 și 16. Să le analizăm:
12:2 =6 rest 0
6:2 =3 rest 0
3:2 =1 rest 1
1:2=0 rest 1
Scriem resturile în ordine inversă și obținem: 24(10) = 11000(2). Să observăm că am obținut
cifrele în ordinea inversă față de poziția lor în număr!!
Secvența C++ de mai jos determină cea mai mare cifră a reprezentării în baza b a
numărului n.
cmax = 0;
cin >> n >> b;
while(n)
{
int cif= n % b;
if(cif > cmax)
cmax = cif;
n /= b;
}
11000(2)=1⋅24+1⋅23+0⋅22+0⋅21+0⋅20
=1⋅16+1⋅8
=16+8
=24
Algoritmul: Să presupunem că se citește baza b, numărul n de cifre ale numărului în
baza b, apoi cifrele. Determinarea reprezentării în baza 10 este:
• se dă un număr x în baza b
• se transformă numărul x din baza b în baza 10 și se obține un număr y
• se transformă numărul y din baza 10 în baza d și se obține rezultatul final
• 16=24
• 2018(10)=7E2(16)
• 2018(10)=11111100010(2)
• dacă grupăm cifrele din
baza 2 câte 4 (deoarece 16=2416=24), 2018(10)=11111100010(2)=111.1
110.0010(2)2018(10)=11111100010(2)=111.1110.0010(2)
• dacă transformăm fiecare grupă din baza 2 în baza 16 vom obține:
o 111(2)=7(16)
o 1110(2)=E(16)
o 0010(2)=2(16)
Vom proceda astfel, pentru transformarea din baza 2în baza 2p:
• transformăm fiecare cifră a numărului din baza 16 în baza 2. Vom obține pentru
fiecare cifră un șir cu cel mult 4 biți.
• dacă un șir conține mai puțin de 4 biți, îl completăm cu zerouri nesemnificative,
cu excepția primului grup (corespunzător primei cifre)
• scriem șirurile de biți în ordine, obținând reprezentarea în baza 2
Lecția 3. Siruri recurente. Baze de numerație. Operatii pe biti. Centrul de Excelenta Vaslui
Prof. Nicu Vlad-Laurențiu
Bibliografie:
*** www.pbinfo.ro
Operații pe biți
Lista operatorilor pe biţi:
~ - negaţie pe biţi
& - şi pe biţi (and)
| - sau pe biţi (or)
^ - sau exclusiv pe biţi (xor)
<< - deplasare la stânga pe biţi (shift left)
>> - deplasare la dreapta pe biţi (shift right)
În exemplele următoare, vom considera că numerele sunt reprezentate pe 16 biţi fără semn (adică
de tip unsigned short).
Negaţia pe biţi este operator unar şi are ca efect schimbarea biţilor 0 în 1 şi biţilor 1 în 0. În
consecinţă, dacă a = 0000000000001110(2), atunci ~a = 1111111111110001(2)
0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 1 0
Considerând op ca fiind oricare din operatorii &, |, ^, o expresie de forma x op y operează asupra
biților operanzilor x şi y.
Astfel, dacă x = 1110(2) şi y = 1101(2) , atunci x & y = 1100(2), x | y = 1111(2), iar x ^ y = 0011(2).
Expresia x << i este echivalentă cu expresia x * 2i. De fapt acest operator elimină cei mai din
stânga i biţi ai lui x şi adaugă la dreapta i biţi de 0. De exemplu, dacă x = 0000000000001110(2), atunci
x << 2 înseamnă 0000000000111000(2) = 56 (adică 14 * 4).
Expresia x >> i este echivalentă cu x div 2i (împărțirea întreagă a lui x prin 2i).
Operatorul de deplasare la dreapta elimină cei mai din dreapta i biți ai lui x și adaugă la stânga i biți
de 0.
Probleme rezolvate
1. Se consideră un număr natural n. Să se verifice dacă n este par sau impar.
Rezolvare: Utilizăm operatorul &. Acesta are rol de testare a biților.
Dacă n este impar, atunci reprezentarea sa în baza 2 va avea cel mai din dreapta bit pe 1.
De exemplu, n = 14 se scrie în baza 2 ca 1110. Atunci 1110 & 1 = 0. Iată că pentru orice
număr n, expresia n & 1 furnizează ca rezultat cel mai din dreapta bit. Putem scrie atunci
următoarea secvență:
cin >> n ;
if (( n & 1 ) == 1) cout << "Numar impar" ;
else cout << "Numar par" ;
Soluția 1:
Lecția 3. Siruri recurente. Baze de numerație. Operatii pe biti. Centrul de Excelenta Vaslui
Prof. Nicu Vlad-Laurențiu
int n1=0;
for ( int i=0; i<32; i++)
if (n & (1 << i)) n1++;
Soluția 2. Mai rapida deoarece numără doar biții de 1.
int n1=0;
do{
n &= n-1;
n1++;
}while (n);
5. Se consideră un număr natural n. Să se determine câtul şi restul împărțirii lui n la 8.
Generalizare: Să se determine câtul şi restul împărțirii lui n la un număr care este
putere a lui 2.
Rezolvare: Pentru determinarea câtului se utilizează deplasarea la dreapta cu 3 biți (ceea ce este
echivalent cu împărțirea prin 23).
Pentru rest se utilizează expresia n & 7 (unde 7 vine de la 23- 1 ). Deoarece 7 = 1112 atunci toți biţii
lui n vor fi anulați, cu excepția ultimilor 3 cei mai din dreapta.
Dar o soluție mai rapidă se bazează pe ideea că dacă n este o putere a lui 2, deci de forma
0000000000100000, atunci n-1 are reprezentarea de forma 0000000000011111, adică bitul
1 s-a transformat în 0, iar biții de la dreapta sunt acum toți 1.
Deci o expresie de forma n & (n-1) va furniza rezultatul 0 dacă și numai dacă n este o putere a
lui 2.
cin >> n ;
if ( (n & (n-1)) == 0 ) cout << "n este putere a lui 2" ;
else cout << "n nu este putere a lui 2" ;
8. Realizați un program care identifica numărul de ordine al celui mai semnificativ bit
de 1 al lui n număr natural nenul.
Rezolvare:
cin>>n;
n = n | (n >> 1);
n = n | (n >> 2);
n = n | (n >> 4);
n = n | (n >> 8);
n = n | (n >> 16);
n = n | (n >> 32);
int nm=0;
do
{
n &= n-1;
nm++;
}
while (n);
cout<<nm-1;
Rezolvare:
11. Realizați un subprogram care identifica cea mai mare putere a lui 2 care îl divide pe
n, număr natural nenul.
Rezolvare:
Soluția 1. Problema se reduce la determinarea celui mai nesemnificativ bit de 1 din reprezentarea
binar a lui n. Prima soluție caută poziția, pornind cu bitul 0.
int i=0;
while (!(n & (1<<i))) i++;
cout<<( 1 << i) ;
Soluția 2. Se bazează pe observația ca n & (n-1) are ca rezultat numărul din care lipește cel mai
nesemnificativ bit de 0. Atunci aplicând XOR intre valoarea inițiala a lui n si ce a lui n &(n-1) vom
obține valoarea cerut.
Exemplu:
n =(101000100)2
n & (n-1) =(101000000)2
n ^( n & (n-1)) =(000000100)2
cout<<(n^(n&(n-1)));
Exista mai multe coduri Gray in continuare vorbim despre "binary reflected Gray code".
Modul de construcție este destul de intuitiv: fiecare număr nou este format din cel anterior prin
modificarea celui mai puțin semnificativ bit, astfel încât numărul sa nu mai fi fost adăugat înainte la
sir.
2 3 011
3 2 010
4 6 110
5 7 111
6 5 101
7 4 100
Rezolvare:
int n;
cin>>n;
n=1<<n;
for(int i=0; i<n; i++)
cout<<i<<" "<<(i^(i>>1))<<'\n';
Probleme de rezolvat:
Pbinfo:1255,122,
Infoarena:
http://www.infoarena.ro/problema/lgput
http://www.infoarena.ro/problema/nim