初涉OI中的群论(Burnside引理和Polya定理)

前言

群论什么的,略玄学…就算你看懂了…也不一定做得出题…

一开始看懂了一点…然而做的第一道题就让这只蒟蒻窒息了…所以写个笔记,也算留作以后复习使用,有错请指出谢了。

“群”

给定一个集合G和一个运算@,一个群(G,@)需要满足:

1.封闭性: ∀ a , b ∈ G , ∃ c ∈ G , a @ b = c \forall a,b \in G, \exists c \in G, a@b=c a,bG,cG,a@b=c

2.结合律: ∀ a , b , c ∈ G , ( a @ b ) @ c = a @ ( b @ c ) \forall a,b,c \in G,(a@b)@c=a@(b@c) a,b,cG,(a@b)@c=a@(b@c)

3.单位元: ∃ e ∈ G , ∀ a ∈ G , a @ e = e @ a = a \exists e \in G,\forall a \in G,a@e=e@a=a eG,aG,a@e=e@a=a

4.逆元: ∀ a ∈ G , ∃ b ∈ G , a @ b = b @ a = e \forall a \in G, \exists b \in G, a@b=b@a=e aG,bG,a@b=b@a=e,记 b = a − 1 b=a^{-1} b=a1
以上摘自《信息学奥赛之数学一本通》

“置换群”

置换 ( 1 2 . . . n a 1 a 2 . . . a n ) \begin{pmatrix} 1 & 2 & ... & n \\ a_1& a_ 2 &...&a_n\end{pmatrix} (1a12a2......nan)的含义为原来数列为 ( 1 , 2 , . . . n ) (1,2,...n) (1,2,...n),用 a 1 a_1 a1代替1,用 a 2 a_2 a2代替2,用 a n a_n an代替n。其中, a 1 , a 2 . . . ∈ { 1 , 2 , . . . } a_1,a_2... \in \{ 1,2,...\} a1,a2...{1,2,...}且互不相同。

举个栗子QWQ,有三个同学A,B,C坐成一排,那么置换 ( 1 2 3 2 3 1 ) \begin{pmatrix} 1&2 &3\\2 &3 &1\end{pmatrix} (122331)就代表一次更换座位的过程。座位被换成了A,B,C
而置换群中的元素是置换,@运算则是置换之间的连接(如下)。

( 1 2 3 2 3 1 ) ( 2 3 1 3 2 1 ) = ( 1 2 3 3 2 1 ) \begin{pmatrix} 1&2 &3\\2 &3 &1\end{pmatrix}\begin{pmatrix} 2&3 &1\\3 &2 &1\end{pmatrix}=\begin{pmatrix} 1&2 &3\\3 &2 &1\end{pmatrix} (122331)(233211)=(132231)

检验一下发现,置换群满足群的定义。

Burnside引理

问题:神明boshi(在mc里)创造天地,也创造众生。现在他要用m种颜色给n只绵羊染色,并且给出s个置换,用于置换绵羊。凡是通过这些置换可以变得一样的染色方案算作同一种,求boshi有多少种不同的染色方案。

对于一个置换 g g g,若存在一种染色方案 s s s,使得 s s s在经过该置换后不变,则称 s s s g g g的一个不动点

设置换 g i g_i gi的不动点数目为 D ( g i ) D(g_i) D(gi) L L L表示本质不同的方案数, G G G是置换群中的集合,则有:

L = 1 ∣ G ∣ ∑ j = 1 s D ( g j ) L=\frac{1}{|G|}\sum_{j=1}^sD(g_j) L=G1j=1sD(gj)

本质不同的方案数为置换的不动点数目的平均值

注意有时一个置换做多次后会变成不同置换,要看题目怎么说。

Polya定理

现在我们定义循环 ( a 1 a 2 . . . a n ) = ( a 1 a 2 . . . a n a 2 a 3 . . . a 1 ) (a_1 a_2 ... a_n)=\begin{pmatrix} a_1&a_2 &... &a_n\\a_2 &a_3 &... &a_1\end{pmatrix} (a1a2...an)=(a1a2a2a3......ana1)

那么每一个置换就可以表示为执行若干循环的结果,例如: ( 1 2 3 3 2 1 ) = ( 13 ) ( 2 ) \begin{pmatrix} 1&2 &3\\3 &2 &1\end{pmatrix}=(13)(2) (132231)=(13)(2)(即交换1和3,2不变)

以上的表示法中,括号数=循环节数,记置换 g i g_i gi的循环节数为 c ( g i ) c(g_i) c(gi)
Polya定理为(字母含义和Burnside引理中相同):

L = 1 ∣ G ∣ ∑ j = 1 s m c ( g j ) L=\frac{1}{|G|}\sum_{j=1}^s m^{c(g_j)} L=G1j=1smc(gj)

其实也就是同一个循环节染成同一种颜色,就是在置换下没有变化的方案啦,所以 D ( g i ) = m c ( g i ) D(g_i)=m^{c(g_i)} D(gi)=mc(gi)

应用

poj2154

题目大意:用n种颜色染一个有n颗珠子的环形项链,可以通过旋转得到的相同方案视作相同,问有多少种不同的方案。

