uva10601 - Cubes

链接

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 = &lt; { f 1 , f 2 , . . . , f k } , A=&lt;\{f_1,f_2,...,f_k\}, A=<{f1,f2,...,fk},函数合成 &gt; &gt; >
定义关系 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 gafi=gb,其中 f i ∈ A f_i\in A fiA,则 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 gf=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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值