Học sinh giỏi 9 Thừa Thiên - Huế 2022 - 2023¶
Bài 1: Mật mã¶
Đề bài¶
Khi biết Hưng đã biết đi xe đạp vững vàng, ba Hưng mua tặng một xe đạp mới.
Để bảo vệ chiếc xe, Hưng dùng khoá dây mật mã mà mẹ tặng và chọn một số nguyên dương nhỏ nhất vừa chia hết cho tổng của các số là ngày, tháng, năm sinh của mẹ Hưng vừa chia hết cho tổng của các số là ngày, tháng, năm sinh của ba Hưng để làm mật mã của khoá xe.
Yêu cầu: tìm mật mã khoá xe.
Dữ liệu vào: MATMA.INP
- Dòng thứ nhất chứa các số lần lượt là ngày, tháng, năm sinh của mẹ Hưng.
- Dòng thứ hai chứa các số lần lượt là ngày, tháng, năm sinh của ba Hưng.
Kết quả: MATMA.OUT
Mật mã của khoá xe.
Ví dụ:
MATMA.INP | MATMA.OUT |
---|---|
1 1 1982 4 8 1980 |
494016 |
Bài giải đề xuất¶
Ý tưởng chính¶
Mật mã là số nguyên dương nhỏ nhất chia hết cho tổng ngày sinh của ba và tổng ngày sinh của mẹ. Điều này đồng nghĩa mật mã là bội chung nhỏ nhất của hai số tổng.
Viết chương trình¶
Bước 1:
Viết hàm tìm ước chung lớn nhất của hai số nguyên dương.
Bước 2:
Tìm bội chung nhỏ nhất theo công thức \(BCNN(a, b) = \frac{a \times b}{UCLN(a, b)}\).
Mã nguồn¶
Code đầy đủ được đặt tại GitHub.
Bài 2: Ngày công¶
Đề bài¶
Bác An là tổ trưởng của tổ sản xuất thuộc xí nghiệp bánh kẹo Hải Thành. Ngoài công việc tham gia sản xuất, mỗi tuần bác An còn phải quản lý tình hình làm việc của các công nhân trong tổ.
Yêu cầu: hãy giúp bác An sắp xếp số ngày làm việc của các công nhân trong tổ theo thứ tự giảm dần; tính tổng số ngày làm việc của tất cả công nhân; tính số ngày làm việc trung bình của tổ.
Dữ liệu vào: NGAYCONG.INP
- Dòng thứ nhất chứa \(n (1 \le n < 10^5)\) là số công nhân trong tổ.
- Dòng thứ hai chứa \(n\) phần tử là số ngày làm việc của mỗi công nhân.
Kết quả: NGAYCONG.OUT
Số ngày làm việc của các công nhân sau khi sắp xếp theo thứ tự giảm dần; tổng số ngày làm ciệc của tất cả công nhân; số ngày làm việc trung bình.
Ví dụ:
NGAYCONG.INP | NGAYCONG.OUT |
---|---|
5 1 6 3 7 2 |
7 6 3 2 1 19 3.80 |
Bài giải đề xuất¶
Ý tưởng chính¶
Để sắp xếp, ta có thể dùng hàm sort()
, có trong cả C++ lẫn Python.
Để tính tổng, ta có thể dùng hàm accumulate()
của C++ hoặc sum()
của Python.
Viết chương trình¶
Mã nguồn¶
Code đầy đủ được đặt tại GitHub.
Bài 3: Xâu đối xứng¶
Đề bài¶
Xâu S được gọi là xâu đối xứng khi những ký tự thuộc xâu S được viết từ trái qua phải cho kết quả giống như khi viết từ phải qua trái.
Xâu con của xâu S là một dạy các ký tự liên tiếp thuộc xâu S.
Cho một xâu S bất kỳ có độ dài \(n (1 \le n < 256)\).
Yêu cầu: cho biết độ dài của xâu con đối xứng dài nhất của xâu S.
Dữ liệu vào: PALINDROME.INP
Xâu S.
Kết quả: PALINDROME.OUT
Một số nguyên chỉ độ dài của xâu con đối xứng dài nhất của xâu S.
Ví dụ:
PALINDROME.INP | PALINDROME.OUT |
---|---|
Daua mua cacao | 3 |
Bài giải đề xuất¶
Ý tưởng chính¶
Để xét chuỗi con là palindrome dài nhất, ta sử dụng kỹ thuật mở rộng từ tâm (expand around center).
Duyệt từng ký tự của chuỗi s
:
- Ứng với vị trí
i
đang xét, tiến hành mở rộng sang trái và sang phải. - Trong khi mở rộng sang hai bên, nếu hai ký tự ở hai đầu trái và phải vẫn còn giống nhau, tức đối xứng, thì ta cập nhật độ dài đối xứng mới.
Cần lưu ý xét cả hai trường hợp: tâm chỉ có một ký tự và tâm có hai ký tự.
Viết chương trình¶
Mã nguồn¶
Code đầy đủ được đặt tại GitHub.
Bài 4: Chọn người¶
Đề bài¶
Công ty nấm Hương Sơn nằm trong khu nông nghiệp công nghệ cao. Nhằm trang bị thêm kiến thức nâng cao về nuôi trồng nấm cho đội ngũ công nhân, công ty xây dựng kế hoạch cử một đoàn công tác sang Nhật để học tập kinh nghiệm. Bộ phận nhân sự đã đề xuất \(N\) người để giám đốc công ty chọn ra \(K\) người tham gia.
Yêu cầu: hãy cho biết tất cả khả năng mà giám đốc đã đưa ra để chọn đúng \(K\) trong số \(N\) người.
Dữ liệu vào: CHONNGUOI.INP
Hai số \(N, K ( 1 \le K < N \le 10^5)\).
Kết quả: CHONNGUOI.OUT
- Các dòng hiển thị theo thứ tự từ điển các khả năng chọn đúng \(K\) trong số \(N\) người.
- Dòng cuối cùng chứa tổng số các khả năng để chọn đúng \(K\) trong số \(N\) người.
Ví dụ:
CHONNGUOI.INP | CHONNGUOI.OUT |
---|---|
3 2 | 1 2 1 3 2 3 3 |
Bài giải đề xuất¶
Ý tưởng chính¶
Đặt A
là mảng dùng để lưu một tổ hợp.
Tổ hợp đầu tiên là {1, 2, ..., k}
.
Bắt đầu từ tổ hợp trên, ta phát sinh tổ hợp tiếp theo bằng cách tìm vị trí i
lớn nhất sao cho A[i]
có thể tăng (A[i] < n - (k - i - 1)
), bằng cách tăng A[i]
lên 1 và cập nhật các phần tử tiếp sau nó.
Lưu ý về hiệu suất
Có lẽ đề bài này đã có nhầm lẫn gì đó. Bởi số tổ hợp \(\mathrm{C}_{n}^{k}\) với \(n \le 10^5\) là rất lớn, dẫn đến mất thời gian trong việc liệt kê tổ hợp và tập tin output tạo ra là rất lớn.
Ví dụ:
Với \(k = 2\), ta có \(\mathrm{C}_{10^5}^{2} = \frac{10^5 \times (10^5 - 1)}{2} = 4,999,950,000 \simeq 5 \times 10^{9}\) tổ hợp.
Còn với \(k = \frac{n}{2} = 500,000\), số tổ hợp là... oh my god 😱😱😱!!!
Viết chương trình¶
Bước 1:
Viết hàm phát sinh tổ hợp.
Bước 2:
Gọi hàm phát sinh tổ hợp và ghi kết quả ra file.
Mã nguồn¶
Code đầy đủ được đặt tại GitHub.