polya定理 poj1286 poj2409

思路:

置换:【1,2,…,n | a1, a2,…an】 表示1被a1取代(a1为1到n的某数),2被a2取代……, a1,a2…,an不相同
置换群:置换群的元素是置换,运算时置换的连接。例如:【1,2,3,4 | 3,1,2,4】【1,2,3,4 | 4,3,2,1】 = 【1,2,3,4 | 2,4,3,1】
轮换:记(a1a2…an) = 【a1,a2,a3,…an | a2,a3,…,an,a1】

方案与方案之间其实是可以看做一种置换,即由其中一种方案通过置换可以变成另一种方案。例如有4个珠子,2种颜色,我们看一下前两个珠子白色,后两个黑色的情况。这种方案可以通过置换【2,3,4,1】可以变成第一个和第四个是黑色,第二个和第三个为白色的方案;
Burnside引理:
置换会使一个着色方案变成另一个方案。但是有些方案比较特殊,他在某些置换下会置换到他自身。我们称之在置换f下不变。记C(f)为置换f下保持不变的着色方案个数。那么就有一个结论:本质不同的着色方案数为所有置换f的C(f)值的平均数。
我们设f的置换群为G,则Burnside引理:等价类数目 N = sum{C(f)} / |G|, f属于G。
这个公式虽然简单,但是对于C(f)的求解还是个问题,于是介绍下面的定理。
Polya定理:
利用置换论中轮换的概念(轮换概念=循环概念),我们将置换f分解为若干循环。记f的循环节数位m(f)。
则有定理:C(f) = k ^ m(f) ,其中k为着色数。
于是有Polya定理:不同的着色方案数 l = sum(k ^ m(f)) / |G| ,其中f属于G。

对于本题还有如下结论:
在此种模型下,所有的置换可以通过一个置换旋转和翻转全部得来。
(1)旋转
将置换顺时针旋转i格,其循环节数的为gcd(n, i);
(2)翻转
当n为奇数:共有n个循环节数为(n+1)/2的循环群
当 n为偶数:共有n/2个循环节数(n+2)/2的循环群,和n/2个循环节数n/2的循环群。

Polya定理是个非常实用的定理,记p为格子数,s为着色数,则它可以在O(ps)内结果着色问题。

<span style="font-family:Arial;">/*
以后遇到累乘与幂用double或者long long 
输出的技巧就是</span>%.0lf
<span style="font-family:Arial;">*/</span>
#include<stdio.h>
#include<math.h>

int gcd(int a,int b)
{
	return b==0?a:gcd(b,a%b);
}

double polya(double k,int n)

{
    int i;
    double ans=0;
    for(i=0;i<n;i++)
       ans+=pow(k,gcd(n,i));
    if(n%2)
       ans+=n*pow(k,n/2+1);
    else
    {
       ans+=(n/2)*pow(k,n/2+1);
       ans+=(n/2)*pow(k,n/2);
    }
    return ans/(2*n);//G<span style="font-family:Arial;">中置换群的个数,n个旋转,n个翻转</span>
}

int main()

{
    int s;
    int c;
    while(scanf("%d",&c)&& c!=-1)
		if(c==0)
			printf("0\n");
		else
		printf("%.0lf\n",polya(3,c));
    return 0;

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值