Hướng dẫn giải của Số có tổng chữ số là số nguyên tố (RDSPRIME - ***)
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.
1. Tóm tắt đề bài
Cho hai số nguyên dương ~a~ và ~b~ (~a \le b~). Hãy đếm xem trong đoạn ~[a, b]~ có bao nhiêu số mà tổng các chữ số của nó là một số nguyên tố.
- Dữ liệu vào (Input):
- Một dòng chứa hai số nguyên dương ~a, b~ cách nhau bởi dấu cách (~1 \le a \le b \le 10^4~).
- Dữ liệu ra (Output):
- Một số nguyên duy nhất là số lượng số tìm được.
2. Phân tích bài toán & Giới hạn
- Giới hạn bài toán:
- ~a, b \le 10^4~.
- Số lượng số cần xét trong đoạn ~[a, b]~ tối đa là ~10^4~ số.
- Với mỗi số ~x \le 10^4~:
- Giá trị chữ số lớn nhất có thể đạt được là số ~9999~ với tổng chữ số ~9 + 9 + 9 + 9 = 36~ (hoặc với ~100000~ có tổng là ~1~).
- Do đó, tổng các chữ số của một số thuộc đoạn ~[1, 10^4]~ luôn nằm trong khoảng ~[1, 36]~.
- Phạm vi kiểm tra số nguyên tố:
- Vì tổng các chữ số nhỏ hơn hoặc bằng ~36~, việc kiểm tra một số có phải số nguyên tố hay không cực kỳ nhẹ và có thể viết một hàm kiểm tra đơn giản chạy với độ phức tạp ~\mathcal{O}(\sqrt{S})~ với ~S \le 36~.
- Đánh giá thời gian & Bộ nhớ:
- Việc duyệt từng số từ ~a~ đến ~b~, tính tổng chữ số và kiểm tra tính nguyên tố sẽ tốn không quá ~10^4 \times \mathcal{O}(\text{số chữ số} + \sqrt{36}) \approx 10^5~ phép tính. Thời gian chạy hoàn toàn tức thì (~< 0.01~ giây).
3. Thuật toán xử lý
Ý tưởng:
- Xây dựng hàm kiểm tra một số nguyên ~n~ có phải số nguyên tố hay không (
isPrime(int n)):- Nếu ~n < 2~: trả về
false. - Duyệt ~i~ từ ~2~ đến ~\sqrt{n}~ (
i * i <= n), nếu ~n~ chia hết cho ~i~ thì trả vềfalse. - Nếu không có ước nào thỏa mãn, trả về
true.
- Nếu ~n < 2~: trả về
- Xây dựng hàm tính tổng các chữ số của một số nguyên dương ~n~ (
tongChuSo(int n)):- Khởi tạo biến
sum = 0. - Sử dụng vòng lặp
while (n > 0), lấy chữ số hàng đơn vịn % 10cộng dồn vàosum, sau đó bỏ chữ số cuối bằngn /= 10. - Trả về giá trị
sum.
- Khởi tạo biến
- Trong hàm
main:- Khai báo hai biến ~a, b~ và biến đếm
dem = 0. - Nhập dữ liệu chuẩn:
cin >> a >> b;. - Duyệt vòng lặp
forvới biến ~i~ chạy từ ~a~ đến ~b~:- Tính tổng các chữ số của ~i~.
- Nếu tổng này là số nguyên tố thì tăng biến
demlên 1.
- In kết quả
demra màn hình và xuống dòng bằngcout << endl;.
- Khai báo hai biến ~a, b~ và biến đếm
- Xây dựng hàm kiểm tra một số nguyên ~n~ có phải số nguyên tố hay không (
Độ phức tạp:
- Thời gian: ~\mathcal{O}((b - a + 1) \cdot \log_{10}(b))~ — Duyệt qua các số trong đoạn ~[a, b]~, mỗi số mất vài phép toán để tách chữ số. Chạy cực nhanh trong thời gian ~< 0.01~ giây.
- Không gian (bộ nhớ): ~\mathcal{O}(1)~ — Chỉ dùng các biến đơn lẻ.
4. Mã nguồn cài đặt (C++)
#include <bits/stdc++.h>
using namespace std;
// Hàm kiểm tra số nguyên tố
bool isPrime(int n)
{
if (n < 2) return false;
for (int i = 2; i * i <= n; i++)
if (n % i == 0)
return false;
return true;
}
// Hàm tính tổng các chữ số của một số nguyên dương
int tongChuSo(int n)
{
int sum = 0;
while (n > 0)
{
sum += n % 10;
n /= 10;
}
return sum;
}
int main()
{
int a, b;
cin >> a >> b;
int dem = 0;
for (int i = a; i <= b; i++)
{
int tong = tongChuSo(i);
if (isPrime(tong))
dem++;
}
cout << dem << endl;
return 0;
}
Đang tải...