这个题目跟UVA 项链的题目是一样的,同样适用Burnside定理计数,3*3*3魔方旋转是一个经典旋转模型,有4种旋转方案,对着魔方转一下最好
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define LL long long int T,ct[7]; LL C[20][20]; void init(){ C[0][0] = C[1][0] = C[1][1] = 1; for(int i=2;i<20;i++){ C[i][0] = 1; for(int j=1;j<20;j++){ C[i][j] = C[i-1][j]+C[i-1][j-1]; } } } LL Stop(){ ///静止不动 LL res = 1; int ha = 12; for(int i=1;i<=6;i++){ res = res*C[ha][ct[i]]; ha -= ct[i]; } return res; } LL Ops_Point(){ ///通过两个对立的顶点,分别旋转120,240,有4组顶点 int bct[7]; memcpy(bct,ct,sizeof(ct)); for(int i=1;i<=6;i++){ if(bct[i]%3 != 0) return 0; bct[i] /= 3; } int ha = 4; LL res = 1; for(int i=1;i<=6;i++){ res = res*C[ha][bct[i]]; ha -= bct[i]; } return 8*res; } LL Ops_Line(){ ///通过两条对立的棱的中心,分别旋转180度,有6组棱 int bct[7]; LL res = 0; for(int i=1;i<=6;i++){ for(int j=i;j<=6;j++){ memcpy(bct,ct,sizeof(ct)); bct[i]--; bct[j]--; if(bct[i]<0||bct[j]<0) continue; bool ok = true; for(int k=1;k<=6;k++){ if(bct[k]%2!=0){ ok = false; break; } bct[k]>>=1; } if(ok == false) continue; int all = 5; LL tmp = 1; for(int k=1;k<=6;k++){ tmp *= C[all][bct[k]]; all -= bct[k]; } if(i == j) res += tmp; else res += (tmp<<1); } } res = res*6; // printf("rot_edge = %lld\n",res); return res; } LL Ops_Face(){///通过两个对立面的中心,分别旋转90,180,270度,有三组 int bct[7]; memcpy(bct,ct,sizeof(ct)); LL res = 0; int ha; bool f = true; for(int i=1;i<=6;i++){ if(bct[i]%4!=0) {f = false; break;} bct[i] /= 4; } if(f == true){ ha = 3; LL tmp = 1; ///旋转90度和270度的时候 for(int i=1;i<=6;i++){ tmp = tmp*C[ha][bct[i]]; ha -= bct[i]; } res = res + (tmp<<1); } memcpy(bct,ct,sizeof(ct)); f = true; for(int i=1;i<=6;i++){ if(bct[i]%2!=0) {f = false; break;} bct[i] /= 2; } if(f == true){ ha = 6; LL tmp = 1; for(int i=1;i<=6;i++){ ///旋转180度的时候 tmp = tmp*C[ha][bct[i]]; ha -= bct[i]; } res = res+tmp; } return 3*res; } int main(){ init(); scanf("%d",&T); while(T--){ memset(ct,0,sizeof(ct)); for(int i=1;i<=12;i++){ int x; scanf("%d",&x); ct[x]++; } LL ans=0; ans = ans + Stop(); ans = ans + Ops_Point(); ans = ans + Ops_Line(); ans = ans + Ops_Face(); // printf("ans1 = %lld\n",ans); ans /= 24; printf("%lld\n",ans); } return 0; }