链接
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1542
Burnside计数定理
我想用离散数学的语言重新描述一下这个定理:
首先你有一个有限集合XXX,fff是这个集合上的置换,ggg是XXX到XXX的函数
定义一个置换群A=<{f1,f2,...,fk},A=<\{f_1,f_2,...,f_k\},A=<{f1,f2,...,fk},函数合成>>>
定义关系RRR,对于两个函数ga,gbg_a,g_bga,gb,如果ga∘fi=gbg_a\circ f_i=g_bga∘fi=gb,其中fi∈Af_i\in Afi∈A,则faRfbf_aRf_bfaRfb
不难证明RRR的自反性、传递性、对称性,因此RRR是等价关系
不动点:对于置换群中的一个置换fif_ifi,如果一个函数ggg满足g∘f=gg\circ f=gg∘f=g,就称ggg是fff的不动点
BurnsideBurnsideBurnside计数定理指出,对于一个集合S={g1,g2,...,gn}S=\{g_1,g_2,...,g_n\}S={g1,g2,...,gn},以RRR诱导出的等价关系来划分SSS,得到的等价类的数目是置换群中每个置换的不动点的个数的平均数
题解
正方体旋转这种冷门知识谁会知道啊qwq
先来构造置换群:
- 不动置换,这个置换被拆成121212个环,每个环的大小为111
- 以对面中心连线为轴旋转90∘90^\circ90∘或270∘270^\circ270∘,这个置换被拆成333个环,大小都为444
- 以对面中心连线为轴旋转180∘180^\circ180∘,这个置换被拆成666个环,大小都为222
- 以对棱为的重点连线为轴旋转180∘180^\circ180∘,这个置换被拆成777个环,大小分别为1,1,2,2,2,2,21,1,2,2,2,2,21,1,2,2,2,2,2
- 以体对角线为为轴旋转120∘120^\circ120∘或240∘240^\circ240∘,这个置换被拆成444个环,每个大小为333
每个环内所有点的颜色都得是一样的
写一个爆搜计数就好了
代码
//等价类计数
#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;
}