Hướng dẫn giải của Tổng nguyên tố (đề Lào Cai 2021)
Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Hướng dẫn giải
Cần đếm số cách viết ~n~ thành ~u + v~ với ~u < v~, trong đó cả ~u~ và ~v~ đều là số nguyên tố. Với ~n \le 300\,000~, chỉ cần duyệt ~u~ sao cho ~2u < n~ (để tránh cặp ~u = v~ và tránh đếm trùng).
Sub 1: Vét cạn — ~O(n \sqrt{n})~, dùng khi ~n \le 5000~
Duyệt mọi ~u~ với ~2u < n~, đặt ~v = n - u~, rồi kiểm tra từng số có phải nguyên tố bằng cách thử chia đến căn bậc hai. Nếu chỉ nộp sub này: đúng 25/25 test.
Sub 2: Sàng nguyên tố — ~O(n \log \log n)~
Sàng Eratosthenes đánh dấu hợp số đến ~n~ một lần. Sau đó mỗi ~u~ kiểm tra ~u~ và ~n - u~ trong ~O(1)~. Nếu chỉ nộp sub này: đúng 25/25 test.
Chương trình hoàn chỉnh
~main~ đọc ~n~. Nếu ~n \le 5000~ gọi sub1, ngược lại gọi sub2.
#include <bits/stdc++.h>
using namespace std;
long long n;
// Kiem tra nguyen to bang chia thu (dung trong sub1)
bool isPrime(long long x) {
if (x < 2) return false;
for (long long d = 2; d * d <= x; d++)
if (x % d == 0) return false;
return true;
}
// Sub 1: vet can. Thu moi u voi u < v = n - u, kiem tra ca u va v deu nguyen to.
// Moi kiem tra bang chia thu: O(n * sqrt(n)). Dung khi n <= 5000.
void sub1() {
long long cnt = 0;
for (long long u = 2; 2 * u < n; u++) {
long long v = n - u;
if (isPrime(u) && isPrime(v)) cnt++;
}
cout << cnt << "\n";
}
// Sub 2: sang nguyen to toi n mot lan, roi dem cap (u, v) nhu sub1. O(n log log n).
void sub2() {
vector<bool> comp(n + 1, false);
comp[0] = comp[1] = true;
for (long long i = 2; i * i <= n; i++)
if (!comp[i])
for (long long j = i * i; j <= n; j += i) comp[j] = true;
long long cnt = 0;
for (long long u = 2; 2 * u < n; u++)
if (!comp[u] && !comp[n - u]) cnt++;
cout << cnt << "\n";
}
int main() {
freopen("cau2b.inp", "r", stdin);
freopen("cau2b.out", "w", stdout);
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
if (n <= 5000) sub1();
else sub2();
return 0;
}
Bình luận