Hướng dẫn giải của Tính điểm học sinh
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
Bài toán yêu cầu làm tròn điểm số của học sinh theo quy tắc sau:
- Nếu điểm < 38: không làm tròn, bị trượt.
- Nếu điểm >= 38: tìm mốc chia hết cho 5 lớn hơn hoặc bằng điểm đó. Nếu chênh lệch giữa mốc đó và điểm số < 3, thì làm tròn lên mốc đó. Ngược lại giữ nguyên.
Ví dụ: 73 gần 75 (chênh lệch 2) => làm tròn 75. 67 gần 70 (chênh lệch 3) => không làm tròn. 38 gần 40 (chênh lệch 2) => làm tròn 40. 33 < 38 => giữ nguyên 33.
Các cách tiếp cận
Cách Phép chia lấy dư và tính toán mốc
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int x;
cin >> x;
if (x < 38) {
cout << x;
} else {
int r = x % 5;
int next = x + ((5 - r) % 5);
if (next - x < 3) cout << next;
else cout << x;
}
if (t) cout << "\n";
}
return 0;
}
- Time Complexity: O(1) mỗi test case
- Space Complexity: O(1)
Hàm này kiểm tra nếu x < 38 thì in ra luôn. Nếu không, nó tính số dư r = x % 5. Để tìm số chia hết cho 5 tiếp theo, nó cộng thêm (5 - r) % 5 vào x (trường hợp r=0 thì cộng 0). Sau đó kiểm tra điều kiện chênh lệch < 3 để quyết định in số mới hay số cũ.
Cách Vòng lặp While tăng dần
#include <bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int a, t1 = 0;
cin >> a;
t1 = a % 5;
if (a < 38) cout << a << '\n';
else if (t1 >= 3) {
while (a % 5 != 0) a++; // Tăng a đến khi chia hết cho 5
cout << a << '\n';
}
else cout << a << '\n';
}
}
- Time Complexity: O(1) (vòng lặp chạy tối đa 4 lần)
- Space Complexity: O(1)
Cách tiếp cận này sử dụng vòng lặp để tăng giá trị a lên từng đơn vị cho đến khi nó chia hết cho 5. Điều này chỉ xảy ra khi số dư (a % 5) >= 3. Nếu số dư < 3, vòng lặp không chạy và giữ nguyên giá trị ban đầu. Logic này dựa trên việc so sánh số dư với 3.
Cách Tính toán mốc trực tiếp
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int c;
cin >> c;
if (c < 38) {
cout << c << "\n";
} else {
int next5 = ((c / 5) + 1) * 5; // Mốc 5 tiếp theo
if (next5 - c < 3) c = next5;
cout << c << "\n";
}
}
return 0;
}
- Time Complexity: O(1) mỗi test case
- Space Complexity: O(1)
Cách này tính toán mốc chia hết cho 5 tiếp theo bằng cách lấy thương của c chia 5, cộng thêm 1, rồi nhân lại với 5. Ví dụ: 73 / 5 = 14, +1 = 15, *5 = 75. Sau đó chỉ cần so sánh sự chênh lệch giữa mốc đó và điểm số ban đầu.
Phân tích độ phức tạp
| Cách tiếp cận | Time | Space | Tên |
|---|---|---|---|
| 1 | O(1) mỗi test case | O(1) | Phép chia lấy dư và tính toán mốc |
| 2 | O(1) (vòng lặp chạy tối đa 4 lần) | O(1) | Vòng lặp While tăng dần |
| 3 | O(1) mỗi test case | O(1) | Tính toán mốc trực tiếp |
Bài học kinh nghiệm
- Quy tắc làm tròn chỉ áp dụng khi điểm >= 38.
- Mốc làm tròn luôn là số chia hết cho 5 lớn hơn hoặc bằng điểm số hiện tại.
- Việc tính mốc chia hết cho 5 tiếp theo có thể làm bằng công thức
(x / 5 + 1) * 5hoặcx + (5 - x % 5). - Nếu số dư
x % 5>= 3, thì khoảng cách từxđến số chia hết cho 5 tiếp theo là5 - (x % 5)chắc chắn nhỏ hơn 3.
Lỗi thường gặp
- Quên kiểm tra điều kiện điểm < 38 trước khi làm tròn.
- Làm tròn sai cách tính mốc chia hết cho 5 tiếp theo (ví dụ: làm tròn xuống thay vì lên).
- Xử lý số dư bằng 0 (ví dụ 70) không đúng cách, có thể bị cộng thêm 5 thành 75.
- Điều kiện chênh lệch < 3 là严格小于 (strictly less than), không bao gồm bằng 3.
Bình luận