zoukankan      html  css  js  c++  java
  • Burnside引理与Polya定理 学习笔记

    原文链接www.cnblogs.com/zhouzhendong/p/Burnside-Polya.html

    问题模型

      有一个长度为 $n$ 的序列,序列中的每一个元素有 $m$ 种取值。

      如果两个序列循环同构,那么我们称这两个序列等价。

      求两两不等价的序列个数。

    Burnside引理

      假设有若干个置换 $P_1,P_2,cdots$ ,设由这些置换生成的置换群为 $Q$ 。如果序列 A 可以通过一个 $Q$ 中的置换变成序列 B,那么我们认为 A 和 B 等价。

      对于一个置换 $P$ ,如果序列 A 经过置换 $P$ 之后不变,那么我们称序列 A 为置换 $P$ 的一个“不动点”。令 $C(P)$ 表示置换 $P$ 的不动点数。

      Burnside引理:

        对于一个置换群 $Q$,两两不同的序列个数为

    $$frac 1 {|Q|} sum_{Pin Q} C(P)$$

    Polya定理

      Polya定理是Burnside引理的一个具体化。

      Polya定理:

        假设置换 $P$ 由 $k$ 个轮换组成,那么 

    $C(P) = m^{k}$ 

      至此,我们已经可以解决最开始的问题模型了。

    $$ans = frac 1n sum_{i=0}^{n-1} m ^ {gcd(i,n)}$$

    例题 - POJ2409 Let it Bead

    题意

      有一种项链有 $n$ 个珠子,珠子有 $m$ 种。项链是环,但是没有起始点,也没有方向。也就是说,如果两个项链循环同构或者对称翻转后循环同构,那么他们等价。

      求不等价的项链种数。

      $ncdot m leq 32$ 。

    题解

      这类问题,我们首先考虑一下置换群 $Q$ 中有哪些元素。

      1. 旋转。可以旋转 $0cdots n-1$ 次,故有 $n$ 种方案。这部分等价于本文开头的问题模型。

      2. 翻转。由于任何形如 “旋转 + 翻转 + 旋转” 的操作都可以由一次翻转得到,所以本质上只有翻转操作。不管 $n$ 是奇数还是偶数,都有 $n$ 种本质不同的翻转操作,而且这些操作与之前的旋转也不同。

      所以,置换群 $Q$ 中共有 $2n$ 种置换。

      现在我们考虑求 $sum C(P)$ 。

      对于 1. 旋转,之前已经提到,这种情况对答案的贡献就是

    $$sum_{i=0}^{n-1} m ^ {gcd(i,n)}$$

      对于 2. 翻转,我们分 $n$ 的奇偶性进行讨论:

      n 为奇数:只能将一个顶点与其对边中点所在直线作为对称轴进行翻转:一共有 $n$ 种方案,每种方案都由 $frac {n+1} 2$ 个轮换构成,故对答案的贡献是 

    $$n cdot m ^ {frac {n+1} 2}$$

      n 为偶数:有两种情况:

        1. 以两个顶点所在直线为对称轴进行翻转:一共有 $frac n 2$ 种方案,每种方案都由 $frac{n+2} 2$ 个轮换构成,故对答案的贡献是

    $$frac n2 cdot m ^ {frac {n+2} 2} $$

        2. 以两条边的中点所在直线为对称轴进行翻转:一共有 $frac n 2$ 种方案,每种方案都由 $frac{n} 2$ 个轮换构成,故对答案的贡献是

    $$frac n2 cdot m ^ {frac {n} 2} $$

      至此,问题解决。

    代码

    #include <algorithm>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    using namespace std;
    typedef long long LL;
    int n,m;
    LL Pow(LL x,LL y){
    	LL ans=1;
    	for (;y;y>>=1,x*=x)
    		if (y&1)
    			ans*=x;
    	return ans;
    }
    int gcd(int a,int b){
    	return b?gcd(b,a%b):a;
    }
    int main(){
    	while (1){
    		cin>>m>>n;
    		if (!n&&!m)
    			break;
    		LL ans=0;
    		for (int i=0;i<n;i++)
    			ans+=Pow(m,gcd(n,i));
    		if (n&1)
    			ans+=Pow(m,(n+1)>>1)*n;
    		else {
    			ans+=Pow(m,n>>1)*(n>>1);
    			ans+=Pow(m,(n+2)>>1)*(n>>1);
    		}
    		ans/=n<<1;
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    php 数组处理
    PHP 递归几种方法
    PHP取一算法
    oracle的db link
    sql2008破解加密存储过程
    ATT 解锁手机
    jQuery 通配符
    win10 Enable developer Mode
    Win8.1 远程桌面 凭据无法工作
    html5media.js 让浏览器兼容<Video><Audio> 标签
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/Burnside-Polya.html
Copyright © 2011-2022 走看看