题目:用k种颜色给一个魔方染色,可以染每个面的9个小矩形,12条棱,8个顶点(总之就是有74个能染的地方),空间旋转后一样的视为相同,问有多少种不同的染色方案。
思路:裸的polya计数,但是这个立方体的对称群本来就很容易弄错。。。《组合数学》里有个例题提到立方体的对称群有24个元素,分别是:
(1)恒等变换。
(2)以两个相对面的中心相连作为对称轴,旋转(i)90,(ii)180,(iii)270度,每种有3个。共9种。
(3)以两个相对棱的中点连线为对称轴翻转180度,有6种。
(4)固定两个相对顶点旋转(i)120,(ii)240度,共8种。
Burnside引理指出,在一个对称变换群作用下不同的染色数目等于每种变换作用下不动点个数的平均数。
但是此题直接求不动点恐怕只能写暴力程序跑了。。。polya定理实际上是Burnside引理稍微一般化了一下。polya定理提出了一种计算不动点数目的较为简便的方法,就是计算在每种映射下,映射中“环”的数目。这个可以通过列表比较清楚地得出。(polya定理还给出了更一般的通过母函数法求解限制每种颜色涂色的数目的方法,但是此题不需要)
那么我们可以得出下表:
面 棱 顶点
(2) (i) (iii) (2,0,0,13) (0,0,0,3) (0,0,0,2)
(2) (ii) (2,26,0,0) (0,6,0,0) (0,4,0,0)
(3) (0,27,0,0) (2,5,0,0) (0,4,0,0)
(4)(i)(ii) (0,0,18,0) (0,0,4,0) (2,0,2,0)
(列表方法见《组合数学》Brualdi)
然后就是一发公式交上去就能AC了
/* * @author: Cwind */ ///#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <queue> #include <stack> #include <functional> #include <set> #include <cmath> using namespace std; #define pb push_back #define PB pop_back #define bk back() #define fs first #define se second #define sq(x) (x)*(x) #define eps (1e-10) #define INF (1000000300) #define clr(x) memset((x),0,sizeof (x)) #define cp(a,b) memcpy((a),(b),sizeof (b)) typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> P; const ll mod=10007; ll qpow(ll a,ll p){ ll ans=1; while(p){ if(p&1) ans=ans*a%mod; a=a*a%mod; p>>=1; } return ans; } int T,K; int inv=qpow(24,mod-2); int cas; int main(){ freopen("/home/slyfc/CppFiles/in","r",stdin); cin>>T; while(T--){ scanf("%d",&K); ll ans=qpow(K,74)+6*qpow(K,20)+9*qpow(K,38)+8*qpow(K,26); ans%=mod; ans*=inv; ans%=mod; printf("Case %d: %lld\n",++cas,ans); } return 0; }