http://wenku.baidu.com/link?url=uEZvNMcUgm0OlH6v39cTKrgXH31h_RO_YhqhMX3M95XVacbv4vzWI1BvV3aoKAtrczWEdXiB1FagPxXKxRU9d91YbkPExOoFg2dVxDrOTNq
置换在ACM里貌似经常碰到,以前不会,一直瞎搞,做不出,最近学了下,感觉懂了点东西,但是还是很多不会做
poj 2369
最基础的题,给你一个排列p,求k,使得p^k=p
就是求最小循环节,然后n是1000,最多有1000!个排列,如果暴力跑也许会炸掉,所以就用置换的性质,先找出所有的循环,然后循环阶数的lcm就是答案了
AC代码:http://paste.ubuntu.net/14677653/
poj 1026
题意:给你一个长度为n的置换,然后给你m是下面做置换的次数,再给你个字符串,长度为n,空的地方用空格,然后求置换后的字符串
题解:先把每个循环找出来,然后对每个循环,只要做t=m%(循环的阶数)这些就行了,然后就在循环里面找当前这个数后t个是什么,然后代换就行,就是输入有点坑爹,调了好久,傻叉了
AC代码:http://paste.ubuntu.net/14677658/
poj 1721
题意:给你一个置换p,然后每次都对自己做平方运算,就是变成p^2,p^4这样,然后给你一个置换q,它是开头p做了m次这样的运算得到的,就是q=p^(2^m),求p
题解:开头感觉无从下手,后来仔细一想,置换群是个封闭的运算,最多n!个置换,然后如果p是生成元,那么最后一个置换p^(n!),所以可以直接暴力做,因为这个平方运算每次是p的2次幂,然后最多暴力跑lg(n!)次,所以直接暴力跑,找到循环节cnt,m%=cnt,然后m=cnt-m,把q跑m次就得到p了
AC代码:http://paste.ubuntu.net/14677679/
CodeForces 612E
题意:给你个置换p,然后做平方运算,得到置换q,题目给你q,问你能否找到p,要构造出来
题解:这题和上面题看着有点类似,但是这题数据量是100W,不能暴力跑了,会炸掉,而且这题值做了一次平方运算,如果暴力跑有点亏啊
所以要找到规律,首先是找到置换里面的所有循环,然后考察每个循环,如果是奇数循环,平方运算之后还是奇数循环,如果是偶数循环,平方之后就变成了两个循环,阶数是原来大循环的一半。
所以构造能否成功就是看这个q里面的偶数循环能否都匹配,如果能匹配的话就再开始构造,就是有点繁琐,要把所有的循环都用vector记录下来,然后奇数就在自己的循环里构造,偶数的话就两个循环一起构造一个大的,就OK了,写起来有点烦而已
AC代码:http://paste.ubuntu.net/14677694/
还学习了将一个排列变成有序的最小花费,也是用置换做,但是poj炸了,代码还没交,题目挺难的都,仍需练习
还得学习polya定理和burnside定理
poj 3270
题意:给你一个排列,然后让你交换到递增排列,交换X和Y的位置,花费就是X+Y,求变成递增序列的最小花费
题解:这题如果不懂置换群,肯定没法做,首先你希望每次交换都能把一个值放到正确的位置,然后你需要找一个最小的元素,每次都和其他元素交换使之到达正确位置,然后一开始觉得就是找排列里最小的元素,然而这样并不一定对。我们来慢慢分析
先找到排列里的所有置换,然后如果你找的小的元素在置换内,将一个有k个元素的置换变成有序,只要k-1次,话费就是置换内所有元素和加上(k-2)*mini(置换中最小的值),这样是在置换里变换的最小花费,但是这就是正解么,未必,有可能置换外面有个很小的值,通过它来变换能得到更小的花费。
所以可以找置换外的最小值a,然后将置换里最小的元素换出去,再和其他k-1个元素换位,最后再把最小的换进来,这样就是这种方法的最小花费,然后每次考虑一个置换,都这样比较一下两种方案就行了
AC代码:http://paste.ubuntu.net/14875072/
poj 3590
题意:给你一个n,问你长度为n的排列里面,通过置换变成自己,即 p^k=p,求最大的k
题意:这题看似简单,其实还是挺难的,k最大,即为排列里面各个置换的长度的lcm最大。
假设各个置换的长度为n1+n2+....+nk=n,然后lcm(n1,n2,....nk)最大,并且按照最小字典序输出
只要知道了各个置换的长度,最小字典序就是长度排个序从小到大输出了,难就难在怎么找置换的长度
后来发现,lcm可以分解,设质数为p1,p2,p3,....pk, lcm=p1^a1 *p2^a2 * ....*pk^ak,然后思考怎么求置换长度呢,如果你取了个长度为p1,那么还是得有长度为p1^a1的置换,这样就浪费了,这样对lcm的增加没有帮主,因为你如果把长度p1的置换换成p1个长度1的置换,字典序变小了,lcm不变
所以我们找到了方法,置换的长度就是p1^a1,p2^a2.....pk^ak,然后多余的都变成长度1的置换,这样是可以保证字典序最小,于是我们只需要用100以内的素数dfs一遍lcm就行了,然后找到最大的lcm,同时保证sum和最小,然后把lcm素数分解,就知道了长度,排个序,然后就能得到排列了
AC代码:http://paste.ubuntu.net/14875123/
poj 3128
题意:给你26个字母的排列q,问你能不能找到p,使p^2=q;
题解:这题和上面cf的一样啊,就是找一下每种偶数长度置换的个数是不是偶数就行了
AC代码:http://paste.ubuntu.net/14875148/
uva 11077
题意:问你一个长度n的排列,需要k次才能变换成有序排列的个数是多少个
题解:在一个长度为m的置换里,变成有序需要m-1次,然后需要k次,可以用递推来做
dp[i][j]表示1-i变成有序,需要j次的排列个数
dp[i][j]=dp[i-1][j]+d[i-1][j-1]*(i-1),这是说明i要么自己成为一个循环,前面i-1个数字用了j次交换,要么就是i加入前面的置换里,和前面i-1个数中任意一个换一下位置,所以乘i-1,这样就多了一次交换
这题会爆long long,用unsigned long long
AC代码:http://paste.ubuntu.net/14875157/
下面来讲polya定理和burnside引理的题
uva 10294:
题意:给n个珠子,k个颜色,让你求项链和手镯的个数呗,这是最最简单的polya定理题,手镯是旋转翻转都认为一样,项链是只能旋转
题解:先考虑旋转,有n种旋转方法,每次转i格,i=0...n-1,求出gcd(i,n),这样求出来的是有多少个循环,然后就是sigma k^gcd(i,n),
翻转考奇偶,都是n种置换,奇偶情况不同,简单题
AC代码:http://paste.ubuntu.net/14875191/
uva 10601
题意:这题貌似给你个立方体,然后给你12条边的颜色,让你考虑这种涂色方案有多少种不同的立方体
题解:立方体里的polya定理,需要考虑一些情况,然后用组合数求解
先打表12的所有组合数,每次求解的时候要把知道循环里有多少个元素,然后每种颜色按照循环个数的分组,如果有的颜色不能整除循环里元素的个数的话,那么这种情况就是0
先是不动置换,只有一种置换有12个循环,循环里有1个元素,然后就是12组,如果是1个1,11个2,考虑每种颜色,就是先C(12,1),再乘C(11,11);
然后是面心旋转,正负90度,有2*3=6种置换,循环里有4个元素,3组循环,然后如果是1个1,11个2,1就不能整除4,所以不行,如果是4个1,8个2,1就能涂满1组,2能涂满2组,然后就是C(3,1)*C(2,2)
面心旋转180度,有3种置换,循环里有2个元素,6组循环,一样处理
对角旋转正负120度,2*4=8种置换,每个循环里有3个元素,共4组
棱心旋转180度,有6种置换,循环组成是(1)^2 (2)^5,有两个1,5个2的循环,这怎么破呢,因为只有6种颜色,所以可以枚举那两个1循环的颜色,然后再考虑分成5个2循环的情况
每次考虑不同的置换情况都需要初始化颜色的数组,不然就很容易错哦,最后除以置换总数1+6+3+8+6=24
AC代码:http://paste.ubuntu.net/14875266/
uva 11255
题意:给你三种颜色的珠子的个数,然后问你能构成几种不同的项链,这次的项链旋转和翻转一样
题解:和上一题一样,先考虑旋转,然后颜色分组,每次都要初始化不要忘记,翻转的话就是奇偶讨论,就是扣掉两个单独的颜色就行了,最后除以2n
AC代码:http://paste.ubuntu.net/14875311/
poj 2154
题意:给你n个珠子,n种颜色,然后串成项链,项链旋转当成一样,结果模P
题意:这题一开始觉得就和正常做一样就行了,n非常大,所以枚举n不行,就要把n的因子都处理出来,这是循环的个数,然后变成求因子的涂色方案,再求gcd(n,i)=这个因子的种数,就是求n/这个因子的欧拉函数,但是就是答案各种不对,因为要模p,所以以为要乘以n的逆元,后来发现逆元必须要求n和p互素,GG了
然后看题解,因为这题给你的是n种颜色啊,所以前面的n的几次方,可以直接除掉n,然后次方-1,然后就不需要用到逆元了orz,数学推导过弱,然后还是会TLE,原来是欧拉函数求解太慢了,不能用大白上的模版,要先素数打表打出来,然后用素数求解欧拉函数orz,这题瞬间学到了3种知识。
AC代码:http://paste.ubuntu.net/14875322/
poj 2888
题意:给你n个珠子,m种颜色,k个限制条件,就是什么颜色不能和什么颜色放在一起,求手镯的个数,旋转认为是相同
题解:这题看着和前面的有点类似也是处理出来因子,然后欧拉函数搞,但是这题多个限制,所以不好做,要考虑长度为k的这段里面的珠子应该怎么放
考虑到m只有10,所以可以用矩阵快速幂来解决,如果两个颜色可以相邻,map[i][j]=1,否则为0,然后长度为k的一段,p^k就是走了从第一个珠子走了k步的意思,是走到了下一段长度k的第一个,所以两个颜色应该是一样的,所以只要所有的p^k[i][i]加起来就行了orz
AC代码:http://paste.ubuntu.net/14875345/
hdu 2865
题意:给你n珠子k个颜色,然后中间还有个大珠子,要求所有相邻的珠子颜色都不同,旋转认为相同,考虑方案数
题解:这题和前面的思路差不多,处理因子,欧拉函数,然后这题的限制是不能有相邻颜色一样,考虑也是递推
F(i)表示长度为i的这段循环里,最后一个和首位颜色不一样的方案数,开头k种颜色,1个给了中间的珠子,所以直接可以考虑每段循环里用的颜色k=k-1
F(1)=0;因为不管放啥,相邻颜色都一样,要注意
F(2)=k(k-1)
F(3)=k(k-1)(k-2)
F(4)=(k-2)F(3)+(k-1)F(2),前面一项表示3和首位颜色一样,后面一项表示3和首位颜色不一样
所以得到递推F(n)=(k-2)F(n-1)+(k-1)F(n-2),然后矩阵快速幂一下就好叻
AC代码:http://paste.ubuntu.net/14875389/
置换群和polya定理的学习暂时结束,以后碰到再好好研究把,燃