题目分析:
所有的置换很容易得出来,如果置换0为 ( 1 2 . . . n 1 2 . . . n ) \begin{pmatrix} 1&2 &... &n\\1 &2 &... &n\end{pmatrix} (1122......nn)的话,那么置换i的循环节数是 g c d ( n , i ) gcd(n,i) gcd(n,i),根据Polya定理得到:

L = 1 n ∑ i = 1 n n g c d ( i , n ) L=\frac{1}{n}\sum_{i=1}^n n^{gcd(i,n)} L=n1i=1nngcd(i,n)
= 1 n ∑ d ∣ n n d ∑ i = 1 n [ g c d ( i , n ) = d ] =\frac{1}{n}\sum_{d|n}n^d\sum_{i=1}^n[gcd(i,n)=d] =n1dnndi=1n[gcd(i,n)=d]
= ∑ d ∣ n n d − 1 ∑ i = 1 n [ g c d ( i / d , n / d ) = 1 ] =\sum_{d|n}n^{d-1}\sum_{i=1}^n[gcd(i/d,n/d)=1] =dnnd1i=1n[gcd(i/d,n/d)=1]
= ∑ d ∣ n n d − 1 ∑ i = 1 n / d [ g c d ( i , n / d ) = 1 ] =\sum_{d|n}n^{d-1}\sum_{i=1}^{n/d}[gcd(i,n/d)=1] =dnnd1i=1n/d[gcd(i,n/d)=1]
= ∑ d ∣ n ϕ ( n / d ) n d − 1 =\sum_{d|n}\phi(n/d)n^{d-1} =dnϕ(n/d)nd1

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int read() {
	int q=0;char ch=' ';
	while(ch<'0'||ch>'9') ch=getchar();
	while(ch>='0'&&ch<='9') q=q*10+ch-'0',ch=getchar();
	return q;
}
const int N=100005;
int T,n,mod,ans,tot,is[N],pri[N];
void init() {
	for(int i=2;i<=100000;++i) {
		if(!is[i]) pri[++tot]=i;
		for(int j=1;j<=tot&&pri[j]*i<=100000;++j) {
			is[pri[j]*i]=1;
			if(!i%pri[j]) break;
		}
	}
}
int ksm(int x,int y) {
	int re=1;x%=mod;
	while(y) {
		if(y&1) re=re*x%mod;
		x=x*x%mod,y>>=1;
	}
	return re;
}
int phi(int x) {
	int re=x;
	for(int i=1;pri[i]*pri[i]<=x;++i) if(!(x%pri[i])){
		re=re-re/pri[i];
		while(!(x%pri[i])) x/=pri[i];
	}
	if(x!=1) re=re-re/x;
	return re%mod;
}
int main() {
	init(),scanf("%d",&T);
	while(T--) {
		scanf("%d%d",&n,&mod);ans=0;
		for(int i=1;i*i<=n;++i) if(!(n%i)) {
			ans+=phi(i)*ksm(n,n/i-1)%mod,ans%=mod;
			if(i*i!=n) ans+=phi(n/i)*ksm(n,i-1)%mod,ans%=mod;
		}
		printf("%d\n",ans);
	}
	return 0;
}

uva10601

题目大意:给你12条用6种以下颜色染色的棍子,问可以组成多少本质不同的正方体

题目分析

可以假设那是一个骰子,以某一个数字为上面,一个数字为前面,所以共有 6 ∗ 4 = 24 6*4=24 64=24种旋转。

这24种旋转为:

1.不旋转,1种,12个循环节,长度为1

2.通过两个对立的顶点旋转120°和240°,共8种,4个循环节,长度为3

3.通过两个对立面的中心旋转90°或270°,共6种,3个循环节,长度为4

4.通过两个对立面的中心旋转180°,共3种,6个循环节,长度为2

5.通过两条对立棱的中心旋转180°,共6种,2个循环节长度为1,5个循环节长度为2

然后每组情况,可以用组合数学搞一搞即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define LL long long
int T;
int a[8],b[8];LL c[15][15];
LL work(LL x) {//循环节长度为x
	LL re=1,js=0;
	for(int i=1;i<=6;++i)
		if(!(a[i]%x)) b[i]=a[i]/x,js+=b[i];
		else return 0;
	for(int i=1;i<=6;++i) re*=c[js][b[i]],js-=b[i];
	return re;
}
LL rot_edge() {//单独处理通过两条对立棱的中心旋转的情况
	LL re=0;
	for(int i=1;i<=6;++i)//枚举在长度为1循环节里的两条边
		for(int j=1;j<=6;++j) 
		if(a[i]&&a[j]) --a[i],--a[j],re+=work(2),++a[i],++a[j];
	return 1LL*6*re;
}
void init() {
	for(int i=0;i<=12;++i) {
		c[i][0]=1;
		for(int j=1;j<=i;++j) c[i][j]=c[i-1][j-1]+c[i-1][j];
	}
}
int main() {
	scanf("%d",&T);init();
	while(T--) {
		for(int i=1;i<=6;++i) a[i]=0;
		for(int i=1;i<=12;++i) {int x;scanf("%d",&x),++a[x];}
		LL ans=work(1)+1LL*8*work(3)+1LL*3*work(2)+1LL*6*work(4)+rot_edge();
		printf("%lld\n",ans/(1LL*24));
	}
	return 0;
}

bzoj1478

题解戳我QWQ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值