【学习笔记】Polya定理

笔者经多番周折终于看懂了Burnside定理和Polya定理,特来写一篇学习笔记来记录一下。


群定义

定义:群(G,·)是一个集合与一个运算·所定义的群。它所需要满足的性质是:

  • 结合律:对于任意a,b,cG,a·b·c=a·(b·c).

  • 封闭性:对于任意a,bG,a·bG.

  • 单位元:存在eG,a·e=a.

  • 逆元:aG,aG,a·a=a·a=e.

举一个例子:对于正方形旋转组成的群(旋转度数分别为0,90,180,270),旋转操作就是群中的元素,单位元就是旋转度数为0的操作。结合律显然满足,我们看剩下两个条件:

  • 封闭性:先旋转90再旋转270就相当于旋转360即旋转0G.容易证明对于每一种操作都存在这种封闭性。

  • 逆元:对于旋转90的操作我们可以再旋转270将它转换为单位元0.对其它所有元素均存在逆元。

所以这个由旋转操作构成的集合(操作是连续旋转)可以被证明是一个群。

子群:即一个群HG.

注意,群中的元素不一定满足交换律,所以才有了左陪集和右陪集的区别:

  • 左陪集 对于一个子群HG,一个元素gG,gH称之为H的一个左陪集。gH=hH,g·h.

  • 右陪集 对于一个子群HG,一个元素gG,Hg称之为H的一个右陪集。Hg=hH,h·g.

陪集的一些性质(只讨论右陪集,左陪集同理)

gG,|H|=|Hg|

证明:

h1H,h2H,h1·gh2·g故得证。

gG,gHg

证明:

由于H是群,所以包含单位元使得gH.

Hg=HgH

证明:

H具有封闭性。

Ha=Hba·b1H

证明:

Ha=HbHa·b1=Ha·b1H

a·b1HHa·b1=HHa=Hb

HaHbHa=Hb

证明:

这条性质意味着H的陪集要么不相交要么相等。

cHa,cHbh1,h2H,h1·a=h2·b=ca·b1=h2·h11HHa=Hb.


群作用

我们说一个群G作用于集合X,当且仅当:

给定一个函数φ(v,x)(其中,vG,xX)有:

φ(e,x)=x,φ(a,φ(b,x))=φ(a·b,x)

有上述函数时才有群G作用于X.


置换

用双行表示法来表示一个置换:

ρ=(1,2,3,4,52,1,3,4,5)

表示一个由序列1,2,3,4,5变为2,1,3,4,5的一个置换。大体就是用第一个元素代替第二个元素...以此类推。

一个长度为n的不同置换数为n!.

关于运算:ρ(a)=(aρ1,aρ2...)

可以证明,这些置换组成了群。


轨道-稳定子定理

定义:

轨道G(x)x通过G中所有元素作用可以达到的所有元素的集合。gG,g(x)x通过g这个元素作用可以达到的所有元素。

稳定子Gx={g|gG,g(x)=x} 即群G中所有 g(x)=xg 的集合。

定理:|Gx||G(x)|=|G|

可以得到,每一个状态x一定只属于一个轨道。我们把g(x)=x的点看做一个轨道的结尾,这个定理就很好证明了。


Burnside 引理

定义G是一个置换群且作用于集合X,x,yX,fG,f(x)=y,x,y属于一个等价类。

注意!这里f(x)不是一个函数,而是元素xf作用下得到的元素。

则不同等价类的数量为:

Ans=1|G|gGXg

Xg=|Gx|.

文字描述:X 在群 G 作用下的等价类总数等于每一个 g 作用于 X 的不动点的算数平均值。

证明待补。

关于这道题:群中元素就是{TurnZeroPlace,TurnOnePlace,TurnTwoPlace...Turn(N1)Place},X是所有置换所形成的环。

对于旋转k个而言,其不动点等价于存在一个长度为a的循环节使得a|k.又因为必然a|n(转n格必然回到原始状态),所以改写判断条件为存在一个长度为gcd(k,n)的循环节。而前gcd(k,n)个元素可以任意填(染色,不是排列),所以答案就是1nk=1nngcd(k,n)

枚举gcd莫比乌斯反演得到Ans=d|nnd1φ(n/d)可以O(n)计算。

模板题链接

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
inline int add(int x,int y){return (x+y)%mod;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline int qpow(int a,int b){
	int res=1;
	while(b){
		if(b&1)res=mul(res,a);
		a=mul(a,a);b>>=1;
	}
	return res;
}
int calc(int x){
	int ans=x;
	for(int i=2;i*i<=x;++i){
		if(x%i)continue;
		ans-=ans/i;
		while(x%i==0)x/=i;
	}
	if(x!=1)ans-=ans/x;
	return  ans;
}
int T,n;
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		int ans=0;
		for(int i=1;i*i<=n;++i){
			if(n%i)continue;
			ans=add(ans,mul(qpow(n,i-1),calc(n/i)));
			if(i*i==n)continue;
			ans=add(ans,mul(qpow(n,n/i-1),calc(i)));
		}
		printf("%d\n",ans);
	}
	return 0;
}
posted @   Refined_heart  阅读(886)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 三行代码完成国际化适配,妙~啊~
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
历史上的今天:
2019-09-13 【题解】序列终结者
2019-09-13 【题解】数列
点击右上角即可分享
微信分享提示