Documente Academic
Documente Profesional
Documente Cultură
Produsul cartezian
Fie n∈N și mulțimile A1, A2,…, An. Produsul cartezian A1×A2×…× An
este mulțimea n-uplurilor (x1,x2,…,xn) cu proprietatea că x1∈A1, x2∈A2,
…, xn∈An.
Regula produsului: Dacă mulțimile A1, A2., …, An au respective k1,k2.,
…,kn atunci numărul de elemente al produsului cartezian A1×A2×…
×An este k1⋅k2⋅…⋅kn.
1. ∅
2. 1 ; 2 ; 3
3. 1,2 ;1,3 ; 2,3
4. 1,2,3
Permutări
Se numește permutare o corespondență biunivocă (bijecție) între o
mulțime finită și ea însăși.
(123123),(123132),(123213),(123231),(123312),(123321)
Dacă σ=(123312), atunci σ(1)=3,σ(2)=1 și σ(3)=2.
Numărul de permutări al unei mulțimi cu n elemente este Pn=n!
=1⋅2⋅⋅…⋅n.
Acest articol conține mai multe despre factorialul unui număr.
Lectia nr. 3. – Elemente de combinatorica si jocuri combinatoriale
Problema
Fie un număr natural n. Să se afișeze, în ordine lexicografică,
permutările mulțimii {1,2,,⋯,n}{1,2,,⋯,n}.
Exemplu
Pentru n=3, se va afișa:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
Rezolvare
Bineînțeles, vom rezolva problema prin metoda backtracking. Vectorul
soluție x[] va reprezenta o permutare candidat. Să ne gândim care
sunt proprietățile unei permutări, pe care le va respecta și vectorul x[]:
Sursă C++
Lectia nr. 3. – Elemente de combinatorica si jocuri combinatoriale
#include <iostream>
using namespace std;
int x[10] ,n;
void Afis()
{
for( int j=1;j<=n;j++)
cout<<x[j]<<" ";
cout<<endl;
}
bool OK(int k){
for(int i=1;i<k;++i)
if(x[k]==x[i])
return false;
return true;
}
bool Solutie(int k)
{
return k == n;
}
void back(int k){
for(int i=1 ; i<=n ; ++i)
{
x[k]=i;
if( OK(k) )
if(Solutie(k))
Afis();
else
back(k+1);
}
}
int main(){
cin>>n;
back(1);
return 0;
Lectia nr. 3. – Elemente de combinatorica si jocuri combinatoriale
Varianta iterativă
În general, algoritmii nerecursivi sunt mai buni decât cei recursivi, deși uneori sunt mai dificil
de urmărit. Următorul program iterativ afișează și el permutările pe ecran:
#include <iostream>
using namespace std;
int n , x[100];
void afisare(int k){
for(int i = 1 ; i <= k ; i ++)
cout << x[i] << " ";
cout << endl;
}
bool OK(int k){
for(int i = 1 ; i < k ; i ++)
if(x[i] == x[k])
return 0;
return 1;
}
void back(){
int k = 1;x[1] = 0;
while(k > 0)
{
bool gasit = false;
do{
x[k] ++;
if(x[k] <= n && OK(k))
gasit = true;
}while(! gasit && x[k] <= n);
if(! gasit) k --;
else
if(k < n){
k ++;
x[k] = 0;
}
Lectia nr. 3. – Elemente de combinatorica si jocuri combinatoriale
else afisare(k);
}
}
int main(){
cin >> n;
back();
return 0;
}
Permutări cu repetiție
Considerăm un set de n obiecte de k.tipuri. Avem n1 obiecte de tipul 1,
n2 obiecte de tipul 2, …, nk obiecte de tipul k și n1+n2+…+nk=n.
Numărul de permutări distincte ale celor n obiecte este:
PR(n)=n! / (n1!⋅n2!⋅…⋅nk!)
Exemplu: Numărul de anagrame distincte ale cuvântului ABABA este:
Aranjamente
Dacă A este o mulțime cu n elemente, submulțimile ordonate cu k
elemente ale lui A, 0 ≤ k ≤ n se numesc aranjamente a n elemente luate
câte k.
Combinări
Lectia nr. 3. – Elemente de combinatorica si jocuri combinatoriale
Cnk=Ank / Pk
Cnk=n⋅(n−1)⋅…⋅(n−k+1). / (1⋅2⋅…⋅k)
Cnk=n! / (k!⋅(n−k)!)
Cnk={ 1 dacă k=0,
(n–k+1)/k⋅Cnk altfel.
Probleme infoarena
https://www.infoarena.ro/problema/superbec
Proprietăți
Lectia nr. 3. – Elemente de combinatorica si jocuri combinatoriale
Problemă
Se citește un număr natural n. Afișați linia n din triunghiul lui Pascal.
Lectia nr. 3. – Elemente de combinatorica si jocuri combinatoriale
Soluție cu combinări
O primă soluție constă în calcularea valorii Cnk pentru fiecare k∈{0,1,2,⋯, n}.
#include <iostream>
using namespace std;
int comb(int n , int k)
{
int p = 1;
for(int i = 1 ; i <= k ; i ++)
p = p * (n-i+1) / i;
return p;
}
int main()
{
int n;
cin >> n;
for(int i = 0 ; i <= n ; i ++)
cout << comb(n,i) << " ";
return 0;
}
Soluție cu matrice
În soluția următoare aplicăm formula Ai,j=Ai−1,j−1+Ai−1,j, folosind un tablou
unidimensional:
#include <iostream>
using namespace std;
int main()
{
int n, A[31][31];
cin >> n;
for(int i = 0 ; i <= n ; i ++)
{
A[i][0] = A[i][i] = 1;
for(int j = 1 ; j < i ; j ++)
A[i][j] = A[i-1][j-1] + A[i-1][j];
}
for(int j = 0 ; j <= n ; j ++)
cout << A[n][j] << " ";
return 0;
}
int main()
{
int n, v[31],u[31];
cin >> n;
v[0] = 0;
for(int i = 1 ; i <= n ; i ++)
{
u[0] = u[i] = 1;
for(int j = 1 ; j < i ; j ++)
u[j] = v[j-1] + v[j];
Lectia nr. 3. – Elemente de combinatorica si jocuri combinatoriale
int main()
{
int n, A[31], B[31];
int * u = A, * v = B;
cin >> n;
v[0] = 0;
for(int i = 1 ; i <= n ; i ++)
{
u[0] = u[i] = 1;
for(int j = 1 ; j < i ; j ++)
u[j] = v[j-1] + v[j];
swap(u,v);
}
for(int j = 0 ; j <= n ; j ++)
cout << v[j] << " ";
return 0;
}
Probleme infoarena:
https://www.infoarena.ro/problema/magic4
https://www.infoarena.ro/problema/xor3
n
n+ k
Cn=C –C 2n
n
2n
n+1
=1/(n+1)⋅C =∏ 2n
n
k
,pentru n≥0
k =2
O formulă recursivă:
n
C n+1=∑ C i ∙C n−i
i=0
/\
/\ /\ /\/\ / \
/\/\/\ / \/\ /\/ \ / \ / \
Probleme inforena :
https://www.infoarena.ro/problema/permutare4
https://www.infoarena.ro/problema/colors
#include<iostream>
#define NMax 1000
using namespace std;
typedef short Huge[NMax+3];
void AtribValue(Huge H,short X) {
H[0] = 0;
while (X) {
Lectia nr. 3. – Elemente de combinatorica si jocuri combinatoriale
++H[0];
H[H[0]] = X % 10;
X /= 10;
}
}
void Mult(Huge H,short X)
/* H <- H*X */
{short i,T=0;
for (i=1;i<=H[0];i++)
{ H[i]=H[i]*X+T;
T=H[i]/10;
H[i]=H[i]%10;
}
while (T) /* Cat timp exista transport */
{ H[++H[0]]=T%10;
T/=10;
}
}
{
Huge res;
AtribValue(res,1);
if(k>n-k) /// C(n, k) = C(n, n-k)
k=n-k;
for(unsigned int i=0;i<k;++i)
/// Calculez valoarea [n*(n-1)*---*(n-k+1)]/[k*(k-1)*---*1]
{
Mult(res,n-i); /// res*=n-i
Divide(res,i+1); /// res/=(i+1)
}
Divide(res,n/2+1); /// res/(n/2+1)
Afisez(res);
}
int main(){
int n;
cin>>n;
catalan(2*n,n);
return 0;
}
#include <iostream>
using namespace std;
unsigned long int catalanDP(unsigned int n)
{
unsigned long int catalan[n + 1];
catalan[0] = catalan[1] = 1;
for (int i = 2; i <= n; i++) {
catalan[i] = 0;
for (int j = 0; j < i; j++)
catalan[i] += catalan[j] * catalan[i - j - 1];
}
return catalan[n];
}
int main() {
Lectia nr. 3. – Elemente de combinatorica si jocuri combinatoriale
1. Ai⊆A,∀i=1,k
2. A1∪A2∪…∪Ak=A
3. Ai∩Aj=∅, ∀i≠j
1,2,3
1,2,3, 1,3,2, 1,2,3
1,2,3
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k; cin >> n >> k;
vector<vector<int>> stir(n + 1, vector<int>(k + 1));
stir[0][0] = 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= min(i, k); j++)
stir[i][j]=stir[i-1][j-1]+j*stir[i-1][j];
cout << stir[n][k] << '\n';
return 0;
Lectia nr. 3. – Elemente de combinatorica si jocuri combinatoriale
}
Numerele lui Stirling de speța I numără câte permutări de ordin n
cu k cicluri există, și se notează cu s(n,k).
#include<fstream>
#define MOD 98999
using namespace std;
ifstream fin("stirling.in");
ofstream fout("stirling.out");
int s[202][202],S[202][202];
int main(){
int t,p,n,m,i,j;
s[0][0]=1; S[0][0]=1;
for(i=1;i<=200;i++)
for(j=1;j<=i;j++){
s[i][j]=s[i-1][j]*(1-i)+s[i-1][j-1];
Lectia nr. 3. – Elemente de combinatorica si jocuri combinatoriale
s[i][j]%=MOD;
S[i][j]=S[i-1][j]*j+S[i-1][j-1];
S[i][j]%=MOD;
}
fin>>t;
for(i=1;i<=t;i++) {
fin>>p>>n>>m;
if(p==1) fout<<s[n][m];
else fout<<S[n][m];
fout<<'\n';
}
return 0;
}
A[0][1] = 1
primul element de pe liniile următoare este egal cu ultimul de pe
linia precedentă: A[i][1] = A[i-1][i]
celelalte elemente ale fiecărei linii sunt egale cu suma celor după
elemente din stânga (linia curentă și linia precedentă): A[i][j] =
A[i][j-1] + A[i-1][j-1], pentru j=2,..., i+1
primul element de pe fiecare linie este numărul Bell
corespunzător: B =A[n][1].
n
Lectia nr. 3. – Elemente de combinatorica si jocuri combinatoriale
Soluție:
#include<iostream>
using namespace std;
int bellNumber(int n) {
int bell[n+1][n+1];
bell[0][0] = 1;
for (int i=1; i<=n; i++) {
bell[i][0] = bell[i-1][i-1];
for (int j=1; j<=i; j++)
bell[i][j] = bell[i-1][j-1] + bell[i][j-1];
}
return bell[n][0];
}
int main() {
for (int n=0; n<=5; n++)
cout<<"Bell Number "<<n<<" este "<< bellNumber(n)<<endl;
return 0;
}
Numerele Narayana
Vezi paper20.pdf
Soluție
#include<bits/stdc++.h>
using namespace std;
int Nara(int n, int k)
{
Lectia nr. 3. – Elemente de combinatorica si jocuri combinatoriale