Olympic 11 Thành phố 2024 - 2025¶
Bài 1: Nghe nhạc¶
Đề bài¶
Bạn An rất thích nghe nhạc nhưng chỉ có \(k\) phút thời gian rảnh.
An có danh sách \(n\) bài hát, mỗi bài có độ dài là \(m_i\) phút. An phải nghe hết một bài hát trước khi nghe bài tiếp theo.
Yêu cầu: Hãy viết chương trình tìm ra một dãy liên tiếp các bài hát sao cho số lượng bài hát là nhiều nhất có thể và An phải đủ thời gian để nghe toàn bộ các bài hát này.
Dữ liệu: NGHENHAC.INP
- Dòng đầu tiên chứa hai số nguyên dương \(n\) và \(k\) \((1 \le n \le 10^5, 1 \le k \le 10^9)\).
- Dòng tiếp theo chứa \(n\) số nguyên dương \(m_i (1 \le m_i \le 10^4)\).
Kết quả: NGHENHAC.OUT
Một số nguyên là số lượng bài hát tối đa mà An có thể nghe.
Ràng buộc:
- 60% số điểm của bài: \(n \le 10^3\).
- 40% số điểm của bài: \(n \le 10^5\).
Ví dụ:
NGHENHAC.INP | NGHENHAC.OUT | Giải thích |
---|---|---|
5 20 9 3 5 4 7 |
4 | An có thể nghe các bài hát ở các vị trí 2, 3, 4, 5 với tổng thời gian là 19 phút. |
Bài giải đề xuất¶
Ý tưởng chính¶
Do yêu cầu tìm một đoạn liên tiếp thoả mãn thời gian không vượt quá \(k\), ta sử dụng cửa sổ trượt với hai con trỏ là left
và right
.
Viết chương trình¶
Mã nguồn¶
Code đầy đủ được đặt tại GitHub.
Bài 2: Học toán¶
Đề bài¶
Để ôn tập kiến thức về ước số chung lớn nhất và bội số chung nhỏ nhất cho em Na, bạn An đã chọn hai số nguyên dương \(a, b\) và yêu cầu em Na tìm hai số nguyên dương \(x, y\) sao cho thỏa mãn đồng thời ba điều kiện sau:
(1) \(a\) là ước số chung lớn nhất của \(x\) và \(y\).
(2) \(b\) là bội số chung nhỏ nhất của \(x\) và \(y\).
(3) Tổng của \(x\) và \(y\) là nhỏ nhất.
Yêu cầu: Hãy viết chương trình tìm hai số nguyên dương \(x\) và \(y\) thỏa mãn các điều kiện trên.
Dữ liệu: HOCTOAN.INP
2 số nguyên dương \(a\) và \(b\) \((1 \le a<b \le 10^4)\).
Kết quả: HOCTOAN.OUT
Gồm 2 dòng:
- Dòng đầu tiên ghi giá trị tổng của \(x\) và \(y\).
- Dòng tiếp theo ghi lần lượt hai số \(x\) và \(y\). Nếu có nhiều kết quả thì chọn kết quả có \(x\) nhỏ nhất. Nếu không tìm được \(x, y\) thì ghi số \(-1\).
Ràng buộc:
- 50% số điểm của bài: \(1 \le a, b \le 10^3\).
- 50% số điểm của bài: không ràng buộc gì thêm.
Ví dụ:
HOCTOAN.INP | HOCTOAN.OUT | Giải thích |
---|---|---|
6 36 | 30 12 18 |
Có các cặp số \((x, y)\) thoả điều kiện (1) và (2) là: (6, 36), (36, 6), (12, 18) và (18, 12). Cặp số (12, 18) và (18, 12) có tổng nhỏ nhất là 30 nhưng cặp (12, 18) có \(x\) nhỏ hơn nên được chọn làm kết quả. |
2 5 | -1 |
Bài giải đề xuất¶
Ý tưởng chính¶
Theo đề bài:
\(a = UCLN(x, y)\)
\(b = BCNN(x, y)\)
Mà \(\frac{x \times y}{UCLN(x, y)} = BCNN(x, y)\)
Suy ra
Vì \(a = UCLN(x, y)\) nên tồn tại \(x_1, y_1\) sao cho:
Thay vào \((1)\) ta được:
Mặt khác, ta cũng có:
Như vậy, bài toán ban đầu có thể phát biểu thành bài toán tương đương như sau:
Tìm hai số nguyên dương \(x_1\) và \(y_1\) sao cho:
-
\(x_1\) và \(y_1\) nguyên tố cùng nhau, hay \(UCLN(x_1, y_1) = 1\) (do \((2)\)).
-
Tích của \(x_1\) và \(y_1\) bằng \(p\), với \(p = b / a\) (do \((3)\)).
-
Tổng \(x_1\) và \(y_1\) là nhỏ nhất (do \((4)\)).
Viết chương trình¶
Bước 1: Viết hàm tìm ước số chung lớn nhất của hai số nguyên dương.
Bước 2:
Vì b
là bội chung lớn nhất và a
là ước chung lớn nhất của x
và y
, ta cần lưu ý trường hợp đặc biệt khi b
không chia hết cho a
.
Với trường hợp này, bài toán kết thúc, trả về -1
.
Bước 3:
Duyệt từng cặp ước số x1
và y1
của p
(với p = b / a
), ta xét cặp ước số nào nguyên tố cùng nhau (có ước chung lớn nhất bằng 1
) và có tổng là nhỏ nhất.
Vì \(x_1 < \sqrt{p} < y_1\) nên ta chỉ cần cho x1
chạy từ 1
đến sqrt(p)
. Điều này bảo đảm hiệu quả của việc tìm cặp ước, đó là nhanh hơn và không trùng lại ước cũ. Đồng thời cũng thoả yêu cầu đề bài là in ra output x
nhỏ hơn và y
lớn hơn.
Mã nguồn¶
Code đầy đủ được đặt tại GitHub.
Bài 3: Robot¶
Đề bài¶
Hai robot di chuyển trong một bảng hình chữ nhật có kích thước \(m \times n\) gồm các ô lưới vuông \(1 \times 1\) đơn vị.
Robot thứ nhất bắt đầu hành trình từ ô ở góc trái trên di chuyển đến ô ở góc phải dưới. Trong quá trình di chuyển, robot thứ nhất chỉ đi sang phải hoặc đi xuống dưới.
Robot thứ hai bắt đầu hành trình từ ô ở góc phải dưới di chuyển đến ô ở góc trái trên. Trong quá trình di chuyển, robot thứ hai chỉ đi sang trái hoặc đi lên trên.
Mỗi hành trình được mô tả bằng một xâu gồm các lệnh: L-sang trái, R-sang phải, U-đi lên, D-đi xuống. Bảo đảm các lệnh luôn dẫn các robot đi đến các vị trí cần đến.
Yêu cầu: Hãy viết chương trình tìm số lượng ô mà cả hai robot cùng đi qua trong hành trình. Biết rằng hai robot di chuyển vào hai thời điểm khác nhau nên không xảy ra va chạm khi đi vào cùng một ô.
Dữ liệu: ROBOT.INP
- Dòng đầu tiên ghi hai số nguyên \(m, n\) cho biết kích thước của bảng \((2 \le m, n \le 10^5)\).
- Dòng thứ hai mô tả hành trình của robot thứ nhất bằng một xâu chỉ gồm các kí tự D và R. Dòng thứ ba mô tả hành trình của robot thứ hai bằng một xâu chỉ gồm các kí tự U và L.
Kết quả: ROBOT.OUT
Một số nguyên \(K\) cho biết số ô mà cả hai robot cùng đi qua được.
Ràng buộc:
- 70% số điểm của bài: \(2 \le m, n \le 1000\).
- 30% số điểm của bài: không ràng buộc gì thêm.
Ví dụ:
ROBOT.INP | ROBOT.OUT |
---|---|
3 4 DRRDR ULLUL |
4 |
Bài giải đề xuất¶
Ý tưởng chính¶
Đặt visited_1
và visited_2
là các mảng hai chiều dùng để dánh dấu các ô đã đi qua của hai robot.
Duyệt từng chuỗi hành trình của hai robot và đánh dấu true
vào mảng visited_1
và visited_2
.
Sau đó, duyệt hai mảng trên để đếm các ô cùng toạ độ và đều là true
.
Viết chương trình¶
Bước 1: Khởi tạo
Khởi tạo các mảng hai chiều visited_1
và visited_2
ứng với hai robot.
Bước 2: Đánh dấu
Duyệt từng ký tự trong chuỗi hành trình input và đánh dấu true
vào mảng visited_1
và visited_2
.
Bước 3: Đếm số ô cùng đi qua
Duyệt hai mảng visited_1
và visited_2
để đếm số ô cùng toạ độ và đều là true
.
Mã nguồn¶
Code đầy đủ được đặt tại GitHub.