ACM训练日记—1月29日

本文详细介绍了置换群的概念及Polya定理的应用,并通过多个实例解释如何使用这些理论解决实际问题,如计算不同颜色的珠子串成项链的不同方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

         今天总算结束了置换群&polya定理,另外还温习了母函数的内容和博客,另外看了斯特林数的知识点。这样明天完成高斯消元的内容,其实以前看过,但周六交流中发现我高斯消元这方面博客看的太少,太简单。明天全力高斯。另外还要复习前面的内容和题目。下面整理下置换群&polya定理。

         置换群&polya定理

1,定义:n元对称群的任意一个子群,都叫做一个n元置换群,简称置换群。

2,设f=(3,2,1,4),g=(2,4,3,1)。   g*f=(3,4,1,2)       f*g=(2,1,3,4)。

    (1)合成运算的封闭性:对于G中所有的置换f与g,f*g也属于G。

    (2)单位元:Sn中的恒等置换c也属于G。(c=(1,2,3,,,,n))

    (3)逆元的封闭性:对G中的每一个置换f,它的逆f^(-1)也属于G。

3,例子:顶点标为1,2,3,4,5,的正五角形。它的对称群D5包含5个旋转,5个反射。       所有G5

       5旋转:(1,2,3,4,5),(2,3,4,5,1),(3,4,5,1,2),(,5,1,2,3),(5,1,2,3,4)。

       5对称:(1,5,4,3,2),(3,2,1,5,4),(5,4,3,2,1),(2,1,5,4,3),(4,3,2,1,5)。

4,对于G中任一元f和C中任一元c,f*c仍属于C。

5,(g*f)*h=g*(f*h)。   满足结合律。

6, 不相连轮换相乘时可以交换。

7, 每个(非轮换)的置换都可表为不相连轮换之积;每个轮换都可表为对换之积,因此,每个置换都可表为对换之积。

8,每个置换表成对换的乘积时,其对换个数的奇偶性不变。

9,使着色c保持不变的所有置换集合G(c)称为c的稳定核。

10,对于每一种着色c,c的稳定核G(c)是置换群,而且对G中的任意置换f与g,g*c=f*c充要f^(-1)*g属于G(c)。

11,设G是X的置换群,而C是X中一个满足下面条件的着色集合,对于G中所有f和c中所有f*c仍在C中,C中非等价着色数N(G,C)=(C(c1)+C(c2)+...C(cn))/|G|,(f属于G)。     burnside定理

例:用n>=3种不同颜色的珠子串成一项链,问有多少种方法。

       共有n!种情况。

      N(Dn,C)=(n!+0+0+...+0)/(2n)

