【置换群&Polya定理的扩展】Cubes UVA - 10601

题意:用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
不动置换: ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) ( 6 ) ( 7 ) ( 8 ) ( 9 ) ( 10 ) ( 11 ) ( 12 )
绕x-x’轴旋转: ( 1 2 3 4 ) ( 5 6 7 8 ) ( 9 10 11 12 )
( 4 3 2 1 ) ( 8 7 6 5 ) ( 12 11 10 9 )
( 1 3 ) ( 2 4 ) ( 5 7 ) ( 6 8 ) ( 9 11 ) ( 10 12 )
选取x-x’的方式有三种,所以以上置换形式的数目要乘三。
绕y-y’轴旋转: ( 6 ) ( 8 ) ( 1 12 ) ( 2 11 ) ( 3 10 ) ( 4 9 ) ( 5 7 )
选取y-y’的方式有六种,所以以上置换形式的数目要乘六。
绕z-z’轴旋转: ( 1 6 12 ) ( 2 11 8 ) ( 3 7 4 ) ( 5 10 9 )
( 12 6 1 ) ( 8 11 2 ) ( 4 7 3 ) ( 9 10 5 )
选取z-z’的方式有四种,所以以上置换形式的数目要乘四。
对应的多项式 P :
不动置换: P 1 = 1 ( x 1 + x 2 + . . . + x 6 ) 12
绕x-x’轴旋转: P 2 = 3 2 ( x 1 4 + x 2 4 + . . . + x 6 4 ) 3
P 3 = 3 ( x 1 2 + x 2 2 + . . . + x 6 2 ) 6
绕y-y’轴旋转: P 4 = 6 ( x 1 + x 2 + . . . + x 6 ) 2 ( x 1 2 + x 2 2 + . . . + x 6 2 ) 5
绕z-z’轴旋转: 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
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);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41343943/article/details/82499532