【题解】UVA - 11255 (Burside)
OI生涯第一道Burside?
上次伦的火箭课件已经进行了扫盲,具体来说,定理内容是这样的:
从我浅薄的知识来看,Polya只是Burside的计数版本
Burside
设置换群(G),以及一个可以被这个群作用的集合(S),那么(G_S)的轨道数量(本质不同的(S)中的元素)是:
[sum_{gin G} {| ext{stab }S_g|over |G|} ]
证明被我吃了
-
旋转同构
- 考虑顺时针转(kin[1,n])步,对于旋转(k)步,总共有(gcd (k,n))种不同的"循环"需要填,这些循环必须满足循环内所有元素相同(这样才能保持旋转时不会造成不同)。每个循环的长度是(nover gcd(k,n)),直接算即可。
-
翻转同构(len=2)
-
加旋转的翻转,意义是有(n)种对称轴,同样地计算一下就行了。
-
奇数
枚举翻转的那个颜色,再进行翻转。
-
偶数
-
对称轴经过两个点
- 枚举两个点的颜色即可
-
对称轴经过一个空隙
-
直接算就好了
-
-
-
关键是恰当地对置换进行分类
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; typedef long long ll;
const int maxn=40+5;
ll c[maxn][maxn];
void pre(const int&n){
for(int t=0;t<=n;++t)
for(int i=c[t][0]=1;i<=t;++i)
c[t][i]=c[t-1][i-1]+c[t-1][i];
}
int a[3],b[3],n;
ll Polya(int k){
int s=0;
for(int t=0;t<3;++t)
if(b[t]%k||b[t]<0) return 0;
else b[t]/=k,s+=b[t];
ll ret=1;
for(int t=0;t<3;++t)
ret*=c[s][b[t]],s-=b[t];
return ret;
}
int main(){
pre(41);
int T;
cin>>T;
size_t siz=sizeof a;
while(T--){
n=0;
for(int t=0;t<3;++t) cin>>a[t],n+=a[t];
ll ans=0;
for(int t=1;t<=n;++t)
memcpy(b,a,siz),ans+=Polya(n/__gcd(t,n));
if(n&1)
for(int t=0;t<3;++t)
memcpy(b,a,siz),--b[t],ans+=Polya(2)*n;
else{
for(int t=0;t<3;++t)
for(int i=0;i<3;++i)
memcpy(b,a,siz),--b[t],--b[i],ans+=Polya(2)*n/2;
memcpy(b,a,siz),ans+=Polya(2)*n/2;
}
cout<<ans/(n<<1)<<endl;
}
return 0;
}