题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4633
典型的Polya定理:
思路:根据Burnside引理,等价类个数等于所有的置换群中的不动点的个数的平均值,根据Polya定理,不动点的个数等于Km(f),m(f)为置换f的循环节数,因此一次枚举魔方的24中置换,人肉数循环节数即可,注意细节,别数错了。
1、静止不动,(顶点8个循环,边12个循环,面54个循环)
2、通过两个对立的顶点,分别旋转120,240,有4组顶点,(点4个循环,边4个循环,面18个循环)x2(120和240度两种)x4(4组对角顶点)
3、通过两个对立面的中心,分别旋转90,180,270度。有3组面
在每次旋转90度和270度的时候(顶点2个循环节,边3个循环节,面15个循环节)x2(90和270两种角度)x3(三组对立面)
在每次旋转180度的时候(顶点4个循环节,边6个循环节,面28个循环节)x1(只有180度)x3(三组对里面)
4、通过两条对立的棱的中心,分别旋转180度,有6组棱(顶点4个循环节,边7个循环节,面27个循环节)×1(180度)×6(6组对立棱)
AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cstdlib> #include <cmath> #include <vector> #include <list> #include <deque> #include <queue> #include <iterator> #include <stack> #include <map> #include <set> #include <algorithm> #include <cctype> using namespace std; typedef long long LL; const int N=1; const int mod=10007; const int INF=0x3f3f3f3f; const double PI=acos(-1.0); int powmod(int a,int b) { int ans=1; while(b) { if(b&1) ans=(ans*a)%mod; a=(a*a)%mod; b>>=1; } return ans; } int main() { int i,j,t,k,ca=0; scanf("%d",&t); while(t--) { scanf("%d",&k); int xh=0; xh=(xh+powmod(k,74))%mod; xh=(xh+6*powmod(k,20))%mod; xh=(xh+3*powmod(k,38))%mod; xh=(xh+6*powmod(k,38))%mod; xh=(xh+8*powmod(k,26))%mod; xh=(xh*powmod(24,mod-2))%mod; printf("Case %d: %d ",++ca,xh); } return 0; } /* 本题模型共有4大类置换,共24种: 1. 不做任何旋转 K ^ (54 + 12 + 8) 2. 绕相对面中心的轴转 1) 90度 K ^ (15 + 3 + 2) * 3 1) 180度 K ^ (28 + 6 + 4) * 3 1) 270度 K ^ (15 + 3 + 2) * 3 3. 绕相对棱中心的轴转 1) 180度 K ^ (27 + 7 + 4) * 6 4. 绕相对顶点的轴转 1) 120度 K ^ (18 + 4 + 4) * 4 1) 240度 K ^ (18 + 4 + 4) * 4 */