首先给出一些定义.
置换:是一个排列.含义是将另一个排列进行重排操作.
如果记A[i]为置换A的第i个元素,那么对一个排列进行置换A这个操作,表示将原先第i个位置上的数字挪到第A[i]个位置.
例如,置换(3,2,1)表示将整个排列颠倒顺序.置换(2,3,4,1)表示将每个元素放到右边相邻的位置,最右边的元素放到最左边的位置.
置换之间定义了乘法.两个置换A和B所带来的效果相当于置换C带来的效果,那么AB=C.
例如,(2,3,4,1)*(2,3,4,1)=(3,4,1,2),每个元素右移一个位置,进行两次,相当于每个元素右移两个位置.
置换乘法满足结合律但不满足交换律.
问题1:n个白色珠子和n个黑色珠子能排列成多少种不同的线性序列?
C(2n,n)即为答案.
问题2:n个白色珠子和n个黑色珠子能排列成多少种不同的线性序列?如果一个序列可以通过不断把最左侧的珠子拿到右边得到另一个序列,那么这两个序列是本质相同的序列.
这样的问题称为等价类计数问题.题目中会定义一类等价关系,满足等价关系的元素被看成同一类,只统计一次.
要用我们接下来描述的算法解决等价类计数问题,等价关系必须能够用多个置换组成的集合表示.如果集合中存在一个置换使得元素A变成元素B,那么A和B等价.
这个集合必须满足对称性,如果存在置换使得元素A变成元素B,就必须存在一个置换使得元素B变成元素A.
这个集合必须满足封闭性.集合中拿出两个置换A和B,A*B=C,那么C置换也必须在集合中.也就是说,如果我们进行一种置换A使元素x变成y,一种置换B使元素y变成z,那么集合中必须存在一种置换C使得x直接变成z.
这个集合中必须含有”单位元”,一个使得元素不发生变化的置换.也就是必须满足每个元素和自身等价.
根据等价关系,所有元素可以分为若干个等价类,同一类的元素相互等价,不同类的元素相互不等价.
圆排列问题实际上就是一个等价类计数问题:记”旋转”为把排列的第一个元素拿到最后,由于一个排列旋转0,1,2,3,…n-1次得到的结果一定不同,每个等价类中都有n个元素,一共有(n-1)!个等价类.
但是对于更广泛的问题,不同等价类中的元素数目不一定相同.
例如,对于问题2,n=2的时候有两个等价类,分别有2,4个元素.
0表示白色,1表示黑色.
0011,1001,1100,0110是一类
1010,0101是一类
我们不妨写个程序看看n=3的情况
000111,100011,110001,111000,011100,001110是一类
110010,100101,001011,010110,101100,011001是一类
110100,101001,010011,100110,001101,011010是一类.
010101,101010是一类
输出更多的情况观察一下规律?每一类的元素数目有什么特点?
我们可以发现,对于总长度为2n的序列,每一类的元素个数都是2n的约数.
假设某一类中含有m个元素,那么从中任意选择一个元素,不断旋转,一定可以得到全部m个元素.
我们可以用置换描述不同的旋转操作:对于长为n的序列,只能旋转0,1,…n-1次.更多的旋转次数一定和之前的某种次数是等价的,例如旋转n+2次相当于旋转2次.本题中,长度为2n的序列,则有2n种置换.
对于集合中的一个置换f,如果某个元素被f操作后和原先相同(不仅本质相同而且”看上去”也相同),那么称这个元素是f的一个不动点.
可以证明,等价类的数目就是所有置换的不动点数目的平均值.证明在最后.
那么对于这个问题,就是对旋转0,1,2,…2n-1次分别求出这个情况下”不变”的元素数目.
旋转0次不变的元素数目即为C(2n,n),任何一个元素都和本身一样.
旋转1次不变,则任意两个相邻位置的颜色相同,故不存在合法解.
旋转2次不变,那么奇数位置都相同,偶数位置都相同,有2种.
旋转m次不变,那么记G=gcd(2n,m),G,2G,3G…这些位置都相同,1,G+1,2G+1…这些位置都相同,因此我们只需要考虑前G个位置如何排列.只有当G为偶数的时候有C(G,G/2)个不动点.
如何证明等价类的数目就是所有置换的不动点数目的平均值?
(这个证明要求涉及的置换满足交换律,比如每个置换都是”旋转k次”的情况)
假设有n种置换,考虑某一个等价类,其中含有m个元素.假设对于其中某一个元素s1,把n个置换分成两类,有x种置换使得它变成它本身,y种置换使得它变成另外(m-1)个元素中的一个.x+y=n.
根据之前的定义,n种置换中存在一个单位元i使得一个元素变成和它相同的元素,那么这个置换i乘上另一个置换A一定还得到置换A.在之前分类的时候,i一定被分到前x种内.
首先我们证明对于这个等价类中的每个元素,x,y的数值是相同的.
假设s1,s2是这个等价类中的两个元素.必然可以找到一个置换A使得s1*A=s2,一个置换B使得A*B=i.
(如果置换A是”将长度为n的序列旋转k下”,那么置换B就是”将长度为n的序列旋转n-k下”)
s1*C=s1,s1*A=s2,
故s1*C*A=s2,s1*A*C=s2(这里使用交换律),
s2*C=s2.
也就是,置换C满足s1*C=s1(使s1变成相同的元素),那么一定满足s2*C=s2.
反过来,如果置换C满足s2*C=s2,那么一定也满足s1*C=s1,
因此对于s1和s2,使这个元素不变的置换的数目x是相同的,而且都是同样的x个置换,组成集合S.
针对元素s1,s2,我们一定恰好有x个置换使s1变成元素s2.
任取一个能使s1*A=s2的置换A,然后枚举S中的置换B,一共得到x个不同的A*B(其中包括A本身),
这x个A*B的结果对应的置换都能够使得s1变成s2.
有m-1个除了s1之外的元素,那么y=(m-1)x,n=mx
每个元素都会在x种置换中贡献一个不动点,一共贡献了n个不动点,最后还要除以n,
所以每个等价类对答案贡献了一个1,正是我们需要的结果.