2048: 令D(n,n)为n人都拿到别人字条的情况数,则可知D(n,n)/A(n,n)为此情况出现的概率。首先有D(2,2)=1(即[2,1]), D(3,3)=2([2,3,1]和[3,1,2])。观察D(4,4)的所有9种情况([2,1,4,3],[3,1,4,2],[4,1,2,3],[2,4,1,3],[3,4,1,2],[4,3,1,2],[2,3,4,1],[4,3,2,1],[3,4,2,1]),可以将这9种情况分为两组:
1) 在D(3,3)的所有情况后加入4,然后将4与前面的元素逐一调换,得出的每一种情况都不重复且属于D(4,4):[2,3,1,4]=>[4,3,1,2],[2,4,1,3],[2,3,4,1]; [3,1,2,4]=>[4,1,2,3],[3,4,2,1],[3,1,4,2]。该情况的数量为D(3,3)*3;推广开来,对于D(n+1,n+1),情况数为D(n,n)*n;
2) 对于所有的D(3,2)情况(3人中2人拿到别人字条,1人拿到自己字条),即[1,3,2],[3,2,1],[2,1,3]添加4后,将4与拿到自己字条的人交换位置,也可以生成合法情况:[1,3,2,4]=>[4,3,2,1]; [3,2,1,4]=>[3,4,1,2]; [2,1,3,4]=>[2,1,4,3]。接下来再考虑D(3,2)的计算,它实际上可以看作是在D(2,2)上直接添加一个人得到,此时3人分为AB两组:A组2人都没有拿到自己的字条,B组1人拿到自己字条。A组的构成方法有C(3,2)种(也可以构成B组C(3,1),这是等价的,因为C(m,n)=C(m,m-n))。A组的组内情况有D(2,2)种,因此一共有C(3,1)*D(2,2)=D(2,2)*3种,推广开来,对于D(n+1,n+1),情况数为D(n-1,n-1)*n
将情况1)和2)相加可得递推公式D(n+1,n+1)=(D(n,n)+D(n-1,n-1))*n,其中初始状态D(2,2)=1,D(3,3)=2. 数值较大,建议使用unsigned long long
2049: 令D(m,n)为m对中n对配对错误的情况数,首先根据2048中的解法可求得所有D(m,m) (m in (1,20])的值,现在的问题变为如何求D(m,n) (m>n)。首先将m人分为AB两组:A组为n对配对错误的,B组为m-n对配对正确的。AB两组的分组方案有C(m,n)种,而对于A组,组内情况有D(n,n)种,对于B组,组内情况数为1,因此D(m,n)=D(n,n)*C(m,n)
OJ刷题真心挺好玩的,可谓寓教于乐的算法学习方法…