# Số nguyên tố, Sàng Eratosthenes
## Số nguyên tố
### Thuật toán "ngây thơ"
Ta sẽ duyệt hết tất cả các số từ 1 đến $N$ và đếm số ước của $N$. Nếu số ước của $N$ là 2 thì $N$ là số nguyên tố, nếu không thì $N$ không là số nguyên tố.
```cpp
bool isPrime(int n) {
for (int i = 2; i < n; i++)
if (n % i == 0) {
// n chia hết cho số khác 1 và chính nó.
return false;
}
return n > 1;
}
```
Độ phức tạp: $O(N)$.
### Một thuật toán tốt hơn
Ta sẽ duyệt các số từ 1 đến $\sqrt{N}$.
```cpp
bool isPrime(int n) {
for (int i = 2; i*i <= n; i++)
if (n % i == 0) return false;
return n > 1;
}
```
Độ phức tạp: $O(\sqrt{N})$.
## Sàng Eratosthenes
Sàng nguyên tố dùng để tìm các số nguyên tố nhỏ hơn hoặc bằng $N$.
Nguyên lí hoạt động của sàng là vào mỗi lần duyệt, ta chọn một số nguyên tố và loại ra khỏi sàng tất cả các bội của số nguyên tố đó mà lớn hơn số đó. Sau khi duyệt xong, các số còn lại trong sàng đều là số nguyên tố.
```cpp
void sieve(int N) {
bool isPrime[N+1];
for(int i = 0; i <= N;++i) {
isPrime[i] = true;
}
isPrime[0] = false;
isPrime[1] = false;
for(int i = 2; i * i <= N; ++i) {
if(isPrime[i] == true) {
//Đánh dấu tất cả các bội của i là hợp số
for(int j = i * i; j <= N; j += i)
isPrime[j] = false;
}
}
}
```
Độ phức tạp: $O(N log N)$.
## Phân tích thừa số nguyên tố với sàng Eratosthenes
```cpp
vector<int> factorize(int n) {
vector<int> res;
for (int i = 2; i * i <= n; ++i) {
while (n % i == 0) {
res.push_back(i);
n /= i;
}
}
if (n != 1) {
res.push_back(n);
}
return res;
}
```
Độ phức tạp: $O(\sqrt{N})$.