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