Hướng dẫn giải của Cắt bánh sinh nhật
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 tìm số lượng nhát dao tối thiểu cần cắt để chia một chiếc bánh hình chữ nhật có kích thước n x m thành n x m miếng bánh hình vuông 1 x 1. Mỗi nhát dao cắt phải đi dọc theo đường thẳng song song với cạnh của bánh và chỉ cắt qua các phần bánh đang nằm liền khối.
Các cách tiếp cận
Cách Trực quan - Tính theo hàng và cột
#include <iostream>
using namespace std;
int main() {
long long n, m;
cin >> n >> m;
// So luong cat theo hang: m - 1
// So luong cat theo cot: n - 1
// Tong so cat: (m - 1) + n * (m - 1) = n * m - 1
// Hoac tuong don: de co k miem phai can k-1 nhat dao
cout << n * m - 1;
return 0;
}
- Time Complexity: O(1)
- Space Complexity: O(1)
Cách này dựa trên suy nghĩ trực quan về việc cắt bánh. Ta có thể cắt dọc theo các hàng ngang trước. Để chia một hàng ngang dài m thành m miếng 1x1, ta cần m-1 nhát dao. Sau đó, ta có n hàng như vậy. Tuy nhiên, cách này không tối ưu. Cắt tối ưu là chia đôi miếng bánh liên tục. Ban đầu có 1 miếng. Mỗi nhát dao chia một miếng thành hai. Để có tổng cộng N = n*m miếng, ta cần N - 1 nhát dao.
Cách Công thức toán học (Quy luật)
#include <iostream>
using namespace std;
int main() {
long long n, m;
cin >> n >> m;
cout << n * m - 1;
return 0;
}
- Time Complexity: O(1)
- Space Complexity: O(1)
Đây là phương pháp tối ưu nhất. Xét quá trình cắt: Ban đầu có 1 miếng bánh. Mỗi nhát dao cắt một miếng bánh đang có thành 2 miếng. Vậy sau k nhát dao, ta có k+1 miếng bánh. Mục tiêu là có n * m miếng bánh (mỗi miếng 1x1). Do đó, ta cần tìm k sao cho k + 1 = n * m. Suy ra k = n * m - 1. Ví dụ: 3x2 = 6 miếng. Cần 6 - 1 = 5 nhát dao.
Phân tích độ phức tạp
| Cách tiếp cận | Time | Space | Tên |
|---|---|---|---|
| 1 | O(1) | O(1) | Trực quan - Tính theo hàng và cột |
| 2 | O(1) | O(1) | Công thức toán học (Quy luật) |
Bài học kinh nghiệm
- Bài toán có thể coi là bài toán chia một khối lượng (1 đơn vị) thành n*m phần bằng nhau. Mỗi lần chia tăng số lượng phần lên 1.
- Số nhát dao cần thiết luôn bằng tổng số miếng bánh cần thiết trừ đi 1.
Lỗi thường gặp
- Sử dụng biến kiểu
intcho n và m, dẫn đến tràn số (overflow) vì n, m có thể lên tới 10^9, tích của chúng lên tới 10^18. Cần dùnglong long. - Nhầm lẫn giữa số hàng và số cột dẫn đến công thức sai (ví dụ tính n(m-1) thay vì nm-1).
Bình luận