前言
求·······的方案数
循环同构算一种
一脸懵逼
(于是我觉得系统的学一遍Burnside引理和Polya定理)
正文
置换
置换的概念
对于一个排列
a
i
a_i
ai
我们想成
i
i
i输进去会出来一个
a
i
a_i
ai
那么我们如果输入一个排列,将能得到一个排列
就比如我们输入的排列是
1
1
1到
n
n
n有序的,那么这个置换就是
(
1
2
3
⋅
⋅
⋅
n
a
1
a
2
a
3
⋅
⋅
⋅
a
n
)
\begin{pmatrix} 1&2&3&···&n \\ a_1&a_2&a_3&···&a_n \end{pmatrix}
(1a12a23a3⋅⋅⋅⋅⋅⋅nan)
当然我们如果随便输入一个排列
b
i
b_i
bi,并且得到一个新的排列,那么这个置换就是
(
b
1
b
2
b
3
⋅
⋅
⋅
b
n
a
b
1
a
b
2
a
b
3
⋅
⋅
⋅
a
b
n
)
\begin{pmatrix} b_1&b_2&b_3&···&b_n \\ a_{b_1}&a_{b_2}&a_{b_3}&···&a_{b_n} \end{pmatrix}
(b1ab1b2ab2b3ab3⋅⋅⋅⋅⋅⋅bnabn)
只要排列
a
i
a_i
ai相同,无论输入什么排列
b
i
b_i
bi生成的置换都是一样的
即置换与横向位置无关,只与纵向的对应关系有关
我们设
A
=
{
a
1
,
a
2
⋅
⋅
⋅
a
n
}
A=\{a_1,a_2···a_n\}
A={a1,a2⋅⋅⋅an},即
∣
A
∣
=
n
|A|=n
∣A∣=n,我们称上面的那些置换为
A
A
A上的
n
n
n次置换
不难发现,本质不同的
n
n
n次置换一共有
n
!
n!
n!种
置换的乘积形式
我们发现,对于一个置换,一个位置的数如果是
i
i
i,进行若干次置换后,这个位置的数会变回
i
i
i
比如一个置换
(
1
2
3
4
5
6
2
3
1
6
5
4
)
\begin{pmatrix} 1&2&3&4&5&6 \\ 2&3&1&6&5&4 \end{pmatrix}
(122331465564)
一个数
1
1
1其变化是
1
→
2
→
3
→
1
1\rightarrow2\rightarrow3\rightarrow1
1→2→3→1
那么我们可以写成
(
2
,
3
,
1
)
(2,3,1)
(2,3,1)
所有的循环的乘积就是这个置换的不相交循环的乘积写法
比如刚刚这个置换就是
(
2
,
3
,
1
)
(
6
,
4
)
(
5
)
(2,3,1)(6,4)(5)
(2,3,1)(6,4)(5)
我们发现
5
5
5这个位置无论进行几次置换值都是
5
5
5,对于这些位置我们称其为不动点
置换群
是一种群,里面每个元素都是置换
然后满足群的一些性质
对于一个
n
n
n,在
n
!
n!
n!种本质不同的
n
n
n次置换中选
x
x
x个(
x
≥
1
x\ge1
x≥1)置换作为元素的群被称为
x
x
x阶
n
n
n次置换群,特殊的,当
x
=
n
!
x=n!
x=n!时,其被称为
n
n
n次对称群
对于一个
n
n
n次置换群,我们发现其元素中必有置换
(
a
1
a
2
a
3
⋅
⋅
⋅
a
n
a
1
a
2
a
3
⋅
⋅
⋅
a
n
)
\begin{pmatrix} a_1&a_2&a_3&···&a_n \\ a_1&a_2&a_3&···&a_n \end{pmatrix}
(a1a1a2a2a3a3⋅⋅⋅⋅⋅⋅anan)
另外,若其元素中有置换
(
b
1
b
2
b
3
⋅
⋅
⋅
b
n
a
b
1
a
b
2
a
b
3
⋅
⋅
⋅
a
b
n
)
\begin{pmatrix} b_1&b_2&b_3&···&b_n \\ a_{b_1}&a_{b_2}&a_{b_3}&···&a_{b_n} \end{pmatrix}
(b1ab1b2ab2b3ab3⋅⋅⋅⋅⋅⋅bnabn)
则其元素中也必有
(
a
b
1
a
b
2
a
b
3
⋅
⋅
⋅
a
b
n
b
1
b
2
b
3
⋅
⋅
⋅
b
n
)
\begin{pmatrix} a_{b_1}&a_{b_2}&a_{b_3}&···&a_{b_n} \\ b_1&b_2&b_3&···&b_n \end{pmatrix}
(ab1b1ab2b2ab3b3⋅⋅⋅⋅⋅⋅abnbn)
以上就差不多是一些定义了
百度百科链接,群
良好并且完整的置换群课件,链接
Burnside引理
设
G
=
{
a
1
,
a
2
,
…
a
g
}
G=\{a_1,a_2,…a_g\}
G={a1,a2,…ag}(
a
a
a是置换)是目标集
[
1
,
n
]
[1,n]
[1,n]上的置换群。每个置换都写成不相交循环的乘积。
c
1
(
a
k
)
c_1(a_k)
c1(ak)是在置换
a
k
a_k
ak的作用下不动点的个数,也就是长度为
1
1
1的循环的个数。通过上述置换的变换操作后可以相等的元素属于同一个等价类。若
G
G
G将
[
1
,
n
]
[1,n]
[1,n]划分成
l
l
l个等价类,则:
l
=
1
∣
G
∣
[
c
1
(
a
1
)
+
c
1
(
a
2
)
+
⋅
⋅
⋅
+
c
1
(
a
∣
G
∣
)
]
l=\frac{1}{|G|}[c_1(a_1)+c_1(a_2)+···+c_1(a_{|G|})]
l=∣G∣1[c1(a1)+c1(a2)+⋅⋅⋅+c1(a∣G∣)]
证明:
对于一个置换
a
a
a,将其写成不相交循环的乘积
我们设
χ
a
(
x
)
=
{
0
x
不
是
不
动
点
1
x
是
不
动
点
\chi_a(x)=\begin{cases}0&x不是不动点\\1&x是不动点\end{cases}
χa(x)={01x不是不动点x是不动点
根据定义,我们展开
∑
a
i
∈
G
c
1
(
a
i
)
=
∑
a
i
∈
G
∑
1
≤
j
≤
n
χ
a
i
(
j
)
=
∑
1
≤
j
≤
n
∑
a
i
∈
G
χ
a
i
(
j
)
\sum_{a_i\in G}c_1(a_i)=\sum_{a_i\in G}\sum_{1\le j\le n}\chi_{a_i}(j)=\sum_{1\le j\le n}\sum_{a_i\in G}\chi_{a_i}(j)
ai∈G∑c1(ai)=ai∈G∑1≤j≤n∑χai(j)=1≤j≤n∑ai∈G∑χai(j)
我们设
Z
(
x
)
\Zeta(x)
Z(x)为满足
x
x
x是不动点的置换集合,我们发现上式的后半部分可以直接套入
∑
1
≤
j
≤
n
∑
a
i
∈
G
χ
a
i
(
j
)
=
∑
1
≤
j
≤
n
∣
Z
(
j
)
∣
\sum_{1\le j\le n}\sum_{a_i\in G}\chi_{a_i}(j)=\sum_{1\le j\le n}|\Zeta(j)|
1≤j≤n∑ai∈G∑χai(j)=1≤j≤n∑∣Z(j)∣
我们发现,对于同一个等价类里的元素
x
1
,
x
2
x_1,x_2
x1,x2,一定满足
Z
(
x
1
)
=
Z
(
x
2
)
Z(x_1)=Z(x_2)
Z(x1)=Z(x2),原因是
Z
(
x
)
Z(x)
Z(x)集合是一个置换群元素集合的子集
这样我们设
C
C
C为一个等价类元素集合,设
c
=
∀
x
∈
C
c=\forall x\in C
c=∀x∈C,那么无论
c
c
c的取值,
Z
(
c
)
Z(c)
Z(c)的值都是一样的
那么继续上式
∑
1
≤
j
≤
n
∣
Z
(
j
)
∣
=
∑
C
∣
C
∣
∗
Z
(
c
)
=
∣
G
∣
∑
C
1
=
∣
G
∣
⋅
∣
C
∣
=
∣
G
∣
l
\sum_{1\le j\le n}|\Zeta(j)|=\sum_{C}|C|*Z(c)=|G|\sum_{C}1=|G|·|C|=|G|l
1≤j≤n∑∣Z(j)∣=C∑∣C∣∗Z(c)=∣G∣C∑1=∣G∣⋅∣C∣=∣G∣l
对于第二个等号,可能你会感到疑惑
这里用到了
∣
C
∣
∗
Z
(
c
)
=
∣
G
∣
|C|*\Zeta(c)=|G|
∣C∣∗Z(c)=∣G∣,即“轨道-稳定集定理”,这里就不展开了,因为这个的证明还需要拉格朗日定理等群论基本知识,有兴趣的可以看这篇博客,里面有一些基本概念的介绍,另外,据说具体证明可以参照 《组合数学》(第5版)P181 定理4-11(暂未考证)
综上
l
=
1
∣
G
∣
∑
a
i
∈
G
c
1
(
a
i
)
l=\frac{1}{|G|}\sum_{a_i\in G}c_1(a_i)
l=∣G∣1ai∈G∑c1(ai)
这篇博客里有比较清楚的例子,我这里就不举例了
我们发现,在染色问题循环同构的题中,
∣
G
∣
|G|
∣G∣是旋转方式数,
∣
A
∣
|A|
∣A∣是所有染色种类数,算法的复杂度是
O
(
∣
G
∣
∣
A
∣
)
\mathcal O(|G||A|)
O(∣G∣∣A∣)的,而后者很容易变得很大,这个时候就需要用到Polya定理
(也正因为如此在OI中应用不多)
Polya定理
前提条件:如果将
[
1
,
n
]
[1,n]
[1,n]用
k
k
k种颜色进行染色
我们定义
λ
(
a
i
)
\lambda(a_i)
λ(ai)为置换
a
i
a_i
ai的循环数量
Polya定理:
l
=
1
∣
G
∣
∑
a
i
∈
G
k
λ
(
a
i
)
l=\frac{1}{|G|}\sum_{a_i\in G}k^{\lambda(a_i)}
l=∣G∣1ai∈G∑kλ(ai)
Polya定理其实就是一种Burnside引理的具体化,就是把上面的
c
1
(
a
i
)
c_1(a_i)
c1(ai)算出来了
例题
[poj1286]Necklace of Beads
题目大意:现在有
3
3
3种颜色的珠子,问有多少种长度为
n
n
n的环,旋转、轴对称同构算一种
题解: 我们发现对于一个
n
n
n的置换只有
2
∗
n
2*n
2∗n种,直接套polya定理求环数量即可,复杂度
O
(
n
2
)
\mathcal O(n^2)
O(n2)
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
typedef long long ll;
#define rg register
template <typename T> inline void read(T&x){char cu=getchar();x=0;bool fla=0;while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}while(isdigit(cu))x=x*10+cu-'0',cu=getchar();if(fla)x=-x;}
template <typename T> inline void printe(const T x){if(x>=10)printe(x/10);putchar(x%10+'0');}
template <typename T> inline void print(const T x){if(x<0)putchar('-'),printe(-x);else printe(x);}
ll n,ans[24];
int a[24];
bool vis[24];
ll pow(ll x,ll y)
{
ll res=1;
for(;y;y>>=1,x=x*x)if(y&1)res*=x;
return res;
}
void dfs(const int x)
{
if(vis[x])return;
vis[x]=1;
dfs(a[x]);
}
void calc()
{
memset(vis,0,sizeof(vis));
int k=0;
for(rg int i=0;i<n;i++)
if(!vis[i])
dfs(i),k++;
ans[n]+=pow(3,k);
}
int main()
{
for(n=1;n<24;n++)
{
for(rg int i=0;i<n;i++)
{
for(rg int j=0;j<n;j++)a[j]=(i+j)%n;
calc();
for(rg int j=0;j<n-j-1;j++)std::swap(a[j],a[n-j-1]);
calc();
}
ans[n]/=2*n;
}
while(1)
{
read(n);
if(n==-1)break;
print(ans[n]),putchar('\n');
}
return 0;
}