Hướng dẫn giải của Làm Tròn Điểm


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.

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ập

Tác giả: Hiếu Nguyễn, lqvinh13, DatBell, congtyluuthaibao1978

Hiểu bài toán

Bài toán yêu cầu làm tròn điểm số của sinh viên dựa trên các quy tắc:

  • Nếu điểm < 38: giữ nguyên.
  • Nếu điểm >= 38:
    • Nếu phần dư khi chia cho 5 nhỏ hơn 3 (tức là 0, 1, 2): giữ nguyên.
    • Nếu phần dư khi chia cho 5 lớn hơn hoặc bằng 3 (tức là 3, 4): làm tròn lên số chia hết cho 5 tiếp theo.

Điểm đặc biệt là nếu làm tròn lên tạo ra số chia hết cho 5, đó cũng là điểm số mới. Ví dụ, 38 sẽ được làm tròn lên 40 vì 38 % 5 = 3, và 5 - 3 = 2 < 3? Không, quy tắc là 'nếu phần dư >= 3 thì làm tròn lên'. 38 % 5 = 3, nên làm tròn lên 40. Tương tự 47 % 5 = 2 (< 3) nên giữ nguyên 47.

Các cách tiếp cận

Cách Logic Phép chia lấy dư (Modulo Logic)
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    while (n--) {
        int score;
        cin >> score;
        if (score >= 38 && score % 5 >= 3) {
            score += (5 - score % 5);
        }
        cout << score << "\n";
    }
    return 0;
}
  • Time Complexity: O(n)
  • Space Complexity: O(1)

Đây là cách tiếp cận trực tiếp nhất. Với mỗi điểm số, ta kiểm tra hai điều kiện:

  1. score >= 38: Điểm phải từ 38 trở lên mới được xem xét làm tròn.
  2. score % 5 >= 3: Phần dư khi chia cho 5 phải là 3 hoặc 4. Nếu cả hai điều kiện đều đúng, ta cộng vào số cần thiết để tròn lên 5. Ví dụ: 38 % 5 = 3, ta cộng 2 (5 - 3) để được 40. Code này xử lý ngắn gọn và hiệu quả ngay trong vòng lặp.
Cách Approach 2: Vòng lặp tăng dần (Increment Loop)
#include <bits/stdc++.h>
using namespace std;

int main() {
    int t;
    cin >> t;
    while (t--) {
        int a;
        cin >> a;
        if (a < 38) {
            cout << a << '\n';
        } else {
            int t1 = a % 5;
            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(n)
  • Space Complexity: O(1)

Cách tiếp cận này sử dụng vòng lặp while để tăng điểm số lên từng đơn vị cho đến khi nó chia hết cho 5. Logic là:

  1. Nếu điểm < 38: In ra.
  2. Nếu điểm >= 38:
    • Tính phần dư t1 = a % 5.
    • Nếu t1 >= 3: Bắt đầu vòng lặp while (a % 5 != 0) a++. Vì điều kiện t1 >= 3 đảm bảo rằng chỉ mất tối đa 2 bước tăng (ví dụ 38 -> 39 -> 40) để đến số chia hết cho 5. Vòng lặp này sẽ dừng lại ở số chia hết cho 5 đó.
    • Nếu t1 < 3: In ra số gốc. Phương pháp này đúng nhưng cồng kềnh hơn so với tính toán trực tiếp.
Cách Approach 3: Kiểm tra điều kiện trực tiếp
#include <iostream>
using namespace std;

int main() {
    int n; cin >> n;
    while(n--) {
        int d; cin >> d;
        if (d < 38) {
            cout << d;
        } else {
            int r = d % 5;
            // Điều kiện 5 - r < 3 có nghĩa là r > 2 (tức r >= 3)
            // 5 - r là số cần cộng thêm
            if (5 - r < 3) cout << (d + (5 - r));
            else cout << d;
        }
        if (n) cout << "\n";
    }
    return 0;
}
  • Time Complexity: O(n)
  • Space Complexity: O(1)

Đây là biến thể của Approach 1, sử dụng một công thức toán học khác để kiểm tra. Thay vì kiểm tra d % 5 >= 3, code này kiểm tra 5 - r < 3. Giải thích:

  • r = d % 5 (giá trị 0, 1, 2, 3, 4).
  • 5 - r là số tiền cần cộng để tròn lên.
  • Nếu r = 0: 5 - 0 = 5 (>= 3) -> False -> Giữ nguyên. Đúng.
  • Nếu r = 2: 5 - 2 = 3 (>= 3) -> False -> Giữ nguyên. Đúng.
  • Nếu r = 3: 5 - 3 = 2 (< 3) -> True -> Cộng thêm 2. Đúng.
  • Nếu r = 4: 5 - 4 = 1 (< 3) -> True -> Cộng thêm 1. Đúng. Logic này hoàn toàn chính xác và là một cách diễn đạt khác của quy tắc làm tròn.

Phân tích độ phức tạp

Cách tiếp cận Time Space Tên
1 O(n) O(1) Logic Phép chia lấy dư (Modulo Logic)
2 O(n) O(1) Approach 2: Vòng lặp tăng dần (Increment Loop)
3 O(n) O(1) Approach 3: Kiểm tra điều kiện trực tiếp

Bài học kinh nghiệm

  • Vấn đề chỉ yêu cầu xử lý các số nguyên, phép toán % và phép cộng cơ bản là đủ.
  • Điều kiện quan trọng nhất là score >= 38score % 5 >= 3. Kết hợp hai điều kiện này là chìa khóa.

Lỗi thường gặp

  • Làm tròn sai các số nhỏ hơn 38 (ví dụ: 33, 34) nếu bỏ qua điều kiện >= 38.
  • Tính toán sai giá trị cộng thêm (ví dụ: cộng thẳng phần dư thay vì trừ cho 5).

Bình luận

Please read the guidelines before commenting.


Không có bình luận tại thời điểm này.