题意:用12根木条搭建正方体,给出每根木条颜色,木条颜色编号1~6,求能搭建不同的正方体的数量。两个正方体视为不同当且仅当不能在旋转翻转等操作后重合。
样例:
3
1 2 2 2 2 2 2 2 2 2 2 2
1 1 2 2 2 2 2 2 2 2 2 2
1 1 2 2 3 3 4 4 5 5 6 6
输出:
1
5
312120
分析:
置换群
G,|G|=24
G
,
|
G
|
=
24
。
不动置换:
(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)(12)
(
1
)
(
2
)
(
3
)
(
4
)
(
5
)
(
6
)
(
7
)
(
8
)
(
9
)
(
10
)
(
11
)
(
12
)
绕x-x’轴旋转:
(1234)(5678)(9101112)
(
1
2
3
4
)
(
5
6
7
8
)
(
9
10
11
12
)
(4321)(8765)(1211109)
(
4
3
2
1
)
(
8
7
6
5
)
(
12
11
10
9
)
(13)(24)(57)(68)(911)(1012)
(
1
3
)
(
2
4
)
(
5
7
)
(
6
8
)
(
9
11
)
(
10
12
)
选取x-x’的方式有三种,所以以上置换形式的数目要乘三。
绕y-y’轴旋转:
(6)(8)(112)(211)(310)(49)(57)
(
6
)
(
8
)
(
1
12
)
(
2
11
)
(
3
10
)
(
4
9
)
(
5
7
)
选取y-y’的方式有六种,所以以上置换形式的数目要乘六。
绕z-z’轴旋转:
(1612)(2118)(374)(5109)
(
1
6
12
)
(
2
11
8
)
(
3
7
4
)
(
5
10
9
)
(1261)(8112)(473)(9105)
(
12
6
1
)
(
8
11
2
)
(
4
7
3
)
(
9
10
5
)
选取z-z’的方式有四种,所以以上置换形式的数目要乘四。
对应的多项式
P
P
:
不动置换:
绕x-x’轴旋转:
P2=3∗2∗(x41+x42+...+x46)3
P
2
=
3
∗
2
∗
(
x
1
4
+
x
2
4
+
.
.
.
+
x
6
4
)
3
P3=3∗(x21+x22+...+x26)6
P
3
=
3
∗
(
x
1
2
+
x
2
2
+
.
.
.
+
x
6
2
)
6
绕y-y’轴旋转:
P4=6∗(x1+x2+...+x6)2(x21+x22+...+x26)5
P
4
=
6
∗
(
x
1
+
x
2
+
.
.
.
+
x
6
)
2
(
x
1
2
+
x
2
2
+
.
.
.
+
x
6
2
)
5
绕z-z’轴旋转:
P5=4∗2∗(x31+x32+...+x36)4
P
5
=
4
∗
2
∗
(
x
1
3
+
x
2
3
+
.
.
.
+
x
6
3
)
4
对于第二个样例:1 1 2 2 2 2 2 2 2 2 2 2
ans=1|G|∗项x21x102的系数和=124∗[(P1中)12!2!10!+(P3中)3∗6!1!5!+(P4中)6∗(5!5!+5!1!4!∗2!2!)]=5.
a
n
s
=
1
|
G
|
∗
项
x
1
2
x
2
10
的
系
数
和
=
1
24
∗
[
(
P
1
中
)
12
!
2
!
10
!
+
(
P
3
中
)
3
∗
6
!
1
!
5
!
+
(
P
4
中
)
6
∗
(
5
!
5
!
+
5
!
1
!
4
!
∗
2
!
2
!
)
]
=
5.
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 13
#define LL long long
LL fac[MAXN];
int c[MAXN],n[4]={12,3,4,6},m[4]={1,4,3,2},a[4]={1,6,8,3};
int main()
{
fac[0]=1;
for(int i=1;i<MAXN;i++)
fac[i]=fac[i-1]*i;
int tm,x;
scanf("%d",&tm);
while(tm--)
{
for(int i=1;i<=6;i++) c[i]=0;
for(int i=1;i<=12;i++)
{
scanf("%d",&x);
c[x]++;
}
LL ans=0;
for(int i=0;i<4;i++)
{
LL tmp=fac[n[i]];
for(int j=1;j<=6;j++)
if(c[j]%m[i]==0)
tmp/=fac[c[j]/m[i]];
else
{
tmp=0;
break;
}
ans+=a[i]*tmp;
}
for(int i=1;i<=6;i++)
{
if(c[i]==0) continue;
for(int j=i;j<=6;j++)
{
if(c[j]==0) continue;
if(i==j&&c[j]<2) continue;
c[i]--,c[j]--;
LL tmp=fac[6]*(1+(i!=j));
for(int k=1;k<=6;k++)
if(c[k]%2==0)
tmp/=fac[c[k]/2];
else
{
tmp=0;
break;
}
c[i]++,c[j]++;
ans+=tmp;
}
}
printf("%lld\n",ans/24);
}
}