De ce contează?
La un concurs de atletism sunt 4 alergători, dar pe podium încap doar 3 locuri: aur, argint, bronz. În câte feluri se poate completa podiumul? Aici nu doar ALEGI 3 oameni dintre cei 4 — îi și AȘEZI într-o ordine, fiindcă locul 1 nu e totuna cu locul 3. Exact asta numără aranjamentele: alegere plus ordine.
De ce A(n,k) = n·(n-1)·...·(k factori)
Vrei să alegi și să ordonezi k elemente distincte din n disponibile. Gândește
pe poziții, una câte una:
- pentru prima poziție ai
nvariante (orice element); - după ce ai fixat-o, pentru a doua poziție ai rămas cu
n - 1variante; - pentru a treia poziție:
n - 2variante; - ... și tot așa, până la poziția
k, unde mai ain - k + 1variante.
Înmulțești toate aceste numere (regula produsului, fiindcă alegerile sunt independente una de alta):
A(n,k) = n · (n-1) · (n-2) · ... · (n-k+1)
Observă că ai exact k factori, care scad din 1 în 1 pornind de la n.
Forma compactă cu factoriale este A(n,k) = n! / (n-k)!, dar pentru calcul e mai
ușor și mai sigur să înmulțești direct cei k factori — nu aduni la nesfârșit
factori care oricum se simplifică.
Exemplu pas cu pas: A(4,2) = 12
Ai elementele {A, B, C, D} și vrei să alegi și să ordonezi 2 dintre ele.
- prima poziție: 4 variante →
A,B,CsauD; - a doua poziție: 3 variante rămase (oricare în afară de cea deja folosită).
Deci A(4,2) = 4 · 3 = 12. Le poți enumera ca să te convingi:
AB AC AD BA BC BD CA CB CD DA DB DC
Sunt 12 perechi ordonate. Atenție: AB și BA apar amândouă, fiindcă
ordinea contează. Dacă ordinea NU ar conta (combinări), AB și BA ar fi
una singură, iar răspunsul ar fi pe jumătate: C(4,2) = 6.
Implementare C++
Calculăm produsul celor k factori, aplicând modulo la fiecare pas ca să nu
depășim domeniul lui long long când n e mare.
#include <iostream>
using namespace std;
const long long MOD = 1000000007;
// A(n, k) = n * (n-1) * ... * (n-k+1), modulo MOD
long long aranjamente(long long n, long long k) {
if (k < 0 || k > n) return 0; // nu poti ordona mai multe decat ai
long long rezultat = 1;
for (long long i = 0; i < k; i++) {
// factorii sunt n, n-1, ..., n-k+1
rezultat = (rezultat * ((n - i) % MOD)) % MOD;
}
return rezultat;
}
int main() {
cout << aranjamente(4, 2) << "\n"; // 12
cout << aranjamente(5, 5) << "\n"; // 120 (permutari: A(n,n) = n!)
cout << aranjamente(3, 5) << "\n"; // 0 (k > n)
return 0;
}Folosim long long și înmulțim modulo la fiecare pas: chiar dacă n are sute de
mii, fiecare produs intermediar rămâne sub MOD * MOD, deci încape lejer în
long long (care ține valori până la aproximativ 9.2 · 10^18).
Complexitate
| Mărime | Valoare |
|---|---|
| Timp | O(k) — un singur for de k pași |
| Spațiu | O(1) — doar variabila rezultat |
Calculul e direct și rapid: nu ai nevoie de tablouri sau de precalcularea factorialelor pentru o singură valoare A(n,k).
Cazul special A(n,n) = n! este chiar numărul de permutări ale celor n
elemente: alegi și ordonezi TOATE elementele. De exemplu A(5,5) = 5 · 4 · 3 · 2 · 1
= 120. Aranjamentele sunt deci o generalizare a permutărilor: permutarea e cazul
în care k ajunge egal cu n.
- Confuzia cu combinările: dacă „AB” și „BA” trebuie numărate ca variante
diferite, sunt aranjamente (ordinea contează). Dacă sunt aceeași alegere, sunt
combinări. Combinările au în plus împărțirea la
k!. - Numeri greșit factorii: A(n,k) are EXACT
kfactori, nun. Pentru A(10,3) înmulțești 10 · 9 · 8 (3 factori), te oprești, NU continui până la 1. - Overflow fără modulo: dacă uiți
% MODla fiecare pas sau foloseștiint, produsul depășește domeniul și obții valori negative aiurea. Mereulong longși modulo la fiecare înmulțire. - Uiți cazul k > n: matematic A(n,k) = 0 când vrei mai multe elemente decât
ai. Tratează-l explicit (
return 0), altfel un factor(n - i)devine negativ și calculul se strică.
| factor | n | n-1 | n-2 | ... | n-k+1 |
Recapitulare
- Aranjamentele A(n,k) numără în câte feluri alegi ȘI ordonezi
kdinnelemente; ordinea contează — aceasta e diferența-cheie față de combinări. - Formula este produsul a exact
kfactori: A(n,k) = n · (n-1) · ... · (n-k+1), calculat în O(k) culong longși% MODla fiecare pas. - Cazul A(n,n) = n! sunt permutările; dacă ordinea nu contează, vorbim despre combinări (alegi fără să ordonezi).