【群论相关】Burnside引理&Polya定理

版权声明:侵删,转载请附带链接或评论 https://blog.csdn.net/corsica6/article/details/81806555

目录


由一个集合 G 和一个运算 · 构成,运算过程即为集合中任何两个元素 a , b a · b 的过程,运算 · 为具体给出的任意一种可行的运算,需要满足群公理的四个要求:

  1. 封闭性: a , b G , c G , a · b = c
  2. 结合律: a , b , c G , ( a · b ) · c = a · ( b · c )
  3. 单位元: e G , a G , a · e = e · a = a
  4. 逆元: a G , b G , a · b = b · a = e b = a 1

置换

下面是一个置换,

( 1 2 3 . . . n a 1 a 2 a 3 . . . a n )

将群的运算(即基本变换方式)用 f : a i ( 1 i n ) ( n G , a i , a i { 1 , 2 , . . . , n } ) 表示。具体置换为把初状态 ( 1 , 2 , 3 , . . . , n ) 的任意排列,用 a i 替代 i (设序列第 x 个位置上的元素为 i ,替代后序列上第 x 个位置上的元素为 a i )而得到新的一种排列,以上变换即为置换。

同样也可以看做置换 f : a i 分解成若干个不相关的循环组,每个循环组内的元素构成一个环,每个环上的元素都可以移动到下一个环上的位置而回到初始状态( i > a i , a i > a a i , . . . , > i ),也就是集合的一一映射关系。群则将置换的过程中元素的位置变换转化成了运算,用数学符号表示出来。

将置换看做群的运算方式,一个封闭群即为一个置换群。


不动点&等价类

设存在一种群内元素的排列方式 q i ,使得经过置换 f : a i 后的排列与原来相同( i = a i = a a i = . . . = i )。则 q i 这种排列方式的状态是 f : a i 置换的不动点。

等价类即是定义一种等价关系,一个状态若可以通过特定的置换得到另一个状态,则这两个状态是等价的,同属一个等价类。

一些题目中“求本质不同的方案”,就是求等价类个数。


Burnside引理

设置换 g : a i 的在可行的染色方案中的不动点个数为 C ( g ) G | G | 个不同的置换群的集合,则等价类个数为:

1 | G | i = 1 | G | C ( g i )

举个例子:

假设给正方形棋盘染黑白两色,轴对称同构,求本质不同方案数。

那么需要考虑:

  1. 水平对称 2.纵向对称 3.左上->右下斜对角线对称 4.右上->左下斜对角线对称

这四种置换,也就是四个置换群,分别求不动点个数即可。


Polya定理

B u r n s i d e 引理需要枚举所有置换的情况来求不动点,复杂度太高,于是引入 P o l y a 定理来更简捷地求置换群的不动点个数。

之前提到了可以将置换 f : a i 分解成若干个循环组,考虑对于不动点来说,每个循环组中的元素的状态(颜色)必须完全一致,而不同循环组之间互不相关。因此对于置换 f : a i ,有 x 种可选的颜色,循环组个数为 k C ( f ) = x k ,更新 B u r n s i d e 引理的式子,得到等价类个数为:

1 | G | i = 1 | G | x i k i

还是上面的例子,这时只需要观察求出不动点个数即可,一般来说题目中所求的不动点都有一些特殊的规律和性质,以保证快速求出。


例题

poj2154-Color

N 种颜色染一条长度为 N 的项链,旋转同构,求本质不同方案数。

观察规律发现对于旋转 1 , . . . , n 次的不同置换而言,循环组个数即为 g c d ( n , i )

再套用 B u r n s i d e 引理, P o l y a 定理,等价类个数为:

1 n n g c d ( n , i )

= d | n n d i = 1 n d [ g c d ( i , n d ) = 1 ]

= d | n n d ϕ n d

这样就可以 O ( n × log n ) 计算了,没有考虑求 ϕ d 的复杂度,似乎远小于 d

代码

#include<cstdio>
#include<map>
#include<cmath>
using namespace std;
const int N=4e4,MX=1e9;
typedef long long ll;
int T,n,mod,ans,p[N],tot;
bool pri[N];
map<int,int>phi;
inline int mul(int x,int y){return x*y%mod;}
inline int ad(int x,int y){x+=y;if(x>=mod) x-=mod;return x;}

inline void pre()
{
    int i,j;ll res;
    for(i=2;i<=MX/i;++i){
        if(!pri[i]) p[++tot]=i;
        for(j=1;j<=tot;++j){
            res=i*p[j];if(res*res>MX) break;
            pri[res]=true;
            if(i%p[j]==0) break;
        }
    }
}

inline int fp(int x,int y)
{
    int re=1;x%=mod;
    for(;y;y>>=1,x=mul(x,x))
     if(y&1) re=mul(re,x);
    return re;
}

inline int PHI(int x)
{
    if(x==1) return 1;
    int i,re=x;
    for(i=1;i<=tot && p[i]*p[i]<=x;++i)
      if(x%p[i]==0){
        for(;x%p[i]==0;x/=p[i]);
        re=re/p[i]*(p[i]-1);
      }
    if(x!=1) re=re/x*(x-1);
    return re%mod;
}

int main(){
    int i;
    pre();
    scanf("%d",&T);
    for(;T;--T){
        ans=0;
        scanf("%d%d",&n,&mod);
        for(i=1;i<=n/i;++i) if(n%i==0){
            ans=ad(ans,mul(fp(n,i-1),PHI(n/i)));
            if(i*i!=n) 
              ans=ad(ans,mul(fp(n,n/i-1),PHI(i)));
        }
        printf("%d\n",ans);
    }
}

m a p W A p o j # i n c l u d e < b i t s / s t d c + + . h > C E ,每次做 p o j 都会先 C E 多次…

bzoj1478: Sgu282 Isomorphism

题解
算是一个非常巧妙的运用了。


引用

以上写的都非常清晰易懂,总之比我写的好多啦。

猜你喜欢

转载自blog.csdn.net/corsica6/article/details/81806555