phuctienn
Senior Member
Em cảm ơn bác nhiềuu, chi tiết, dễ hiểu lắm ạCũng không biết người khác ra sao, mình tiếp cận theo hướng phân tích các case cơ bản rồi suy ra pattern. Kiểu vầy:
Done, vậy tổng kết các kết luận trên, ta có thuật toán đại loại vầy:
- Đầu tiên dễ thấy, tổng n = 1 chắc chắn phải được tạo ra từ mảng [1], nếu trong mảng chưa có số 1 thì bắt buộc phải patch vào
- Tổng n = 2 thì sao ? Vì chắc chắn mảng đã tạo được tổng n = 1 rồi, nên:
- Nếu mảng có 1 số 1 nữa thì khỏi cần làm gì
- Nếu mảng chỉ có đúng một số 1 (đã dùng để tạo tổng n = 1 trước đó) thì:
- Mảng có số 2 không ? Nếu có thì ok
- Nếu không có thì lại có 2 hướng:
- Hoặc là patch thêm 1 số 1 vào
- Hoặc là patch thêm 1 số 2 vào
- => Chỗ này phân tích thì thấy patch số 2 lợi hơn vì khi đó auto tạo được số 3 luôn (chỗ này quan trọng)
- Lại nghĩ rộng ra, nếu mình đang tìm tổng bằng số n mà không cách nào tạo được với mảng hiện tại thì best solution là patch đúng số n đó vào
- Lại suy rộng ra tiếp:
- Nếu mình patch số n vào, mình sẽ tạo thêm được nhiều tổng khác lớn hơn n chứ không chỉ là tổng = n (từ chỗ in đậm)
- Ngẫm lại, nếu mình đang xét tới số n, nghĩa là trước đó mình đã xét xong các số từ 1 -> n - 1. Vậy h thêm số n thì chắc chắn sẽ tạo được thêm các tổng từ n -> 2 * n - 1
- Vậy nếu đang xét số n, mà phải patch, thì sau đó mình xét tiếp số 2 * n luôn (vì có thể skip đoạn n -> 2 * n - 1
- Ở trên toàn là trường hợp nếu phải patch, vậy nếu không cần patchthì sao ?
- Dễ thấy, trong case đơn giản, cũng tương tự như trên, nếu đang xét đến số n mà số đó có trong mảng thì auto skip luôn đến số 2*n
- Nhưng skip vậy thì các số ở trong mảng mà từ n -> 2*n - 1không dùng nữa à ?
- Đương nhiên vẫn phải dùng để tối ưu, nếu đang xét đến tổng = n rồi, thì các số trong mảng nhỏ hơn n sẽ không có tác dụng gì trong tương lai nữa
- Giả sử đang xét đến tổng = n, bây giờ dùng thêm số x vào thì dễ thấy sẽ tạo được thêm các tổng từ n + 1 -> n + x - 1.
- Hay nói cách khác, nếu đang xét số n mà trong mảng có số x <= n chưa dùng thì dùng luôn và skip đến số n + x
- Mình sẽ xét các tổng s từ 1 -> n, đến khi s > n thì ngưng
- Nếu đang xét và thấy trong mảng có số x nhỏ hơn s, thì skip s = s + x. Bỏ số x này ra khỏi mảng
- Ngược lại, nếu trong mảng có đúng số s => Skip s = 2*s. Bỏ số s này khỏi mảng.
- Ngược lại, phải patch số s này => Skip s = 2*s. Tăng biến đếm số lượng patch
- Đến khi s > n thì done => return số lượt patch




Mà thôi kệ biết là O(n) là được rồi
Cảm ơn bác chỉ cho em nha
