群论小记
command_block · · 个人记录
1.群的概念与基本性质
-
存在单位元 : 存在一个
e\in G ,使得对于任意的a\in G ,满足a*e=e*a=a 。元素
e 则被称作单位元。 -
存在逆元 : 对于任意的
a\in G ,存在一个b\in G ,满足a*b=b*a=e 。元素
b 可以记作a^{-1} 。
则称
有时把
设有两个不同的单位元
-
\color{blue}\text{定理 1.2}:$ $ab=ac\Rightarrow b=c,\ ba=ca\Rightarrow b=c
证左部,右部同理。
若
则有
若只希望了解置换计数,可以到此为止。
-
\color{blue}\text{定理 1.4}:$ 对于任意的(有限)群 $G=\{e,a_1,a_2...a_n\} 对于任意的
a\in G 都存在一个常数{\rm ord}(a) ,使得a^{{\rm ord}(a)}=e 。此时称{\rm ord}(a) 为a 的阶。且有
a^{-1}=a^{{\rm ord}(a)-1} 。
任取
由于封闭性,这
不妨设
令
2. 置换与置换群
- 置换的定义
假设有
满足各个
写作置换 :
如
这个置换就代表着:
- 把
1 移到第3 个 - 把
2 移到第1 个 - 把
3 移到第4 个 - 把
4 移到第2 个
又作:
- 置换乘法
置换的乘法就是把映射叠加。
设
则
所以有
也可以这样写 :
容易证明如下的几条基本性质 :
-
置换的乘积还是置换。
-
置换乘法满足结合律。
-
单位元为
\begin{pmatrix}1&2&3&...&n\\1&2&3&...&n\\\end{pmatrix} -
\begin{pmatrix}1&2&...&n\\a_1&a_2&...&a_n\end{pmatrix}$ 的逆为 $\begin{pmatrix}a_1&a_2&...&a_n\\1&2&...&n\end{pmatrix}
但注意,置换乘法一般不满足交换律。
- 置换群
根据上面的若干性质,不难证明对
总是研究全体置换,未免乏味,我们一般只研究一个子群。
有如下事实 : 对于任意一个
解释一下同构是什么意思,想想一个二分图,左侧的点用对子
若这两个图同构,则称两个群同构。(其实就是把所有的运算结果打了个表)
现在我们就是要证明置换群能够造出任意的图来。
对于
这些乘积必然两两不同。假设有
我们设
令
则有
注意到,前面的“二分图”有
- 置换的循环
把置换看做一张有向图, 连边
的循环是
的循环是
的循环是
置换可以用这些环来表示,而且表示方法是唯一的。
由于比双层写法更简洁,下面有时会以循环的方式写出置换。
2. Burnside / Polya
设
- 不动点
对于
将
对于
记作
- 等价类
等价类
如
那么
根据等价类的定义,对于每个
设置换集合
由于
能够发现
那么有
另一方面,对于任意的
那么有
所以,
综上可得
则有
回忆
又因为
于是就有
- Polya定理
以问题引入 : 给出一条长度为
若将每种染色方案视为一个元素,令
问题在于,置换的大小是
能够发现,“翻转”同样是对
若能把对“位置”的小置换群,和对“状态”的大置换群联系起来,就能更方便地计算了。
-
设 $G$ 是 $n$ 个元素的置换群,则染色总方案数为 : $$\dfrac{1}{|G|}\sum\limits_{p\in G}T(p)$$ 其中 $T(p)$ 指在置换 $p$ 下,不动的染色方案数。 - 比如 $\begin{pmatrix}1&2&3&4\\2&1&4&3\\\end{pmatrix}$。 那么染成 $\{a,a,b,b\}$ ,置换完了之后还是 $\{a,a,b,b\}$ ,则称之为不动的染色方案 染成 $\{a,b,c,d\}$ 置换完了之后是 $\{b,a,d,c\}$ ,和原来不相等,则不是“不动方案”。 -
\color{blue}\text{证明}: 设
G' 是对状态的置换群。不难发现大置换和小置换有对应关系,使用小置换对每种状态讨论即可得到大置换。形式化的讲,设
p\in G 对应p'\in G' 。若一种染色方案
a 在经过p 的“移动”之后,变为了b ,则a\xrightarrow{p'}b 。所以有
|G|=|G'| 。根据经典的Burnside引理,可以得到答案为
\dfrac{1}{|G'|}\sum\limits_{p'\in G'}c(p') 而
c(p') 的意义正是G 中相对应的置换p 下不动的染色方案数,证毕。 -
接下来介绍如何求
T(p) 。设
d(p) 为p 的循环个数,则(根据等式的传递性)每个循环中必须染上同一种颜色,且不同循环之间没有影响。能得到
T(p)=m^{d(p)} 。
回到题目,
后者有循环节
前者有循环节
总方案数是
3. 习题
- P4980 【模板】Polya定理
这道题里的置换就是旋转。
有旋转
设
Polya式子 :
暴力 : 根据上文介绍的方法,对每个置换缩点求循环个数
打表或者拿出草稿纸画了一通后,你会发现
-
若每次跳 $i$ 步,在长度为 $n$ 的环上,多少次才能回到原点呢? 当 $i\perp n$ 时,可以证明 $0,i,2i,3i...(n-1)i$ 在$\pmod n$ 意义下互不相同。 此时的答案就是 $n$。 若 $i\not\perp n$ ,采用模分类,设 $d=\gcd(i,n)$ ,若从 $0$ 开始,不难发现 $d\!\!\not|\ i$ 的位置都是无用的。 这就变成了子问题 $\frac{n}{d},\frac{i}{d}$ ,此时两者互质,答案就是 $\frac{n}{d}$。
得
相信已近在学习群论的你,一定能把这道数论水题秒掉的。
-
后面的
\sum\limits_{i=1}^n[\gcd(n,i)=d] =\sum\limits_{i=1}^{n/d}[n\perp i]=\varphi(n/d)
整理得
大力求欧拉函数大概是
然而还有一个质因数分解+dfs凑出所有因数+光速幂的
Code:
#include<algorithm>
#include<cstdio>
#define ll long long
using namespace std;
const int mod=1000000007;
ll powM(ll a,int t){
ll ret=1;
while(t){
if (t&1)ret=ret*a%mod;
a=a*a%mod;t>>=1;
}return ret;
}
int phi(int n)
{
int ans=n;
for (int i=2;i*i<=n;i++)
if (n%i==0){
ans=ans/i*(i-1);
while(n%i==0)n/=i;
}
if (n>1)ans=ans/n*(n-1);
return ans;
}
void solve(int n)
{
ll ans=0;
for (int i=1;i*i<=n;i++)
if (n%i==0){
if (i*i!=n)ans=(ans+powM(n,n/i-1)*phi(i))%mod;
ans=(ans+powM(n,i-1)*phi(n/i))%mod;
}
printf("%lld\n",ans);
}
int T,n;
int main()
{
scanf("%d",&T);
while(T--){
scanf("%d",&n);
solve(n);
}return 0;
}
- P4727 [HNOI2009]图的同构记数
第一眼这道题以为是子集
今早闲得无聊拿着《组合数学(第4版)》看了看,里面居然有讲到这个问题。
边 (有,无) 的状态可以看做对一个完全图染色,某条边染成黑色说明存在,染成白色就假装不存在,我们成功地把这个问题转化成了一个染色计数问题。
我们先看看式子 :
我们现在是在对边计数,但是我们的置换是所有的点置换。
显然,可以由点置换构造出边置换,但是点置换的个数是
万幸的是, 点置换循环节的构成 和 边置换的不动点个数 有一定的关系。
考虑一个点置换,他每个循环的大小为
能够感知,所有循环节组成相同的点置换,边的等价类个数是相同的。
也就是说我们只要枚举
而正整数拆分的数量级是
现在,对于一组
-
对于循环节内的边,会被分为
\left\lfloor\dfrac{S}{2}\right\rfloor 个等价类。理解 : 我们可以把这个循环节看成一个圈,由于这个圈会转,肯定会让某些边相同。
循环内节点按
1...S 编号,假设有边(1,p) ,那么边(2,p+1) ,(3,p+2) ……和(S-p+1,S) 肯定都和(1,p) 相同。我们枚举p,会发现
p>\left\lfloor\dfrac{S}{2}\right\rfloor 的情况会和p\leq \left\lfloor\dfrac{S}{2}\right\rfloor 的情况重复。如图 : 左边
S=8 ,等价类数为\left\lfloor\dfrac{8}{2}\right\rfloor=4 ;\quad 右边S=7 ,等价类数为\left\lfloor\dfrac{7}{2}\right\rfloor=3 。 -
对于两个循环节之间的边,会被分为
gcd(S_1,S_2) 个等价类。理解 : 我们还是采用圈来理解,由于这个两个圈都会转,情况有点复杂。
循环内节点按
1...S_1 与1...S_2 编号,假设有边(x,y) ,那么有多少条边和这条边相同呢?这等价于考虑 : 这条边会在多少次置换后回到原位 ?
答案是
lcm(S_1,S_2) ,如果不理解的话,想象着两个齿轮咬合着转。那么每个等价类的边得个数为
lcm(S_1,S_2) ,边的总数为nm ,则等价类的总数是\dfrac{nm}{lcm(S_1,S_2)}=gcd(S_1,S_2)
如图 : 左边
第一个等价类的边
第二个等价类的边
那么根据上述,对于循环节大小为
我们接下来还要算循环节大小为
我们考虑把
我们考虑生成一个长为
得
如果有两个
设
我们还要在每个集合内连边,使得它构成一个循环。
然后在乘上对应的边置换的贡献,得到
别忘了除以置换个数
最后注意实现复杂度和常数,小心被卡。
Code:
#include<cstdio>
using namespace std;
const int mod=997;
int n;
int powM(int a,int t=mod-2){
int ret=1;
while(t){
if (t&1)ret=ret*a%mod;
a=a*a%mod;t>>=1;
}return ret;
}
int facn,inv[66],ifac[66],gcd[66][66],
s[66],b[66],ans;
void dfs(int num,int pos,int last)
{
if (num==0){
int t=0,sav=facn;
for (int i=1;i<=n;i++)b[i]=0;
for (int i=1;i<pos;i++)b[s[i]]++;
for (int i=1;i<=n;i++)sav=sav*ifac[b[i]]%mod;
for (int i=1;i<pos;i++)sav=sav*inv[s[i]]%mod;
for (int i=1;i<pos;i++)
for (int j=i+1;j<pos;j++)
t+=gcd[s[i]][s[j]];
for (int i=1;i<=n;i++)t+=s[i]/2;
sav=sav*powM(2,t)%mod;
ans=(ans+sav)%mod;
return ;
}if (last>num)last=num;
for (int i=1;i<=last;i++){
s[pos]=i;
dfs(num-i,pos+1,i);
}
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)inv[i]=powM(i);
ifac[0]=1;
for (int i=1;i<=n;i++)
ifac[i]=ifac[i-1]*inv[i]%mod;
facn=powM(ifac[n]);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
for (int k=1;k<=n;k++)
if (i%k==0&&j%k==0)gcd[i][j]=k;
dfs(n,1,n);
printf("%d",ans*ifac[n]%mod);
return 0;
}
类似的题目 : P4128 [SHOI2006]有色图
- 题解 P4916 【魔力环】