题意:
有6种颜色,现在给出各个颜色的个数,要在正方体上染色,有几种染法。
题解:
这题因为颜色种类的个数给出了,只能用burnside引理来做。对于每种置换计算等价的个数。
总共有四种变换
1、自身不变。循环节12个,长度1
2、根据定点连线为轴旋转120度、240度。循环节4个,长度3
3、根据对面的中心连线为轴旋转90、180、270度。90、270循环节个数3,长度4。180循环节个数6,长度2
4、根据对边的中心连线为轴旋转180度。循环节个数7个,5个长度2,2个长度1,这里要暴力枚举长度为1的循环节涂什么颜色。
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<queue> #include<map> #include<set> #define B(x) (1<<(x)) using namespace std; typedef long long ll; void cmax(int& a,int b){ if(b>a)a=b; } void cmin(int& a,int b){ if(b<a)a=b; } void cmax(ll& a,ll b){ if(b>a)a=b; } void cmin(ll& a,ll b){ if(b<a)a=b; } void add(int& a,int b,int mod){ a=(a+b)%mod; } void add(ll& a,ll b,ll mod){ a=(a+b)%mod; } const int oo=0x3f3f3f3f; const ll MOD=1000000007; int C[15][15]; int a[15],b[15]; void Init(){ for(int i=0;i<15;i++){ C[i][0]=C[i][i]=1; for(int j=1;j<i;j++) C[i][j]=C[i-1][j-1]+C[i-1][j]; } } ll Count(int k){ memcpy(b,a,sizeof a); for(int i=0;i<6;i++){ if(b[i]%k==0){ b[i]/=k; }else return 0; } ll sum=1; int n=12/k; for(int i=0;i<6;i++){ sum*=C[n][b[i]]; n-=b[i]; } return sum; } ll Count2(int k){ for(int i=0;i<6;i++){ if(b[i]%k==0){ b[i]/=k; }else return 0; } ll sum=1; int n=10/k; for(int i=0;i<6;i++){ sum*=C[n][b[i]]; n-=b[i]; } return sum; } ll Static(){ return Count(1); } ll Point(){ return 4*2*Count(3); } ll Plane(){ return 3*(2*Count(4)+Count(2)); } ll Edge(){ ll ans=0; for(int i=0;i<6;i++){ for(int j=0;j<6;j++){ memcpy(b,a,sizeof a); b[i]--;b[j]--; if(b[i]<0||b[j]<0)continue; ans+=6*Count2(2); } } return ans; } ll Polya(){ ll ans=0; ans+=Static(); ans+=Point(); ans+=Plane(); ans+=Edge(); return ans/24; } int main() { //freopen("E:\\read.txt","r",stdin); int T,col; Init(); scanf("%d",&T); while(T--){ memset(a,0,sizeof a); for(int i=1;i<=12;i++){ scanf("%d",&col); a[col-1]++; } cout<<Polya()<<endl; } return 0; }