UVA_10601
对于一个立方体,一共有24种本质不同的旋转,整体上分为四类:
①静止不动;
②以某面与对面的中心的连线为轴,沿一个方向旋转90度、180度、270度;
③以某棱与对棱的中心的连线为轴,沿一个方向旋转180度;
④以某个顶点与对顶点的连线为轴,沿一个方向旋转60度、120度。
对于每类都可以用组合数计算出不动方案的种数,然后应用一下burnside引理就可以得到最后的结果了。
#include<stdio.h> #include<string.h> int a[6], b[6], C[15][15]; void prepare() { int i, j; memset(C, 0, sizeof(C)); C[0][0] = 1; for(i = 1; i <= 12; i ++) { C[i][0] = C[i][i] = 1; for(j = 1; j < i; j ++) C[i][j] = C[i - 1][j] + C[i - 1][j - 1]; } } void init() { int i, k; memset(a, 0, sizeof(a)); for(i = 0; i < 12; i ++) { scanf("%d", &k); ++ a[k - 1]; } } long long calculate(int m) { int i, j, n = 0; long long ans = 1; for(i = 0; i < 6; i ++) { if(b[i] % m != 0) return 0; b[i] /= m; n += b[i]; } for(i = 0; i < 6; i ++) { ans *= C[n][b[i]]; n -= b[i]; } return ans; } long long fsolve() { long long ans = 0; memcpy(b, a, sizeof(a)); ans += calculate(1); memcpy(b, a, sizeof(a)); ans += 6 * calculate(4); memcpy(b, a, sizeof(a)); ans += 3 * calculate(2); return ans; } long long esolve() { int i, j; long long ans = 0; for(i = 0; i < 6; i ++) for(j = 0; j < 6; j ++) { memcpy(b, a, sizeof(a)); -- b[i], -- b[j]; if(b[i] < 0 || b[j] < 0) continue; ans += 6 * calculate(2); } return ans; } long long vsolve() { long long ans = 0; memcpy(b, a, sizeof(a)); ans = 8 * calculate(3); return ans; } void solve() { long long ans = 0; ans += fsolve(); ans += esolve(); ans += vsolve(); printf("%lld\n", ans / 24); } int main() { int t; prepare(); scanf("%d", &t); while(t --) { init(); solve(); } return 0; }