PS: 寫的時候博主比較naive,所有的變換都是向右結合的,還請諒解(
0. 引子 (update 2020/12/21){#s-0}
直接上理論會有點難受,不妨先來點簡單的計數題找找感覺?
0.1 倒序同構序列計數{#s-0.1}
長度為 \(n\) 的序列 \(A\) 滿足 \(\forall 1 \le i \le n, \ 1 \le a_i \le m\) ,問有多少種不同的序列 \(A\) ?
序列是無標號的,即正序和倒序記為一種方案。
容易想到一種計數方式——若不考慮同構,顯然有 \(m^n\) 種選擇方案。對其中的非回文序列,可以直接計數然后除以 \(2\) 去重。而回文序列正反都相同,不能直接除掉,因此對每個回文序列補上“倒序”的情況再除以 \(2\) 即可。回文序列有 \(m^{\lceil \frac n 2 \rceil}\) 種,故最終答案為 \(\frac 1 2 (m^n + m^{\lceil \frac n 2 \rceil})\) 。
PS:現在我們可以對直鏈鹵代烷進行計數了,答案為 \(\frac 1 2 (4^2 \times 3^{n-2} + 4 \times 3^{\lceil \frac n 2 \rceil -1})\) 。
PPS:你也許馬上想到了環鹵代烷計數,它正是后面Polya所解決的問題。
在這個小問題中,我們“補”上的回文序列正是Burnside思想的精髓。Burnside的目標便是為此類等價類計數問題找到一種通用的解決方案。欲知后事如何,請看下文分解。
1. 群{#s-1}
1.1 群的概念{#s-1.1}
群 \((S,\circ)\) 是一個元素集合 \(S\) 和一種二元運算 \(\circ\) 的合稱,其滿足以下性質。
封閉性
對於 \(\forall a,b \in S\) , \(\exist c \in S\) 使得 \(c = a \circ b\)
結合律
對於 \(\forall a,b,c \in S\) , \(a \circ (b \circ c) = (a \circ b) \circ c\)
單位元
\(\exist I \in S\) ,使得對於 \(\forall a \in S\) , \(a \circ I = I \circ a = a\)
根據定義,單位元具有唯一性,即一個群只有一個單位元。
證明:設 \(a,b\) 都是 \(S\) 的單位元,則 \(a = a \circ b = b\) ,兩者實質上相同。
逆元
對於 \(\forall a \in S\) , \(\exist a^{-1} \in S\) ,使得 \(a \circ a^{-1} = a^{-1} \circ a = I\)
根據定義,逆元具有唯一性,即每個元素有且僅有一個逆元。
證明:設 \(a\) 有兩個逆元 \(b,c\) ,則 \(b = b \circ I = b \circ (a \circ c) = (b \circ a) \circ c = I \circ c = c\) ,兩者實質相同。
這也同時說明了不存在兩個元素 \(a, b\) 的逆元是同一個元素 \(c\),因為 \(c\) 只有唯一一個逆元。
即逆元是一一對應的。
1.2 更抽象的群{#s-1.2}
我們更進一步,將 \(S\) 中的每一個元素視為一個函數, 默認 \(\circ\) 代表函數的復合,即 \((f \circ g) (x) = f(g(x))\)。所以現在一個群可以只用一個函數集合 \(S\) 來表示。
例如,記 \(r_\theta (x)\) 表示將 \(x\) 旋轉 \(\theta\) 度,那么 \(S = \{ r_{0^\circ}, r_{90^\circ},r_{180^\circ},r_{270^\circ}\}\) 就是一個群。
證明一下,顯然有封閉性和結合律。
單位元是 \(r_{0^\circ}\) ,因為 \(r_{0^\circ} (r_\theta(x)) = r_{\theta^\circ} (r_0 (x)) = r_\theta(x)\)
\(S\) 中元素 \(r_\theta\) 的逆元便是 \(r_{360^\circ - \theta}\) ,因為他們兩個卷起來就是 \(I = r_{0^{\circ}}\)
1.3 提示{#s-1.3}
由於群滿足封閉性,所以我們在尋找群的時候一定要“找完”所有可能的狀態,例如 \(\{ r_{0^\circ}, r_{90^\circ}\}\) 就不是一個群。
2. Burnside{#s-2}
記號說明:通常使用 \(a,b,c,d \in C\) 表示計數對象,而 \(f,g,h \in G\) 表示變換。
2.1 等價{#s-2.1}
給定一個作用在計數集合 \(C\) 上的變換集合 \(G\),若 \(C\) 中計數對象 \(d\) 可以由計數對象 \(c\) 通過 \(G\) 中變換得到,即 \(\exist f \in G\) 使得 \(d = c \circ f\),我們便稱 \(c\) 與 \(d\) 等價,記作 \(c \sim d\) 。
\(G\) 其實就是個函數集合,其中的函數都接受 \(C\) 中元素作為參數,輸出也是 \(C\) 中元素。
類似的我們記 \(f(c)\) 為 \(c \circ f\) ,表示對計數對象 \(c\) 做變換 \(f\) 。
我們同樣可以對一個函數做變換,即 \(f \circ g\) 是允許的。請參考上文更抽象的群 。
在Burnside中,我們要求 \(G\) 是一個群。這樣我們可以導出一些關於等價的性質。
自反性
\(a \sim a\)
因為 \(G\) 是群,故有單位元 \(I \in G\) , \(a \circ I = a\) ,滿足等價定義。
對稱性
\(a \sim b \iff b \sim a\)
設 \(a \circ f = b\) ,因為 \(G\) 是群,故存在 \(f^{-1}\) 使得 \(b \circ f^{-1} = a\) ,滿足等價定義。同理反向再證一次即可得出充分完全性。
傳遞性
\(a \sim b , b \sim c \Rightarrow a \sim c\)
設 \(a \circ f = b, b \circ g = c\),因為 \(G\) 是群,所以 \(f \circ g \in G\)(封閉性),\(a \circ (f \circ g) = (a \circ f) \circ g = b \circ g = c\),滿足等價定義。
2.2 等價類及等價類計數{#s-2.2}
等價類即所有等價的計數元素的集合。計數集合 \(C\) 由許多個等價類構成,好比連通塊。 統計 \(C\) 中有多少個等價類,就是等價類計數。
如何快速的等價類計數,便是我們接下來所研究的。
2.3 弱化版{#s-2.3}
不妨先來研究一個弱化版本,這可以幫助我們捋清思路。
2.3.1 引理{#s-2.3.1}
若對於 \(\forall c \in C,f \in G \quad (f \not= I)\) , \(c \circ f \not= c\) 都成立,那么對於 \(\forall c \in C, f \in G,g \in G \quad (f \not= g)\) ,都有 \(c \circ f \not= c \circ g\) ,即與 \(\forall c\) 等價的元素有且僅有 \(|G|\) 個。
利用反證法。假設 \(\exist c,f,g\) 使得 \(c \circ f = c \circ g\) ,那么有 \(c \circ f \circ g^{-1} = c\) ,即 \(c \circ (f \circ g^{-1}) = c\) (同時因為 \(f \not= g\) ,所以 \(f \circ g^{-1} \not= I\) ),於是與假設產生矛盾,故引理成立。
對 \(c\) 做變換得到的元素兩兩不同,共有 \(|G|\) 種變換,故有且僅有 \(|G|\) 個元素與 \(c\) 等價。
2.3.2 弱化版Burnside{#s-2.3.2}
若對於 \(\forall c \in C,f \in G \quad (f \not= I)\) , \(c \circ f \not= c\) 都成立,那么
\[等價類計數 = \frac{|C|}{|G|} \]
這是肉眼可得的結論。由引理,對於 \(\forall c\) ,都有且僅有 \(|G|\) 個互不相同的元素與其等價。由於等價的傳遞性,這 \(|G|\) 個元素是封閉的,實質上形成了許多個大小為 \(|G|\) 的等價類。那么等價類個數自然就是總計數元素個數 \(|C|\) 除以每個等價類的大小 \(|G|\) 了。
2.4 標准版{#s-2.4}
弱化版的關鍵之處在於引理, \(c \circ f \not= c\) 讓我們知道每個 \(c\) 有 \(|G|\) 個互不相同的元素與其等價。我們將這個條件和這個引理做一些“推廣”。
2.4.1 穩定核 & 不動點{#s-2.4.1}
穩定核 \(G(c)\) :對於計數對象 \(c\) ,使得 \(c \circ f = c\) 的所有變換 \(f\) 的集合,即 \(\{ f \in G | c \circ f = c \}\)
不動點 \(C(f)\) :對於變換 \(f\) ,使得 \(c \circ f = c\) 的所有計數對象 \(c\) 的集合,即 \(\{ c \in C | c \circ f = c \}\)
注意單個字母 \(G\) 代表整個變換集合;而 \(G(c)\) 是根據計數元素 \(c\) 生成的一個被 \(G\) 包含的變換集合;
注意單個字母 \(C\) 代表整個計數集合;而 \(C(f)\) 是根據變換 \(f\) 生成的一個被 \(C\) 包含的計數集合。
2.4.2 引理1{#s-2.4.2}
\[\sum_{c \in C} |G(c)| = \sum_{f \in G} |C(f)| \]
證明:
其實質是更換枚舉方式。
2.4.3 引理2{#s-2.4.3}
對於 \(\forall c\) , \(G(c)\) 是個群。
分別證明群的四個性質即可。
封閉性
對於 \(\forall f,g \in G(c)\) , \(c \circ (f \circ g) = (c \circ f) \circ g = c \circ g = c\) ,所以 \(f \circ g \in G(c)\) 。封閉性得證。
結合律
\(G(c) \subseteq G\) ,結合律直接由 \(G\) 給出。
單位元
\(c \circ I = c\) ,所以 \(I \in G(c)\) 。(這里的 \(I\) 代指 \(G\) 的單位元)
逆元
對於 \(\forall f \in G(c)\) , \(c \circ f^{-1} = (c \circ f) \circ f^{-1} = c \circ (f \circ f^{-1}) = c\) ,所以 \(f^{-1} \in G(c)\) 。
Extra (update 2020/03/28)
有個群論定理可以直接證明上述結論:
有限群的非空封閉子集都是子群。
另外,在后面我們將會發現 \(|G(c)|\) 實際上是 \(|G|\) 的約數,這反應了拉格朗日定理:
一個有限群 \(S\) 的子群的大小是 \(|S|\) 的約數。
有趣的是,拉格朗日定理的證明實際上和下文引理3的證明幾乎一模一樣。
這兩個定理在這里不做詳細討論,有興趣的同學可以左轉算法導論和這里(拉格朗日定理證明)
2.4.4 引理3{#s-2.4.4}
對於 \(\forall c\) ,記 \(S(c)\) 為與 \(c\) 等價的計數元素的集合,有
\[|S(c)| = \frac{|G|}{|G(c)|} \]
這個引理與弱化版引理是對應關系。請對比起來理解。
我們的證明思路是:對於某個計數元素 \(c\) ,求出 對於某個確定的變換 \(f\) ,有多少個變換 \(g\) 與其作用效果相同,即 \(c \circ f = c \circ g\) 。
即 \(f ,g\) 對 \(c\) 的作用效果相同 等價於 \(f \circ g^{-1}\) 在 \(c\) 的穩定核內。
於是對於一個變換 \(h \in G(c)\) ,根據群的基本性質,存在唯一的 \(g^{-1} = f^{-1} \circ h\) ,使得 \(f \circ g^{-1} = h\) 。變換 \(h \in G(c)\) ,所以有 \(|G(c)|\) 種取值; \(f\) 是確定的,根據逆元唯一性, \(f^{-1}\) 也是確定的;故 \(g^{-1}\) 有 \(|G(c)|\) 種取值。又由於逆元的一一對應性, \(g\) 有 \(|G(c)|\) 種取值。
即對於 \(\forall f\) ,都有且僅有 \(|G(c)|\) 個 \(g\) 與其作用效果相同。
這說明了什么?“作用效果相同”也是一種類似等價的關系,容易證明其具有傳遞性,於是他們是封閉的。作用效果相同的變換實質上形成 \(\frac{|G|}{|G(c)|}\) 個大小為 \(|G(c)|\) 的兩兩相連的連通塊或者說“作用效果相同等價類”,合起來構成了整個 \(G\) 。我們便知道了 \(c\) 通過變換可以變出 \(\frac{|G|}{|G(c)|}\) 個不同的計數元素,即與 \(c\) 等價的元素有 \(\frac{|G|}{|G(c)|}\) 個,引理3證畢。
2.4.5 Burnside{#s-2.4.5}
\[等價類計數 = \frac{1}{|G|}\sum_{f \in G} |C(f)| \]
倒數第二個式子,每個元素貢獻 \(\frac{1}{S(c)}\) ,合起來便是等價類計數。這便是等價類計數的本質。
2.5 Burnside的本質{#s-2.5}
直接除以4不行,因為前四種找不到4個等價的情況
所以強行把它們補成4個就行了。。。
Burnside就是“強行補”的過程
——zkx
Burnside的精髓就在於此。
Burnside弱化版,實際上是省掉了強行補的部分,使所有有效部分都在 \(C(I)\) 。
可以發現“群”是Burnside的唯一約束
這個約束幾乎就是沒有約束。。。
所以Burnside是非常通用的等價類計數法
——zkx
3. 置換群{#s-3}
(Burnside的內容已經結束,這里開始是Polya了)
3.1 置換{#s-3.1}
一個置換長這樣:
其中 \(a_1,a_2,a_3,...,a_n\) 是一個 \(n\) 排列。置換是一個接受序列,輸出序列的函數,它表示對每一個 \(i\) ,將原序列第 \(i\) 個數放到第 \(a_i\) 個位置上。這種括號是置換的表示方式,表示多個映射關系。
3.2 移位置換{#s-3.2}
一個普通的移位置換長這樣:
即全員右移 \(1\) 位。很自然的可以拓展到 \(k\) 位移位置換:
容易發現 \(\tau_n^k\) 是 \(k\) 個 \(\tau_n\) 的復合,所以我們寫成乘方的形式。
3.3 移位置換圖{#s-3.3}
移位置換 \(\tau_n^k\) 所形成的圖:考慮將 \(n\) 個點排成一個圓圈, \(1\) 連 \(k\) , \(2\) 連 \(k+1\) ,...,\(n\) 連 \(k-1\) 。
如圖便是 \(\tau_6^2\) 形成的移位置換圖,共有兩個環。
3.4 移位置換環個數定理{#s-3.4}
\(\tau_n^k\) 移位置換圖中環的個數為 \(\gcd(k,n)\) 。
證明的思路同樣是已經使用多次的:求出對於一個數 \(a\) ,有多少個數 \(b\) 與它在同一個環內。
對於 \(\forall a,b\) , \(a,b\) 在同一個環內的條件為
最后兩個式子之間的轉化運用了二元整數解不定方程的有解條件,即裴蜀定理。
那么這樣一來,對於 \(\forall a\) ,顯然有且僅有 \(\frac{n}{\gcd(k,n)}\) 個數與它在同一環內,故共有 \(\gcd(k,n)\) 個環。(“在同一環內”傳遞性導出的封閉性,這個方法在上文已經多次使用到)
4. Polya{#s-4}
4.1 概念{#s-4.1}
Polya是Burnside在環同構計數問題上的一個導出結論,比朴素的Burnside更加優秀。環同構的變換群 \(G\) 是一個移位置換群,即
即在平面內旋轉環能夠變得相同的方案算作一種。
顯然移位置換群是一個群 廢話,證明很簡單,同樣是證明群的四個性質,這里不再贅述。
最簡單的一類問題便是——洛谷P4980 Polya定理
給定一個 \(n\) 個點, \(n\) 條邊的環,有 \(m\) 種顏色,給每個頂點染色,問有多少種本質不同的染色方案,答案對 \(10^9+7\) 取模。
本質不同定義為:只需要不能通過旋轉與別的染色方案相同。
4.2 推導{#s-4.2}
有了前面那么多的鋪墊,大名鼎鼎的Polya定理現在已經可以自己動手推出來了!
先寫出Burnside引理,並套入移位置換
注: \(\tau_n^n = \tau_n^0\) ,上面從 \(1\) 到 \(n\) 的枚舉是對的
\(|C(\tau_n^i)|\) 是什么?
\(\tau_n^i\) 的不動點的個數,即要求 \(\tau_n^i\) 移位置換圖里同一環上點顏色相同的方案數。(為了做置換后看上去和原來一樣)
根據移位置換環個數定理, \(\tau_n^i\) 有 \(\gcd(n,i)\) 個環。有 \(m\) 種顏色給 \(\gcd(n,i)\) 個環去染,顯然方案數為 \(m^{\gcd(n,i)}\) 。我們不局限於本題推而廣之,方案數是一個關於環個數 \(\gcd(n,i)\) 的函數 \(f(\gcd(n,i))\) 。(也可以是關於環大小 \(\frac{n}{\gcd(n,i)}\) 的函數,反正最重要的參數是 \(\gcd(n,i)\) )
帶入原式
誒!這個式子里面有 \(\gcd\) !
不用抑制住沖動,我們按照常見的莫反題目套路來。
好恭喜你可以在 \(O(\sqrt n)\) 的優秀時間復雜度里求得答案了!
4.3 實現{#s-4.3}
提示一下實現上的一些細節。
快速冪作為基本技巧就不提了;
歐拉函數直接質因數分解求即可。這里會遇到一個小問題:外面一層枚舉因數,里面一層分解質因數,這不 \(O(\sum_{d|n} \sqrt d)\) 了嗎?
似乎利用數列的放縮之類的黑科技可以證明一個比 \(O(n)\) 更緊的上界是 \(O(n^{\frac 3 4})\) ,實際上則有香港記者的速度(洛谷 \(n=10^9\) , \(10^3\) 組數據可以隨便跑過)
/*
洛谷P4980 Polya定理
sun123zxy
朴素寫法
洛谷共2.08s
2019/12/24
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
ll Rd(){
ll ans=0;char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') ans=ans*10+c-'0',c=getchar();
return ans;
}
const ll MOD=1E9+7;
ll QPow(ll x,ll up){
x%=MOD;
ll ans=1;
while(up)
if(up%2==0) x=x*x%MOD,up/=2;
else ans=ans*x%MOD,up--;
return ans;
}
ll Inv(ll x){return QPow(x,MOD-2);}
ll Phi(ll n){
ll t=n;
ll ans=1;
for(ll i=2;i*i<=t;i++){
ll c=0;
while(t%i==0) t/=i,c++;
if(c) ans=ans*(QPow(i,c)-QPow(i,c-1)+MOD)%MOD;
}
if(t>1) ans=ans*(t-1)%MOD;
return ans;
}
ll N;
ll Polya(ll d){
return QPow(N,d)*Phi(N/d)%MOD;
}
void Solve(){
ll Ans=0;
for(ll i=1;i*i<=N;i++){
if(N%i==0){
Ans+=Polya(i);
if(i!=N/i) Ans+=Polya(N/i);
Ans%=MOD;
}
}
Ans=Ans*Inv(N)%MOD;
printf("%lld\n",Ans);
}
int main(){
ll T=Rd();while(T--){
scanf("%lld",&N);
Solve();
}
return 0;
}
不過當然有真正 \(O(\sqrt n)\) 的寫法。只需在最外層分解質因數,然后DFS的去枚舉因數,這樣就不用每次去分解 \(\frac{n}{d}\) 啦!於是這種寫法就快更多了。
/*
洛谷P4980 Polya定理
sun123zxy
更優寫法
洛谷共125ms
2019/12/24
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
int Rd(){
int ans=0;char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') ans=ans*10+c-'0',c=getchar();
return ans;
}
const ll MOD=1E9+7;
ll QPow(ll x,ll up,bool isM=1){
x%=MOD;
ll ans=1;
while(up){
if(up%2==0) x=x*x,up/=2;
else ans=ans*x,up--;
if(isM) x%=MOD,ans%=MOD;
}
return ans;
}
ll Inv(ll x){return QPow(x,MOD-2);}
namespace Div{
int p[30],c[30];
int pN;
void Div(int nb){
pN=0;
int t=nb;
for(int i=2;1LL*i*i<=t;i++){
if(t%i==0){
p[++pN]=i,c[pN]=0;
while(t%i==0) t/=i,c[pN]++;
}
}if(t>1) p[++pN]=t,c[pN]=1;
}
}
int N;
ll Ans;
void DFS(int pos,ll d,ll phi){
using namespace Div;
if(pos==pN+1){
Ans=(Ans+QPow(N,d)*phi)%MOD;
return ;
}
ll tpow=1,tphi=QPow(p[pos],c[pos],0)-QPow(p[pos],c[pos]-1,0);
for(int i=0;i<=c[pos];i++){
DFS(pos+1,d*tpow,phi*tphi);
tpow*=p[pos];
if(i==c[pos]-1) tphi=1;
else tphi/=p[pos];
}
}
void Solve(){
Div::Div(N);
Ans=0;DFS(1,1,1);
Ans=Ans*Inv(N)%MOD;
printf("%lld\n",Ans);
}
int main(){
int T=Rd();while(T--){
scanf("%d",&N);
Solve();
}
return 0;
}
5. 總結{#s-5}
對於大多數題目,Burnside & Polya通常是套在最表面的那一層皮,難點一般在求 \(|C(f)|\) 或者 \(f(\gcd(n,i))\) 的部分。
6. 參考及后記{#s-6}
zkx / keke_046 / 彳亍 學長的 《Polya計數.pptx》
整個PPT思路非常清晰,可以看出keke學長對Polya有極其深入的理解。我學Burnside完全是照着這個PPT一點一點的看懂的。
彳亍來講課的那個暑假可以說是真正讓我在OI數學這一塊有很多新的收獲,orz orz orz
2020/10/23 update: keke學長的PPT應該參考了《組合數學》,回頭去翻翻。
《算法導論》第三版 31章 數論算法
初稿寫成后,在學習數論時偶然翻到這一節有對群的一些討論,發現自己之前的理解不夠優秀,做了一些訂正。
之前把交換群認成群了然后瞎yy了一套理論xD
后記
Burnside & Polya 最開始是去年暑假keke學長為我們講授。當時雲里霧里,半懂不懂。12月的時候因為PKUWC/THUWC成為機房留守兒童(霧),就花了一兩天把keke的PPT慢慢看懂了,做了最初的筆記,在接下來的幾個月里修訂完善。
概念多,證明繞,很容易掉進思維的陷阱。要是能一步一步把證明過程捋清楚的話,對思維能力的提升還是很大的。
任何推導的目的都是由已知得到未知。把性質與推論構成的“有向無環圖”搞清楚了,才算真正弄清楚了來龍去脈。
Burnside弱化版是整理筆記時靈光一閃生造出來的一個中間步驟,希望對大家的理解有所幫助。
多次用到了“將等價類計數問題轉換為有多少個元素與某個確定的元素等價,並利用等價傳遞性導出封閉性說明形成連通塊”這一思想,很具有推廣性;另外遇到一些不太好證的命題可以試試反證法。
2020/03/21