Polya(置换)
Polya定理
本篇文章并不是详细讲解,而是加深自己的记忆
群:
群的定义: 集合 \(G\) 和作用于集合 \(G\) 的二元计算 \(×\),满足以下 \(4\) 个性质就记为 \((G,×)\)。
- 封闭性:\(a,b∈G\), \(a × b∈G\)
- 结合律:$ (a\times b)\times c = a\times (b\times c)$
- 单位元: 存在 \(e∈G\) ,满足对于任意 \(a\in G\) 有: \(a\times e = e\times a = a\) ,此时 \(e\) 被称为单位圆。乘法运算就是一个群。
- 逆元:对于任意 \(a\in G\) 存在 \(a'\in G\) 满足 \(a\times a' = a'\times a = e\) ,此时 \(a'\) 唯一。
子群:
分为左陪集,右陪集。
陪集性质:
- \(\forall g\in G,|H|= |Hg|\)
- \(∀g∈G,g\in Hg\)
- \(Hg = H\iff g\in H\)
- \(Ha=Hb⟺a×b^{−1}∈H\)
- \(Ha∩Hb\neq∅→Ha=Hb\)
- \(H\) 的全体右陪集的并为 \(G\)
左陪集同理,证明省略2。
比较常见的表述:
若 \(H≤G\),则 \(G/H\) 代表 \(G\) 中所有的 \(H\) 的左陪集即 \(\{gH,g\in G\}\)
若 \(H≤G\),则 \([G:H]\) 表示 \(G\) 中 \(H\) 的不同的陪集的数量
拉格朗日定理:
置换:
定义:
双行表示 \(\sigma\) 法:表示从上列 \(a\) 到下列 \(b\) 的置换,表示用第 \(a_i\) 个元素替换第 \(b_i\) 个元素。
表示一个置换
每个置换就是一个这样的排列,一个长度为 \(n\) 的不同的置换数量为 \(n!\).
运算:
表示为 \(\sigma(a)\),运算规则为: \(\sigma(a)=(a_{\sigma1},a_{\sigma2}...a_{\sigma n})\)
我们称呼为置换的合成。
置换群:
我们令群 \(G=(M,×)\) ,其中 \(M\) 为 \(N={1,2,3...n}\) 集合的若干个排列构成的集合,此时若 \(G\) 满足群的性质,\(G\) 就是一个置换群。
群作用:
分为左群作用和右群作用:
对于一个集合 \(M\) 和群 \(G\):
若给定了一个二元函数 \(\phi(v,k)\) ,其中 \(v\) 为群中的元素, \(k\) 为集合元素,有:
其中 \(e\) 为单位元,则群 \(G\) 作用于集合 \(M\).
轨道-稳定子定理
Burnside 定理
定义 \(G\) 为一个置换群,定义其作用于 \(X\), 如果 \(x,y\in X\) 在 \(G\) 作用下可以相等,即存在 \(f\in G\) 使得 \(f(x)=y\) ,则定义 \(x,y\) 属于一个等价类,则不同的等价类的数量为:
\(X^g\) 为 \(X\) 在 \(g\) 作用下的不动点的数量,即满足 \(g(x)=x\) 这样的 \(x\) 的数量。
文字版:\(X\) 在群 \(G\) 作用下的等价类总数等于每一个 \(g\) 作用于 \(X\) 的不动点的算数平均值。
综上,就得到了 \(Burnside\) 定理。
本质不同的 \(n\) 个点的环可以看作:
在群 \(G\) 为 { 旋转 \(0\) 个,旋转 \(1\) 个...旋转 \(n−1\) 个 } 这些置换作用下得到的等价类的数量。
同时我们定义集合 \(M\) 为 \(\{1\to n\}\) 的所有可能排列表示初始的环。
答案就为:
旋转 \(0\) 个的不动点为 \(n^n\) ,即所有集合都合法。
对于旋转 \(k\) 个,\(gcd(k,n)\) 随意取,贡献为 \(n^{gcd(k,n)}\)
答案就是:
枚举 \(gcd\) ,再运用欧拉函数,得到:
暴力计算即可算出。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
int T,n;
int qmi(int a,int b){
int res=1; while(b){if(b&1) res=res*a%mod; a=a*a%mod; b>>=1;} return res;
}
int phi(int x){
int ans=x;
for(int i=2;i<=sqrt(x);i++){
if(x%i) continue;
ans=ans-ans/i;
while(x%i==0) x/=i;
}
if(x!=1) ans=ans-ans/x;
return ans;
}
signed main(){
cin>>T;
while(T--){
cin>>n; int cnt=sqrt(n),ans=0;
for(int i=1;i<=cnt;i++){
if(n%i) continue;
int p1=phi(i),f1=qmi(n,n/i);
f1=f1*p1%mod; ans=(ans+f1)%mod;
if(i*i!=n){
int p2=phi(n/i),f2=qmi(n,i);
f2=f2*p2%mod; ans=(ans+f2)%mod;
}
}
cout<<ans*qmi(n,mod-2)%mod<<endl;
}
system("pause");
return 0;
}