Polya 定理 (附POJ 1286 Necklace of Beads 解题报告)

来源:互联网 发布:涂子沛 数据之巅 pdf 编辑:程序博客网 时间:2024/06/05 10:22

Polya定理:

       设G是一个p个对象的置换群,那么用k种颜色对p个对象进行染色!当一种方案在群G的作用下变为另外一种方案,那么我们这个时候就认为这两个方案是一样的。那么在这种规定下不同的染色方案为:

n=(Ek^m(f))/|G|,其中m(f)是置换f的循环节。

       Polya定理是基于Burnside定理和另外一个定理的,其中Burnside定理的通俗表达方法如下:

      1)如果令C(f)表示在置换f的作用下,本质不变的着色方案数!那么可以证明的是“本质不同的着色方案数就是所有置换f下的C(f)的平均数”。

       在Burnside的基础上,我们在介绍一个定理:

       2)如果使用k种颜色给有限集合S着色,那么对于一个置换f,在该置换下本质不变的着色方案数就是C(f)=k^(m(f)),其中m(f)是置换f的循环节数。

       基于上面的1)2)两个定理,便很明显的得到Polya定理。

       介绍了Polya定理之后,我们来看看Polya的简单应用,在POJ 1286题中,如果是旋转或者是对称变换相同的着色方案算作一种着色方案数。那么我们直接使用Polya定理进行求解就行了,但是这个时候对奇数和偶数的情况下对称变换的置换是不一样的,分开求解就可以了!对于旋转的置换的循环节我们直接进行dfs求解就可以了。

       

#include <iostream>#include <cstring>#include <cstdio>#include <cstdlib>using namespace std;typedef long long LL;LL myPow(LL a,int b){    LL sum=1LL;    while(b)    {        if(b%2==1)        {            sum*=a;        }        a*=a;        b/=2;    }    return sum;}int vis[30],adj[30];void dfs(int i){    if(vis[i]==0)    {        vis[i]=1;        dfs(adj[i]);    }}int find(int s,int n){    memset(vis,0,sizeof(vis));    for(int i=1;i<=n;i++)    {        int e=(s+i-1)%n;        if(e==0)            e=n;        adj[i]=e;    }    int sum=0;    for(int i=1;i<=n;i++)    {        if(vis[i]==0)        {            dfs(i);            sum++;        }    }    return sum;}int main(){    int n;    LL a,b;    while(scanf("%d",&n))    {        if(n==-1)            break;        if(n<=0)        {            printf("0\n");            continue;        }        if(n%2==0)        {            a=myPow(3LL,n);           for(int i=2;i<=n;i++)           {               int tn=find(i,n);               a+=myPow(3LL,tn);           }            b=(LL)n;            a=a+(LL)(n/2)*(myPow(3LL,(n+2)/2));            a=a+(LL)(n/2)*(myPow(3LL,n/2));            b+=(LL)n;        }        else        {            a=myPow(3LL,n);            for(int i=2;i<=n;i++)            {                int tn=find(i,n);                a+=myPow(3LL,tn);            }            b=(LL)n;            a=a+(LL)n*(myPow(3LL,1+(n-1)/2));            b+=(LL)n;        }        printf("%lld\n",a/b);    }    return 0;}

下面附上我的代码:


原创粉丝点击