首先给出一些定义.
置换:是一个排列.含义是将另外一个排列进行重排操做.
若是记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,gc
故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.gcd
任取一个能使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,正是咱们须要的结果.