acm-Polya计数定理

Polya定理目录

  • 轨道-稳定子定理
  • Burnside 引理
  • polya 引理

轨道-稳定子定理

对于一个置换群 G G G,定义 G G G作用于一个元素 a a a代表取 G G G中所有的置换对 a a a作变换后能够得到的所有可能的结果构成的集合,这个集合中的所有元素也就构成了一个在 G G G作用下形成的等价类。
轨道-稳定子定理就是说对于任意一个元素 a a a的等价类中元素个数 × \times ×对元素 a a a施加 G G G中的置换后元素 a a a保持不变的置换个数 = G =G =G中的总置换个数。

Burnside 引理

Z i Z_i Zi表示对 i i i元素进行置换后结果仍为 i i i元素的置换集合, E i E_i Ei表示 i i i元素的等价类的大小, D i D_i Di表示在 i i i置换下不变的元素个数, N N N表示元素总个数, L L L表示等价类总个数。
于是轨道-稳定子定理可以表示成 ∣ Z i ∣ × ∣ E i ∣ = ∣ G ∣ |Z_i|\times |E_i|=|G| Zi×Ei=G,下面开始Burnside 引理的推导。
∑ i = 1 N ∣ Z i ∣ = ∑ i = 1 L ∣ E i ∣ ∣ Z i ∣ = L ∣ G ∣ ⇒ L = 1 ∣ G ∣ ∑ i = 1 N ∣ Z i ∣ = 1 ∣ G ∣ ∑ i = 1 ∣ G ∣ D i \begin{aligned} \sum_{i=1}^{N}|Z_i| &=\sum_{i=1}^L|E_i||Z_i|\\ &=L|G|\\ \Rightarrow L&=\frac{1}{|G|}\sum_{i=1}^{N}|Z_i|\\ &=\frac{1}{|G|}\sum_{i=1}^{|G|}D_i \end{aligned} i=1NZiL=i=1LEiZi=LG=G1i=1NZi=G1i=1GDi

polya 引理

p o l y a polya polya定理就是Burnside 引理的应用,考虑一个环上染色的问题,假设可以染的颜色有 k k k种,定义 G G G就是环的所有旋转变换,那么考虑对于每种旋转都是一种置换,置换就存在循环节,假设有 k k k个循环节,则每个循环节内染色必须相同,不难得出染色方案的等价类数量为 L = ∑ i = 1 n k M i n L=\frac{\sum_{i=1}^{n}k^{M_i}}{n} L=ni=1nkMi,其中 M i M_i Mi代表循环节个数, n n n代表环长,即有 n n n种不同的置换。

例题一
题目来源:LuoGuP4980 【模板】Pólya 定理

题面:
acm-Polya计数定理_第1张图片
题解:
容易发现 L = 1 n ∑ i = 1 n n g c d ( i , n ) L=\frac{1}{n}\sum_{i=1}^nn^{gcd(i,n)} L=n1i=1nngcd(i,n),改成枚举因子的形式容易得到 L = 1 n ∑ d ∣ n n d φ ( n d ) L=\frac 1n\sum_{d\mid n}n^d\varphi(\frac nd) L=n1dnndφ(dn),直接暴力算就行了。
代码:

#include 
using namespace std;
const int mod = 1e9+7;


int phi(int n){
	int ans=1;
	for(int i=2;i*i<=n;++i){
		if(n%i==0){
			while(n%i==0){
				ans*=i;
				n/=i;
			}
			ans=ans/i*(i-1);
		}
	}
	if(n>1){
		ans*=(n-1);
	}
	return ans;
}
int qpow(int a,int b){
	int ans=1;
	while(b){
		if(b&1)ans=1ll*ans*a%mod;
		b>>=1;
		a=1ll*a*a%mod;
	}
	return ans;
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
		int ans=0;
		for(int i=1;i*i<=n;++i){
			if(n%i)continue;
			if(i==n/i){
				ans=(ans+1ll*qpow(n,i)*phi(n/i)%mod)%mod;
			}else{
				ans=(ans+1ll*qpow(n,i)*phi(n/i)%mod)%mod;
				ans=(ans+1ll*qpow(n,n/i)*phi(i)%mod)%mod;
			}
		}
		ans=1ll*ans*qpow(n,mod-2)%mod;
		printf("%d\n",ans);
	}
} 

你可能感兴趣的:(数学,组合计数,acm竞赛,算法)