欢乐暑假线上编程比赛第三题:轮换数

来源:互联网 发布:应用宝软件 编辑:程序博客网 时间:2024/05/14 06:37
题目详情

把n各事物的集合划分成k个非空子集的方式数,比如{1,2,3,4}划分2个非空子集,我们可以得到7种划分方式:

{1,2,3}U{4};{1,2,4}U{3};{1,3,4}U{2};{2,3,4}U{1};{1,2}U{3,4};{1,3}U{2,4};{1,4}U{2,3}.相信大家一看就知道这

个怎么做吧,因为这就是著名的Striling数.但是今天的问题却是,计算n个元素安排城k个轮换(而不是子集)的

方式数.轮换是循环排列,也就是[A,B,C,D]=[B,C,D,A]=[C,D,A,B]=[D,A,B,C];而另一方面轮换[A,B,C,D]不同

于[A,B,D,C]或[D,C,B,A].那么比如给定四个元素[1,2,3,4]我们可以得到11种不同方式形成2个轮换:[1,2,3][4];

[1,2,4][3];[1,3,4][2];[2,3,4][1];[1,3,2][4];[1,4,2][3];[1,4,3][2];[2,4,3][1];[1,2][3,4];[1,3][2,4];[1,4][2,3] 现在

给出n个元素,求出k个非空的轮换数

输入格式:

多组数据,每组数据一行包含两个整数,n和k (1<=k<=n<=500)。

输出格式:

结果对2014取余数的最终结果



答题说明

输入样例

1 1

输出样例:

1


思路:动态规划。对于每个轮换,我们可以将它旋转使它里面的最小元素在最前面,称这种形式为最小表示。

判断两个轮换是否相同只需要通过旋转把它们里面最小的元素移到最前面,然后看最小表示是否相同。n个元

素的k轮换,假设这k个轮换每个轮换的最小元素是mi,其中1<=i<=k,由于轮换与轮换之间的位置无关,所

以我们假设对于i < j, 有mi < mj,则1到mj - 1这些元素肯定不在第j个轮换,假设k个轮换的元素从左到右存

放在数组array[n]当中。假设dp[i][j]表示前i个元素形成j个轮换的数量,则有可能前j-1个元素形成了前j-1个轮

换,或者前j个元素形成了前j-1个轮换,或者前j+1......。假设前t个元素形成了前j-1个轮换,那么对于第j个轮换

最小元素为t+1,对于后面的t+2到i这些元素,由于他们的摆放对j个轮换的最小元素没有影响,所以他们可以随

意摆放,即我们可以先将它们摆放在数组array中,所以有递推公式:

              


源代码(C++):


                                  

0 0