【置换群&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 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 :
不动置换:P1=1(x1+x2+...+x6)12
绕x-x’轴旋转: P2=32(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=42(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)36!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);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值