用6种颜色去染正方体的12条棱,但是每种颜色都都限制了使用次数。
要确定正方体的每一条棱,可以先选择6个面之一作为顶面,然后剩下的四个面选一个作为前面,共有24种。
所以正方体的置换群共有24个置换。
具体每种置换的情况就是:UVA 10601 Cubes
幸运的是,任意一个置换中的循环节长度都是相同的(有一种置换除外),所以在计算每个置换的“不动点”的时候就方便了很多。
调了好久调不对样例,后来发现C[0][0]没有初始化为1,=_=||
1 #include <cstdio> 2 #include <vector> 3 #include <cstring> 4 #include <cassert> 5 using namespace std; 6 typedef long long LL; 7 8 int a[7], b[7]; 9 const int maxn = 12; 10 LL C[15][15]; 11 12 LL cal(int k)//k为循环节长度 13 { 14 LL ans = 1; 15 vector<int> t; 16 int num = 0; //num为循环节的个数 17 for(int i = 0; i < 6; i++) 18 { 19 if(a[i] % k == 0) { t.push_back(a[i]/k); num += a[i]/k; } 20 else return 0; 21 } 22 for(int i = 0; i < 6; i++) 23 { 24 ans *= C[num][t[i]]; 25 num -= t[i]; 26 } 27 return ans; 28 } 29 30 int main() 31 { 32 //freopen("in.txt", "r", stdin); 33 34 for(int i = 0; i <= maxn; i++) C[i][0] = C[i][i] = 1; 35 for(int i = 2; i <= maxn; i++) 36 for(int j = 1; j <= i; j++) 37 C[i][j] = C[i-1][j] + C[i-1][j-1]; 38 39 int T; 40 scanf("%d", &T); 41 while(T--) 42 { 43 memset(a, 0, sizeof(a)); 44 int x; 45 for(int i = 0; i < 12; i++) { scanf("%d", &x); a[x-1]++; } 46 LL ans = 0; 47 ans += cal(1); //原始排列 48 ans += 3 * cal(2); //以两个对面的中心为轴旋转180° 49 ans += 3 * 2 * cal(4); //以两个对面的中心为轴旋转90°或270° 50 ans += 4 * 2 * cal(3); //以两个对角顶点为中心旋转 51 for(int i = 0; i < 6; i++) 52 for(int j = 0; j < 6; j++) 53 {//以两个对棱中心连线为轴旋转180° 54 if(a[i] == 0 || a[j] == 0) continue; 55 a[i]--; a[j]--;//减去两个1循环 56 ans += 6 * cal(2); 57 a[i]++; a[j]++; 58 } 59 printf("%lld ", ans / 24); 60 } 61 62 return 0; 63 }