链接
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1542
Burnside计数定理
我想用离散数学的语言重新描述一下这个定理:
首先你有一个有限集合
X
X
X,
f
f
f是这个集合上的置换,
g
g
g是
X
X
X到
X
X
X的函数
定义一个置换群
A
=
<
{
f
1
,
f
2
,
.
.
.
,
f
k
}
,
A=<\{f_1,f_2,...,f_k\},
A=<{f1,f2,...,fk},函数合成
>
>
>
定义关系
R
R
R,对于两个函数
g
a
,
g
b
g_a,g_b
ga,gb,如果
g
a
∘
f
i
=
g
b
g_a\circ f_i=g_b
ga∘fi=gb,其中
f
i
∈
A
f_i\in A
fi∈A,则
f
a
R
f
b
f_aRf_b
faRfb
不难证明
R
R
R的自反性、传递性、对称性,因此
R
R
R是等价关系
不动点:对于置换群中的一个置换
f
i
f_i
fi,如果一个函数
g
g
g满足
g
∘
f
=
g
g\circ f=g
g∘f=g,就称
g
g
g是
f
f
f的不动点
B
u
r
n
s
i
d
e
Burnside
Burnside计数定理指出,对于一个集合
S
=
{
g
1
,
g
2
,
.
.
.
,
g
n
}
S=\{g_1,g_2,...,g_n\}
S={g1,g2,...,gn},以
R
R
R诱导出的等价关系来划分
S
S
S,得到的等价类的数目是置换群中每个置换的不动点的个数的平均数
题解
正方体旋转这种冷门知识谁会知道啊qwq
先来构造置换群:
- 不动置换,这个置换被拆成 12 12 12个环,每个环的大小为 1 1 1
- 以对面中心连线为轴旋转 9 0 ∘ 90^\circ 90∘或 27 0 ∘ 270^\circ 270∘,这个置换被拆成 3 3 3个环,大小都为 4 4 4
- 以对面中心连线为轴旋转 18 0 ∘ 180^\circ 180∘,这个置换被拆成 6 6 6个环,大小都为 2 2 2
- 以对棱为的重点连线为轴旋转 18 0 ∘ 180^\circ 180∘,这个置换被拆成 7 7 7个环,大小分别为 1 , 1 , 2 , 2 , 2 , 2 , 2 1,1,2,2,2,2,2 1,1,2,2,2,2,2
- 以体对角线为为轴旋转 12 0 ∘ 120^\circ 120∘或 24 0 ∘ 240^\circ 240∘,这个置换被拆成 4 4 4个环,每个大小为 3 3 3
每个环内所有点的颜色都得是一样的
写一个爆搜计数就好了
代码
//等价类计数
#include <bits/stdc++.h>
#define maxn 110
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
int cnt, res[maxn], need[maxn];
int read(int x=0)
{
int c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return f*x;
}
void dfs(int pos)
{
int i;
if(pos>need[0])
{
cnt++;
return;
}
for(i=1;i<=6;i++)
{
if(res[i]>=need[pos])
{
res[i]-=need[pos];
dfs(pos+1);
res[i]+=need[pos];
}
}
}
int main()
{
int i, T=read(), ans;
while(T--)
{
cl(res);
for(i=1;i<=12;i++)res[read()]++;
ans=0;
cnt=0;
need[0]=12;
for(i=1;i<=12;i++)need[i]=1;
dfs(1);
ans+=cnt;
cnt=0;
need[0]=3;
for(i=1;i<=3;i++)need[i]=4;
dfs(1);
ans+=cnt*6;
cnt=0;
need[0]=6;
for(i=1;i<=6;i++)need[i]=2;
dfs(1);
ans+=cnt*3;
cnt=0;
need[0]=7;
need[1]=need[2]=1;
need[3]=need[4]=need[5]=need[6]=need[7]=2;
dfs(1);
ans+=cnt*6;
cnt=0;
need[0]=4;
for(i=1;i<=4;i++)need[i]=3;
dfs(1);
ans+=cnt*8;
printf("%d\n",ans/24);
}
return 0;
}