Hướng dẫn giải của Tính tổng các số chẵn trong [a, b]
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.
Lời giải này đang bị ẩn cho đến khi bạn chọn mở ra.
Chúng tôi khuyên bạn nên tự thử giải bài trước. Việc mở lời giải có thể làm lộ mất ý tưởng chính trước khi bạn có cơ hội tự giải.
Bạn phải đăng nhập để mở lời giải này.
Đăng nhậpTác giả: , , ,
Hiểu bài toán
Cho hai số nguyên a và b (với -10000 ≤ a ≤ b ≤ 10000). Nhiệm vụ là tính tổng tất cả các số chẵn nằm trong khoảng từ a đến b (bao gồm a và b). Ví dụ, với a=2 và b=4, các số chẵn là 2 và 4, tổng là 6.
Các cách tiếp cận
Cách Brute Force (Duyệt qua từng số)
#include <stdio.h>
int main() {
int a, b;
long long tong = 0;
scanf("%d %d", &a, &b);
for (int i = a; i <= b; i++) {
if (i % 2 == 0) {
tong += i;
}
}
printf("%lld", tong);
return 0;
}
- Time Complexity: O(N)
- Space Complexity: O(1)
Phương pháp này sử dụng một vòng lặp để duyệt qua từng số nguyên từ a đến b. Với mỗi số, ta kiểm tra xem nó có chia hết cho 2 không (dùng phép chia lấy dư i % 2 == 0). Nếu số đó chẵn, ta cộng nó vào biến tổng. Đây là cách làm trực quan nhất và dễ hiểu cho người mới học lập trình. Tuy nhiên, với khoảng cách giữa a và b lớn, nó sẽ chậm hơn các phương pháp khác.
Cách Công thức toán học (Optimized)
#include <stdio.h>
int main() {
int a, b;
scanf("%d %d", &a, &b);
// Tìm số chẵn đầu tiên >= a
int start = a;
if (start % 2 != 0) start++;
// Tìm số chẵn cuối cùng <= b
int end = b;
if (end % 2 != 0) end--;
// Nếu không có số chẵn trong đoạn
if (start > end) {
printf("0");
} else {
// Số lượng số chẵn: (end - start) / 2 + 1
// Tổng: (start + end) * số_lượng / 2
long long n = ((long long)end - start) / 2 + 1;
long long tong = (start + end) * n / 2;
printf("%lld", tong);
}
return 0;
}
- Time Complexity: O(1)
- Space Complexity: O(1)
Đây là phương pháp tối ưu nhất, chạy ngay lập tức bất kể a và b cách nhau bao xa. Thay vì duyệt từng số, ta dùng công thức tính tổng của một cấp số cộng.
Bước 1: Xác định số chẵn đầu tiên (start) trong đoạn [a, b]. Nếu a là số lẻ, start = a + 1.
Bước 2: Xác định số chẵn cuối cùng (end) trong đoạn [a, b]. Nếu b là số lẻ, end = b - 1.
Bước 3: Tính số lượng các số chẵn n = (end - start) / 2 + 1.
Bước 4: Tính tổng theo công thức tổng của cấp số cộng: Sum = n * (đầu + cuối) / 2 = n * (start + end) / 2.
Lưu ý sử dụng kiểu dữ liệu long long để tránh tràn số nếu tổng vượt quá giới hạn của kiểu int.
Phân tích độ phức tạp
| Cách tiếp cận | Time | Space | Tên |
|---|---|---|---|
| 1 | O(N) | O(1) | Brute Force (Duyệt qua từng số) |
| 2 | O(1) | O(1) | Công thức toán học (Optimized) |
Bài học kinh nghiệm
- Nếu a và b có khoảng cách lớn (ví dụ hàng chục triệu), cách duyệt tuần tự sẽ rất chậm (Time Limit Exceeded), trong khi cách dùng công thức toán học luôn chạy nhanh.
- Tổng của một dãy số arithmetic progression (cấp số cộng) có thể tính bằng công thức: Số lượng phần tử * (Phần tử đầu + Phân tử cuối) / 2.
Lỗi thường gặp
- Quên kiểm tra các trường hợp đặc biệt khi a hoặc b là số lẻ (ví dụ a=3, b=5 thì không có số chẵn nào, nhưng nếu chỉ bắt đầu từ a và lặp thì code vẫn chạy bình thường nếu viết không cẩn thận logic kiểm tra bắt đầu/kết thúc).
- Sử dụng biến lưu tổng có kiểu
intthay vìlong long. Trong bài này với giới hạn 10000, tổng tối đa khoảng 50 triệu nênint(2^31-1 ~ 2 tỷ) vẫn đủ, nhưng thói quen dùnglong longcho tổng là an toàn hơn ở các bài toán tổng quát. - Phép chia lấy dư với số âm trong C:
i % 2có thể trả về -1 nếuilà số âm lẻ. Tuy nhiên, logici % 2 == 0vẫn đúng để kiểm tra số chẵn trong hầu hết các trình biên dịch hiện đại, nhưng để an toàn tuyệt đối, có thể dùngabs(i) % 2 == 0.
Bình luận