12,f=(6,8,5,4,1,3,2,7)=[1,6,3,5]*[2,8,7]*[4]。

      置换f的循环分解中的循环个数记为 #(f) 。     上面f,#(f)=3

      那么|C(f)|=k^(#(f))。         3^3=9.

13,Polya定理:设G={π1,π2,π3........πn}是X={a1,a2,a3.......an}上一个置换群,用m中颜色对X中的元素进行涂色,那么不同的涂色方案数为:1/|G|*(mC(π1)+mC(π2)+mC(π3)+...+mC(πk)). 其中C(πk)为置换πk的循环节的个数

 上下来自:http://blog.youkuaiyun.com/liangzhaoyang1/article/details/72639208

例子:

Θ不动:a1=(1)(2)(3)(4) 
Θ旋转90度 :a2=(1 2 3 4) 
Θ旋转180度 :a3=(1 3)(2 4) 
Θ旋转270度:a4=(1 4 3 2) 
比如,“逆时针旋转180度”,这个置换写成循环的乘积就是(1,3)(2,4),即1和3互变,2和4互变,不难发现,1和3的颜色必须相同,2和4的颜色也必须相同,而1-3和2-4的颜色互不相干。 
Polya定理得,共有(24+21+22+21)4=6(种方案). 
可以看Burnside引理和Polya定理是一样的,Polya定理是Burnside引理的优化。

习题:

1,poj2409

感谢:http://blog.youkuaiyun.com/chenzhenyu123456/article/details/46495673

题意:就是用c种颜色给n个珠子上色,通过旋转和翻转得到相同的算一种着色方式,问有多少种上色方式。

共有m种旋转置换和m种翻转置换。
对于旋转置换:每种置换的循环节数c(fi) = gcd(m,i),(i为一次转过多少个珠子即1 <= i <= m)
对于翻转置换:如果m为奇数,共有m种翻转置换,每种置换的循环节数均为c(f) = m/2 + 1;            
如果m为偶数,分两种情况 
(1)从空白处穿对称轴,则轴两边各有m/2个对象,得到c(f) = m/2;
(2) 从两个对象上穿对称轴,则轴两边各有m/2-2个对象,得到c(f) = m/2 + 1。

来自:http://blog.youkuaiyun.com/tuotq/article/details/50084077

ll polya(int c,int n)
{
    int i;
    ll ans=0;
    //旋转置换,共n种,每种旋转i个格,循环节有gcd(n,i)个
    for(i=0; i<n; i++)
    {
        ans+=(ll)pow(1.0*c,gcd(n,i));
    }
    if(n&1) //奇数翻转,沿每个点同中心点连线翻转共n种,
    {
        //循环节有(n-1)/2+1
        ans+=n*(ll)pow(1.0*c,(n+1)/2);
    }
    else //偶数翻转
    {
        ans+=n/2*(ll)pow(1.0*c,n/2);//两个相邻点中点和圆心
        //的连线也是n/2条,循环节的个数是n/2
        ans+=n/2*(ll)pow(1.0*c,n/2+1);//对称轴是每个点和对
        //面的点的连线,共n/2条,循环节的个数是 (n-2)/2+2
    }
    return ans/(2*n);
}

       就是套用polya公式,但要分析清楚所有情况。

2,Codeforces 612E Square Root of Permutation 

     题意:给定一个序列q,找p*p=q(即p[p[i]] = q[i])的p序列是否存在,不存在输出-1,存在输出任意一个p序列。

    (1)环的元素个数是偶数,经过一次变换后,环会分裂成两个元素大小相等的环。 
    (2)环的元素个数是奇数,经过一次变换后,环只是移动位置而不会发生分裂,只是位置发生变化。

3,hdoj2888

 部分参考:http://blog.youkuaiyun.com/tsaid/article/details/7371164

题意:给定n(n <= 10^9)颗珠子和m种颜色,这n颗珠子可以组成一串项链,每颗珠子可以用m中颜色来填充,如果两种涂色方法通过旋转项链可以得到,则两种涂色方法等价。现在再给定K组限制,每组限制a、b代表颜色a和颜色b不能涂在相邻的珠子上面。问一共有多少种涂色方法。

      补:A的k次幂表示图的长度为k的通路,回到自身则表示长度为k的回路

 可以理解为走n步共多少种走法。相当于用矩阵做。

4,poj2154

本题以下与代码均来自:http://blog.youkuaiyun.com/tsaid/article/details/7366708

题意:给出两个整数n和p,代表n个珠子,n种颜色,要求不同的项链数,翻转置换不考虑。结果模p.

      因为数据比较大,所以按照之前的方法会超时,要利用到欧拉函数进行优化。

题意:给出两个整数n和p,代表n个珠子,n种颜色,要求不同的项链数,翻转置换不考虑。结果模p.

题解:

我们知道gcd(i,n)表示了循环节的个数。例如gcd(2,6) = 2, 它的具体过程为:[1,3,5] [2,4,6]

对于任意一个循环置换,他所有循环节的长度为 n / gcd(i,n),在上面的例子中: 循环节长度 = 6 / gcd(2,6) = 3


为了方便说明,用L表示循环节的长度,显然 L | n

如果我们枚举L,求出对于每一个L有多少个i, 使得 L = n / gcd (i,n), 那么我们实际上也得到了循环节个数为 n / L 的置换个数。


L = n / gcd (i,n)转换一下得到:n / L = gcd(i,n )

设 cnt = n / L = gcd(i, n)  注:cnt表示循环节个数,L表示每一个循环节的长度

因为 cnt | i, 所以可令 i = cnt * t; ( 因为0 <= i < n, 所以0 <= t < n / cnt = L )

又因为 cnt = n / L, 所以 n = cnt * L;

则 gcd ( i, n ) = gcd ( cnt*t, cnt*L ) = cnt;  ①

可知当 gcd ( t, L ) = 1 时 ① 式成立。

由于 gcd ( t, L ) = 1 的个数就是 Euler(L)的个数,

所以我们可以得到结论:循环节个数为n/L的置换有Euler(L)个

int Polya ( int n, int m )  
{  
    int ret = 0;  
    for ( int l = 1; l*l <= n; l++ )  
    {  
        if ( n % l ) continue;  
        ret = (ret + Euler(l,m) * mod_exp(n, n/l-1, m)) % m;  
        if ( l * l == n ) break;  
        ret = (ret + Euler(n/l,m) * mod_exp(n, l-1, m)) % m;  
    }  
    return ret;  

 5,另外还有hdu2865是一道好题,矩阵快速幂+置换+欧拉函数优化+dp。这道题我恐怕现在还写不出来,就不搬别人博客了,推荐这道题。


到此几乎已经包括我看过的所有题型。关于欧拉函数优化的题其实还是应该在多看看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值