Hướng dẫn giải của Tìm số ngày của tháng


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, tuyetlancontact, tle778047, nguyencongk53e

Hiểu bài toán

Bài toán yêu cầu xác định số ngày trong một tháng của một năm dương lịch dựa trên đầu vào là tháng (month) và năm (year). Người dùng cần tuân thủ các điều kiện hợp lệ: 1 <= month <= 12 và year > 0. Nếu input không thỏa mãn, in ra 'INVALID'. Cần xử lý đúng năm nhuận để tính số ngày cho tháng 2.

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

Cách Kiểm tra điều kiện và in ra theo từng trường hợp (Nested If-Else)
#include <stdio.h>
int main(){
    int m,y;
    scanf("%d %d",&m ,&y);
    if(m<=0 || m>12 || y<=0) printf("INVALID");
    else{
        if(m==1||m==3||m==5||m==7||m==8||m==10||m==12) printf("31");
        else if(m==4||m==6||m==9||m==11) printf("30");
        else{
            if(y%400==0||(y%4==0 && y%100!=0)) printf("29");
            else printf("28");
        }
    }
    return 0;
}
  • Time Complexity: O(1)
  • Space Complexity: O(1)

Hàm main nhận input tháng và năm. Trước hết, kiểm tra xem tháng có nằm trong khoảng [1, 12] và năm có lớn hơn 0 không. Nếu không, in 'INVALID'. Nếu hợp lệ, sử dụng cấu trúc if-else lồng nhau để phân loại tháng: in 31 ngày cho các tháng 1, 3, 5, 7, 8, 10, 12; in 30 ngày cho các tháng 4, 6, 9, 11. Nếu không phải các tháng trên (tức là tháng 2), kiểm tra điều kiện năm nhuận (chia hết cho 400 hoặc (chia hết cho 4 và không chia hết cho 100)) để in 29 hoặc 28.

Cách Sử dụng hàm kiểm tra năm nhuận và cấu trúc rẽ nhánh
#include <stdio.h>
#include <stdbool.h>
int m;
long long y;

bool filter(int a, long long b){
    if ((a < 1) || (a > 12)) return false;
    if (b < 0) return false;
    return true;
}

bool nam_nhuan(long long a){
    if (a % 400 == 0) return true;
    else if ((a % 4 ==0) && (a % 100 != 0)) return true;
        else return false;
}

void process(){
    if (m == 2){ 
        if (nam_nhuan(y)) printf("%d", 29);
        else printf("%d", 28);
    }
    else{
        switch (m){
            case 1: case 3: case 5: case 7: case 8: case 10: case 12: printf("%d", 31); break;
            case 4: case 6: case 9: case 11: printf("%d", 30); break;
        }
    }
}

int main(){
    scanf("%d%lld", &m, &y);

    if (filter(m,y) == false) printf("INVALID");
    else process();

    return 0;   
}
  • Time Complexity: O(1)
  • Space Complexity: O(1)

Cách tiếp cận này tách biệt logic kiểm tra tính hợp lệ và xử lý logic tính số ngày. Hàm filter đảm bảo input hợp lệ. Hàm nam_nhuan helper giúp code dễ đọc hơn. Trong hàm process, sử dụng switch statement để xử lý các tháng có 31 hoặc 30 ngày, và if để xử lý riêng tháng 2 dựa trên kết quả kiểm tra năm nhuận.

Cách Tối ưu hóa cấu trúc in ra (Cải tiến logic)
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int a,b;
    scanf("%d %d",&a,&b);
    if((a>0&&a<=12)&&(b>-10000&&b<=10000))
    {
        if((b%400==0)||(b%4==0&&b%100!=0))
        {
            if(a==2) printf("29");
        }
        else printf("28");
        if(a==1||a==3||a==5||a==7||a==8||a==10||a==12) printf("31");
        else {if(a!=2) printf("30");}}
    else printf("INVALID");

    return 0;
}
  • Time Complexity: O(1)
  • Space Complexity: O(1)

Đây là một biến thể của Approach 1 nhưng có cấu trúc hơi khác thường. Nó kiểm tra năm nhuận trước. Nếu là năm nhuận và là tháng 2, in 29. Nếu không, in 28. Sau đó, nó kiểm tra xem có phải là các tháng 31 ngày hay không. Nếu không phải là các tháng 31 ngày và cũng không phải là tháng 2 (đã được xử lý ở trên), nó in 30. Cách này tận dụng việc in giá trị 28 mặc định cho tháng 2 nếu không phải năm nhuận.

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

Cách tiếp cận Time Space Tên
1 O(1) O(1) Kiểm tra điều kiện và in ra theo từng trường hợp (Nested If-Else)
2 O(1) O(1) Sử dụng hàm kiểm tra năm nhuận và cấu trúc rẽ nhánh
3 O(1) O(1) Tối ưu hóa cấu trúc in ra (Cải tiến logic)

Bài học kinh nghiệm

  • Cần kiểm tra tính hợp lệ của input (1 <= month <= 12, year > 0) trước khi tính toán.
  • Quy tắc năm nhuận: Chia hết cho 400 HOẶC (chia hết cho 4 VÀ không chia hết cho 100).
  • Các tháng 1, 3, 5, 7, 8, 10, 12 có 31 ngày.
  • Các tháng 4, 6, 9, 11 có 30 ngày.
  • Tháng 2 có 28 ngày, 29 ngày nếu là năm nhuận.

Lỗi thường gặp

  • Quên kiểm tra điều kiện year > 0 (chỉ kiểm tra month).
  • Sai điều kiện năm nhuận (ví dụ: chỉ kiểm tra year % 4 == 0 mà không loại trừ các năm chia hết cho 100 nhưng không chia hết cho 400).
  • Quên xử lý trường hợp INVALID khi input nằm ngoài giới hạn cho phép.
  • Lỗi kiểu dữ liệu khi xử lý năm (ví dụ: scanf không khớp với biến long long nếu dùng %d).

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.