polya计数

polya计数

总结

问题: 同构计数

bunside定理: 在置换g下染色方案不变数的平均值;公式:(frac{1}{|G|}sum_{gin 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_{gin 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;
}
原文地址:https://www.cnblogs.com/fridayfang/p/11082886.html