Hướng dẫn thuật toán

Trùm CUỐI 2026-01-11 11:08:32

Link bài tập

1. Phân tích đề bài

  • Mục tiêu: Tìm số cách kết hợp các đồng xu để có tổng bằng x .
  • Đặc điểm quan trọng: Thứ tự các đồng xu có quan trọng (ví dụ: 2+2+5 khác với 5+2+2 ). Đây thực chất là bài toán tìm số hoán đổi các đồng xu để đạt tổng x .
  • Ràng buộc: x lên đến 10^6 n đến 100 , vì vậy thuật toán cần có độ phức tạp khoảng O(n \cdot x) .

2. Ý tưởng thuật toán

Sử dụng Quy hoạch động (Dynamic Programming):

  • Gọi dp[i] là số cách khác nhau để tạo ra tổng số tiền bằng i.
  • Để có được tổng bằng i, bước cuối cùng ta có thể đã chọn một đồng xu mệnh giá c_j bất kỳ từ tập hợp n đồng xu (với điều kiện i \ge c_j ).
  • Khi đó, số cách để tạo ra tổng i chính là tổng của tất cả các cách tạo ra số tiền (i - c_j) với mọi đồng xu c_j .

3. Các bước thực hiện

  1. Khởi tạo:
    • Tạo một mảng dp kích thước x + 1 và gán tất cả giá trị ban đầu bằng 0 .
    • Đặt dp[0] = 1 (có duy nhất 1 cách để tạo ra tổng bằng 0 là không chọn đồng xu nào).
  2. Trạng thái chuyển đổi (Công thức truy hồi):
    • Duyệt i từ 1 đến x (tính toán số cách cho từng tổng tiền tăng dần):
      • Với mỗi i , duyệt qua từng mệnh giá đồng xu c_j trong danh sách.
      • Nếu i \ge c_j , ta cập nhật: dp[i] = (dp[i] + dp[i - c_j]) % (10^9 + 7).
  3. Kết quả:
    • Giá trị nằm tại dp[x] chính là đáp án cần tìm.

4. Lưu ý khi triển khai

  • Thứ tự vòng lặp: Để tính số hoán vị (thứ tự quan trọng), vòng lặp duyệt tổng tiền i phải nằm bên ngoài và vòng lặp duyệt các đồng xu c_j nằm bên trong. (Nếu đảo ngược hai vòng lặp này, bạn sẽ tính số tổ hợp - nơi thứ tự không quan trọng).
  • Xử lý Modulo: Vì kết quả có thể rất lớn, hãy thực hiện phép chia lấy dư % (10^9 + 7) ngay tại mỗi bước cộng trong vòng lặp để tránh tràn số.
  • Kiểu dữ liệu:
    • Trong C++: Nên dùng mảng int hoặc long long và cẩn thận với giới hạn thời gian (10^8 phép tính có thể mất gần 1 giây).
    • Trong Python: Do Python xử lý số nguyên lớn tốt nhưng tốc độ vòng lặp chậm, cần tối ưu bằng cách sử dụng PyPy hoặc các kỹ thuật giảm thiểu truy cập mảng.