题意:
有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;
}