polya计数
polya计数
总结
问题: 同构计数 \
bunside定理: 在置换g下染色方案不变数的平均值;公式:\(\frac{1}{|G|}\sum_{g\in G}C(g)\), 其中\(C(g)\) 是在染色方案在置换g下保持不变的方案的数目;不证; \
polya定理: \
polya定理是对Burnside定理求\(C(g)\)的优化,注意到置换中处于同一循环的元素应该保持染色相同,而不同循环的元素则互不影响。下面简单解释一下置换中的循环。 \
对于如下置换 g1\
1 2 3 4 5 \
3 2 1 5 4 \
那么由如下循环 (1,3)(2)(4,5),即要求(1,3)染色相同,(2)染色相同,(4,5) 染色相同。假设存在m中颜色,那么\(C(g1)=m^3\);由此可得polya公式: \
\(\frac{1}{|G|}\sum_{g\in G}{m^{c(g)}}\),其中\(c(g)\)表示置换g的循环次数(也称循环节的长度)
参考:
burnside定理可以看blog
入门题poj2409
分析
考虑旋转和反转两种置换,旋转的循环节长度为\(gcd(n,i) i=0,1,2..n-1\);
考虑翻转:分奇偶讨论对称轴即可
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int c,s;
int gcd(int a,int b){
if(b==0) return a;
return gcd(b,a%b);
}
ll polya(){
ll ans = 0;
for(int i=0;i<s;i++){
ans+=(ll)pow(c,gcd(s,i));
}
if(s&1){//odd
ans+=(ll)s*(ll)pow(c,s/2+1);
}
else{
ans+=(ll)(s/2)*(ll)pow(c,s/2+1);
ans+=(ll)(s/2)*(ll)pow(c,s/2);
}
return (ll)ans/(2*s);
}
int main(){
while(cin>>c>>s){
if(c==0&&s==0) break;
if(c==0) return 0;
if(s==0) return 1;
cout<<polya()<<endl;
}
return 0;
}