BCDIV - Chia nhóm

Tags: dp

Problem

https://vn.spoj.com/problems/BCDIV

https://oj.vnoi.info/problem/BCDIV

Một hôm trời nắng nóng bức, Chí Phèo nhà ta lại đến nhà Bá kiến đòi tiền mua rượu. Oái oăm thay, tên Bá Kiến keo kiệt hôm nay lại dở chứng bắt Chí phải thực hiện yêu cầu của mình rồi mới cho tiền. Chí tức tối lắm nhưng vì quá ghiền rượu nên hắn đành phải chấp nhận điều kiện mà cụ thể là giải 1 bài toán.

Bài toán có nội dung như sau :
Cho n phần tử khác nhau, hỏi có bao nhiêu cách chia n phần tử đó thành k nhóm mà mỗi nhóm có ít nhất 1 phần tử (các hoán vị của các nhóm được xem là 1 cách).

Vì thất học nên Chí nghĩ mãi không ra, các bạn giúp Chí 1 tay nhé, không thì hắn ta chết vì thèm rượu mất ^^

Dữ liệu vào:

  • Dòng đầu tiên chứa số T là số test.
  • T dòng tiếp theo mỗi dòng chứa 2 số N và K, với 1<=K<=N<=25

Dữ liệu ra:

  • T dòng, mỗi dòng là số cách với test tương ứng.
Input
1
4 2

Output
7

Giải thích : 7 cách chia đó là (ABC)(D) , (ABD)(C) , (ADC)(B) , (DBC)(A) , (AB)(CD) , (AC)(BD) , (BC)(AD)


Tutorial

Gọi F[i][j] là số cách chia i phần tử thành j nhóm. Khi đó, ta gọi I phần tử là A[1], A[2], …, A[i].

Xét A[i] : có hai trường hợp :

A[i] là một nhóm riêng biệt có 1 phần tử là chính nó, khi đó F[i][j] = F[i-1][j-1]

A[i] nằm trong nhóm của một số phần tử khác, tức là chia i-1 phần tử còn lại thành j nhóm sau đó cho A[i] vào một trong các nhóm đó.

F[i-1][j] cách chia mà A[i] có j cách chọn nhóm nên F[i][j] = j*F[i-1][j]

F[i][j] = F[i-1][j-1] + j*F[i-1][j]


Submission

BCDIV.cpp