菜鸟系列——polya计数法

本文介绍了Burnside引理和Polya计数法在解决计数问题中的应用,通过POJ2409 'Let it Bead'实例详细解析了如何运用这两种方法来计算不同排列的数量。在旋转情况下,考虑每个元素的循环节数;在翻转情况下,根据奇偶性分析不同的循环节情况。
菜鸟就要老老实实重新学起:

Burnside引理,polya计数法:

Burnside引理: 1/|G|*(C(π1)+C(π2)+C(π3)+.....+C(πn));

C(π):指不同置换下的等价类数。例如π=(123)(3)(45)(6)(7),X={1,2,3,4,5,6,7};那么C(π)={3,6,7}共3个等价类。

Polya定理: 1/|G|*(mC(π1)+mC(π2)+mC(π3)+...+mC(πk)).

设G={π1,π2,π3........πn}是X={a1,a2,a3.......an}上一个置换群, 其中C(πk)为置换πk的循环节的个数。

eg:

POJ2409 Let it Bead

http://poj.org/problem?id=2409

题意:
有一个n长的项链,用m种颜色对其染色,有多少中不同的染色方法,项链可以旋转或者翻转。
思路:

用polya计数法,

对于旋转:每种旋转的循环节数就是gcd(i,n).

对于翻转:奇数时,按一个点与对边的轴翻转,循环节就是(n+1)/2,有n种。

                  偶数时,可以以两条对边翻转,循环节数就是n/2,可以以两对点翻转,循环节数就是(n+2)/2 ,分别有n/2种

code:
long long n,m;
long long  flag,sum,ave,ans,res;

long long gcd(long long x,long long y)
{
    return y?gcd(y,x%y):x;
}
long long power(long long x,long long k)
{
	long long ans = 1;
	while(k)
    {
		if(k & 1) ans *= x;
		x *= x;
		k >>= 1;
	}
	return ans;
}
int main()
{
    int i,j,k,kk,t,x,y,z;
    while(scanf("%lld%lld",&m,&n)!=EOF&&n)
    {
        sum=0;
        for(i=1;i<=n;i++)
            sum+=power(m,gcd(n,i));
        if(n&1)sum+=(n*power(m,(n+1)/2));
        else sum+=(n/2*power(m,(n+2)/2)+n/2*power(m,n/2));
        sum/=(2*n);
        printf("%lld\n",sum);
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值