Burnside 引理 与 Pólya 定理 学习笔记

news2024/10/3 8:30:29

为了防止明天就把好不容易听完的东西都还给 rabbit_lb 了,还是记一点吧。

1. 群论基础

1.1 群(group) 的定义

给定集合 G G G G G G上的二元运算 ⋅ \cdot ,满足下列条件称之为群:

  • 封闭性:若 a , b ∈ G a,b\in G a,bG,则 a ⋅ b ∈ G a\cdot b\in G abG
  • 结合律:对于任意 a , b , c ∈ G a,b,c\in G a,b,cG,有 ( a ⋅ b ) ⋅ c = a ⋅ ( b ⋅ c ) (a\cdot b)\cdot c=a\cdot (b\cdot c) (ab)c=a(bc)
  • 单位元:存在单位元 e ∈ G e\in G eG ∀ a ∈ G ,   a ⋅ e = e ⋅ a = a \forall a\in G,\, a\cdot e=e\cdot a=a aG,ae=ea=a
  • 逆元:对于任意 a ∈ G a\in G aG,存在 b ∈ G b\in G bG,使得 a ⋅ b = b ⋅ a = e a\cdot b=b\cdot a=e ab=ba=e。记为 b = a − 1 b=a^{-1} b=a1

1.2 一些概念

  • 群元素个数有限则称为有限群,无限则称为无限群

  • 有限群 G G G 的元素个数叫做群的阶,记做 ∣ G ∣ |G| G

  • G G G G G G上的二元运算 ⋅ \cdot 构成一个群, H H H G G G 的子集,且 H H H 在原有运算下也是一个群,则 H H H G G G 的一个子群。

  • 若群 G G G 的任意两元素均满足交换律,则称 G G G 为交换群(Abel 群)。

1.3 群的性质

  • 单位元唯一: e 1 e 2 = e 1 = e 2 e_1e_2=e_1=e_2 e1e2=e1=e2
  • 消去律: a b = a c ⇒ b = c ab=ac\Rightarrow b=c ab=acb=c
  • 每个元的逆元唯一:反证,若 a a − 1 = a − 1 a = e ,   a b − 1 = a − 1 b = e aa^{-1}=a^{-1}a=e,\, ab^{-1}=a^{-1}b=e aa1=a1a=e,ab1=a1b=e,则 a a − 1 = a b − 1 aa^{-1}=ab^{-1} aa1=ab1,即 a − 1 = b a^{-1}=b a1=b
  • G G G 有限,且 a ∈ G a\in G aG,则存在最小正整数 r r r,使得 a r = e a^r=e ar=e,且 a − 1 = a r − 1 a^{-1}=a^{r-1} a1=ar1 r r r 称为 a a a 的阶。

2. 置换群

2.1 置换

[ 1 , n ] [1,n] [1,n] 到自身的一个映射称为 n n n 阶置换,表示为 ( 1 2 … n a 1 a 2 … a n ) \begin{pmatrix}1&2&\dots & n\\a_1&a_2&\dots&a_n\end{pmatrix} (1a12a2nan),其中 a 1 , a 2 , … , a n a_1,a_2,\dots,a_n a1,a2,,an [ 1 , n ] [1,n] [1,n] 的一个排列。

n n n 阶置换共有 n ! n! n! 个,同一个置换有 n ! n! n! 中表示方法,如 p 1 = ( 1 2 3 4 3 1 2 4 ) = ( 3 1 4 2 2 3 4 1 ) p_1=\begin{pmatrix}1&2&3&4\\3&1&2&4\end{pmatrix}=\begin{pmatrix}3&1&4&2\\2&3&4&1\end{pmatrix} p1=(13213244)=(32134421) n n n 阶置换也可以看作 [ 1 , n ] [1,n] [1,n] 上的一元运算。

P 1 = ( 1 2 … n a 1 a 2 … a n ) ,   P 2 = ( 1 2 … n b 1 b 2 … b n ) P_1=\begin{pmatrix}1&2&\dots & n\\a_1&a_2&\dots&a_n\end{pmatrix},\, P_2=\begin{pmatrix}1&2&\dots & n\\b_1&b_2&\dots&b_n\end{pmatrix} P1=(1a12a2nan),P2=(1b12b2nbn),则定义置换乘法 P 1 P 2 = ( 1 2 … n b a 1 b a 2 … b a n ) P_1P_2=\begin{pmatrix}1&2&\dots & n\\b_{a_1}&b_{a_2}&\dots&b_{a_n}\end{pmatrix} P1P2=(1ba12ba2nban)

置换乘法不满足交换律,但满足结合律。

2.2 置换群

[ 1 , n ] [1,n] [1,n] 上由多个置换组成的集合,在 2.1 的乘法定义下构成的群,称为置换群

  • 封闭性: ( 1 2 … n a 1 a 2 … a n ) ( a 1 a 2 … a n b 1 b 2 … b n ) = ( 1 2 … n b 1 b 2 … b n ) \begin{pmatrix}1&2&\dots & n\\a_1&a_2&\dots&a_n\end{pmatrix} \begin{pmatrix}a_1&a_2&\dots & a_n\\b_1&b_2&\dots&b_n\end{pmatrix}=\begin{pmatrix}1&2&\dots & n\\b_1&b_2&\dots&b_n\end{pmatrix} (1a12a2nan)(a1b1a2b2anbn)=(1b12b2nbn)
  • 结合律:由 2.1 知置换乘法满足结合律。
  • 单位元: e = ( 1 2 … n 1 2 … n ) e=\begin{pmatrix}1&2&\dots & n\\1&2&\dots&n\end{pmatrix} e=(1122nn)
  • 逆元: ( 1 2 … n a 1 a 2 … a n ) − 1 = ( a 1 a 2 … a n 1 2 … n ) \begin{pmatrix}1&2&\dots & n\\a_1&a_2&\dots&a_n\end{pmatrix}^{-1}=\begin{pmatrix}a_1&a_2&\dots & a_n\\1&2&\dots&n\end{pmatrix} (1a12a2nan)1=(a11a22ann)

[ 1 , n ] [1,n] [1,n] 上的所有( n ! n! n! 个)置换构成的群,称为 n n n 阶对称群,记作 S n S_n Sn。平时所说的 [ 1 , n ] [1,n] [1,n] 上的一个置换群,一定是 S n S_n Sn的子群。

2.3 循环

2.3.1 置换的循环表示

置换 ( 1 2 … n a 1 a 2 … a n ) \begin{pmatrix}1&2&\dots & n\\a_1&a_2&\dots&a_n\end{pmatrix} (1a12a2nan) 可以写作 ( 1 , a 1 , a a 1 , …   ) ( …   ) (1,a_1,a_{a_1},\dots)(\dots) (1,a1,aa1,)() 的形式,称为置换的循环表示。E.g. ( 1 2 3 4 5 3 1 2 5 4 ) = ( 132 ) ( 45 ) \begin{pmatrix}1&2&3 & 4&5\\3&1&2&5&4\end{pmatrix}=(132)(45) (1321324554)=(132)(45) ( 1 2 3 4 5 5 2 3 1 4 ) = ( 154 ) ( 2 ) ( 3 ) \begin{pmatrix}1&2&3 & 4&5\\5&2&3&1&4\end{pmatrix}=(154)(2)(3) (1522334154)=(154)(2)(3)

( a 1 a 2 … a m ) (a_1a_2\dots a_m) (a1a2am) 称为 m m m 阶循环,有 m m m 种表示方法。

通常情况下,我们可以忽略所有阶为 1 1 1 的循环。两个不相交的循环之间满足交换律。

定理:任意置换可表示成若干不相交循环的积。

证明:考虑令置换 i i i a i a_i ai 连边,图由若干个环构成。显然每个环都可以表示成一个循环。

2.3.2 共轭类

我们设置换 p p p 的循环表示为 $p=(a_1a_2\dots a_{k_1})(b_1,b_2\dots b_{k_2})\dots (h_1h_2\dots h_{k_n}),其中 $ ∑ i = 1 n k i = n \sum\limits_{i=1}^n k_i=n i=1nki=n。设 k k k 阶循环出现的次数为 c k c_k ck
那么置换 p p p 的格式为 ( 1 ) c 1 ( 2 ) c 2 … ( n ) c n (1)^{c_1}(2)^{c_2}\dots(n)^{c_n} (1)c1(2)c2(n)cn。E.g. ( 1 ) ( 23 ) ( 4567 ) (1)(23)(4567) (1)(23)(4567) 的格式为 ( 1 ) 1 ( 2 ) 1 ( 4 ) 1 (1)^1(2)^1(4)^1 (1)1(2)1(4)1

S n S_n Sn 中所有相同格式的置换构成一个共轭类

定理: S n S_n Sn ( 1 ) c 1 ( 2 ) c 2 … ( n ) c n (1)^{c_1}(2)^{c_2}\dots(n)^{c_n} (1)c1(2)c2(n)cn 所在的共轭类元素个数为 n ! ( c 1 ! c 2 ! … n ! ) ( 1 c 1 2 c 2 … n c n ) \dfrac{n!}{(c_1!c_2!\dotsc_n!)(1^{c_1}2^{c_2}\dots n^{c_n})} (c1!c2!n!)(1c12c2ncn)n!

可以这样理解这个式子:

  • 一个长度为 i i i 的循环共有 i i i 种表示, c i c_i ci 个长度为 i i i 的循环有 i c i i^{c_i} ici 种表示;
  • 对互不相交的 c i c_i ci 个循环枚举全排列,共有 c i ! c_i! ci! 种表示。
2.3.3 对换与奇偶置换

2 2 2 阶循环叫做对换

定理:任意循环都可以表示为若干对换的积。

推柿子:
( 1   2   3 … n − 1 ) ( 1   n ) = ( 1 2 … n − 1 2 3 … 1 ) ( 1 2 … n − 1 n n 2 … n − 1 1 ) = ( 1 2 … n − 1 n 2 3 … n 1 ) = ( 1   2   …   n ) \begin{aligned} &(1\, 2\, 3\dots n-1)(1\, n)\\ =&\begin{pmatrix}1&2&\dots & n-1\\2&3&\dots&1\end{pmatrix}\begin{pmatrix}1&2&\dots & n-1&n\\n&2&\dots&n-1&1\end{pmatrix}\\ =&\begin{pmatrix}1&2&\dots & n-1&n\\2&3&\dots&n&1\end{pmatrix}\\ =&(1\,2\,\dots\,n) \end{aligned} ===(123n1)(1n)(1223n11)(1n22n1n1n1)(1223n1nn1)(12n)
那么进一步地,有分解 ( 12 … n ) = ( 12 ) ( 13 ) … ( 1 n ) (1 2\dots n)=(12)(13)\dots(1n) (12n)=(12)(13)(1n)。注意每个置换的分解不唯一。

若一个置换能分解为奇数个对换之积,则为奇置换;否则为偶置换

Warning. 置换相乘的奇偶性类似于自然数加法,而非自然数乘法:奇 x 奇 = 偶,奇 x 偶 = 奇。

3. Burnside 引理

3.1 等价类与 k k k 不动置换类

G G G [ 1 , n ] [1,n] [1,n] 上的一个置换群, k ∈ [ 1 , n ] k\in [1,n] k[1,n] G G G 中使 k k k 元素保持不变的置换全体,称为 k k k 不动置换类,记作 Z k Z_k Zk

定理:置换群 G G G k k k 不动置换类 Z k Z_k Zk G G G 的子群。

  • 封闭性: k k k 怎么置换都不动。
  • 结合性:显然。
  • 单位元: G G G 的单位元也在 Z k Z_k Zk 中。
  • 逆元: Z k Z_k Zk 中的置换 p p p G G G 中的逆元 p − 1 p^{-1} p1 也在 Z k Z_k Zk 中。

置换 p i p_i pi 使图像 k k k 变为 l l l,则称 k k k l l l 属于同一个等价类。设 k k k 所在的等价类记为 E k E_k Ek

如图,将正方形四个顶点红蓝染色,等价类个数为 6 6 6。(每行是一个等价类)

3.2 轨道稳定子定理

定理:设 G G G [ 1 , n ] [1,n] [1,n] 上的一个 置换群, E k E_k Ek [ 1 , n ] [1,n] [1,n] G G G 的作用下包含 k k k 的等价类, Z k Z_k Zk k k k不动置换类。有 ∣ E k ∣ ∣ Z k ∣ = ∣ G ∣ |E_k||Z_k |=|G| Ek∣∣Zk=G

证明:每个等价类有 ∣ E k ∣ |E_k| Ek 个元素,同时因为它们属于同一等价类,每个元素的 Z k Z_k Zk 相同。因此这些 Z k Z_k Zk 覆盖了整个 G G G,即每个等价类都有 ∣ E k ∣ ∣ Z k ∣ = ∣ G ∣ |E_k||Z_k |=|G| Ek∣∣Zk=G

3.3 Burnside 引理

将上式变形,有:
∑ k = 1 n ∣ Z k ∣ ∣ G ∣ = ∑ k = 1 n 1 ∣ E k ∣ \sum_{k=1}^n \frac{|Z_k|}{|G|}=\sum_{k=1}^n \frac{1}{|E_k|} k=1nGZk=k=1nEk1
仔细想一下会发现 ∑ k = 1 n 1 ∣ E k ∣ \sum_{k=1}^n \frac{1}{|E_k|} k=1nEk1 就是等价类个数。

然而问题并没有解决,因为 Z k Z_k Zk 不好求。进一步地,我们定义 c 1 ( a k ) c_1(a_k) c1(ak) 表示在置换 a k a_k ak 的作用下不动点的个数,即长度为 1 1 1 的循环个数。那么等价类个数为:
l = 1 ∣ G ∣ ∑ j − 1 n c 1 ( a j ) l=\frac{1}{|G|}\sum_{j-1}^n c_1(a_j) l=G1j1nc1(aj)
这个式子就是 Burnside 引理。

4. Pólya 定理

Pólya 定理是 Burnside 引理的推广,应用于 染色问题循环同构 方案计数。

G = { P 1 , P 2 , … , P g } G=\{P_1,P_2,\dots,P_g\} G={P1,P2,,Pg} n n n 个对象 的一个置换群, C ( P k ) C(P_k) C(Pk) 是置换 P k P_k Pk 的循环的个数,用 m m m 种颜色对 n n n 个对象着色,着色方案数为
l = 1 ∣ G ∣ ∑ j = 1 g m C ( P j ) l=\frac{1}{|G|} \sum_{j=1}^g m^{C(P_j)} l=G1j=1gmC(Pj)

接下来用一个例题说明该定理的具体用法。

用火柴搭一个足球,有多少种方案?

Tips: 足球有 60 60 60 个顶点, 90 90 90 条棱, 12 12 12 个五边形, 20 20 20 个六边形。

  • 不动: 1 1 1 种置换, 2 90 2^{90} 290 种染色;
  • 五边形对五边形转: 6 × 4 = 24 6\times 4=24 6×4=24 种置换, 2 90 / 5 2^{90/5} 290/5 种染色;
  • 六边形对六边形转: 10 × 2 = 20 10\times 2=20 10×2=20 种置换, 2 90 / 3 2^{90/3} 290/3 种染色;
  • 棱中点对棱中点转: 15 15 15 种置换, 0 0 0 种染色(一定都会变)。

则本质不同的方案数为 ( 2 90 + 24 × 2 18 + 20 × 2 30 ) / ( 1 + 24 + 20 + 15 ) (2^{90}+24\times 2^{18}+20\times 2^{30})/(1+24+20+15) (290+24×218+20×230)/(1+24+20+15)

5. 例题

P4980【模板】Polya 定理

板子。发现置换只有旋转,考虑枚举旋转的角度,有:
1 n ∑ k = 1 n n gcd ⁡ ( k , n ) \frac{1}{n}\sum_{k=1}^n n^{\gcd(k,n)} n1k=1nngcd(k,n)
枚举 gcd ⁡ \gcd gcd,可以变成
1 n ∑ d ∣ n n d ∑ k = 1 n d [ gcd ⁡ ( k , n d ) = 1 ] \frac{1}{n} \sum_{d\mid n}n^d \sum_{k=1}^{\frac{n}{d}}[\gcd(k,\frac{n}{d})=1] n1dnndk=1dn[gcd(k,dn)=1]
也就是
1 n ∑ d ∣ n n d φ ( n d ) \frac{1}{n}\sum_{d\mid n}n^d\varphi(\frac{n}{d}) n1dnndφ(dn)
暴力计算欧拉函数即可通过。

Code
#define int long long 
const int mod=1e9+7;
int T,n;
il int qpow(int n,int k=mod-2)
{
    int res=1; 
    for(;k;n=n*n%mod,k>>=1) if(k&1) res=res*n%mod;
    return res;
}
il int phi(int x)
{
    int res=x;
    for(int i=2;i*i<=x;i++)
    {
        if(x%i==0) res=res/i*(i-1);
        while(x%i==0) x/=i;
    }
    if(x>1) res=res/x*(x-1);
    return res;
}
signed main()
{
    T=read();
    while(T--)
    {
        n=read(); 
        int ans=0;
        for(int d=1;d*d<=n;d++) if(n%d==0)
        {
            (ans+=qpow(n,d)*phi(n/d)%mod)%=mod;
            if(d*d!=n) (ans+=qpow(n,n/d)*phi(d)%mod)%=mod;
        }
        ans=ans*qpow(n)%mod;
        printf("%lld\n",ans);
    }
    return 0;
}

CF1065E Side Transmutations

首先可以发现翻转是可以抵消的。如果我们操作 b 1 b_1 b1,再操作 b 2 b_2 b2,再操作 b 1 b_1 b1,这相当于只操作了一个 b 2 b_2 b2。也就是说,想要得到最终状态我们只关心每个 b i b_i bi 被操作次数的奇偶性。

考虑 Polya 定理,但是发现不动点看起来不好算。

进一步对 b i b_i bi 进行转化,考虑将字符串分成形如 [ b 1 , b 2 ) , [ b 2 , b 3 ) , … [b_1,b_2),[b_2,b_3),\dots [b1,b2),[b2,b3), 的若干段。那么我们统计不动点的时候只关心每一段是否被翻转。
不难看出,字符串每段的翻转状态与 b b b 的操作次数奇偶性序列构成双射。设 l e n i len_i leni 表示第 i i i 段的长度。

那么如果第 i i i 段被翻转了,这一段本身的贡献是 ∣ A ∣ l e n i |A|^{len_i} Aleni;否则为 ∣ A ∣ 2 l e n i |A|^{2len_i} A2leni。而对于中间长度为 n − 2 l e n m n-2len_m n2lenm 且永远不会被翻转的段,贡献恒为 ∣ A ∣ n − 2 l e n m |A|^{n-2len_m} An2lenm

故设 T = { 1 , 2 , … , n } T=\{1,2,\dots,n\} T={1,2,,n},本质不同的方案数为
∣ A ∣ n − 2 l e n m 2 m ∑ S ⊆ T ( [ i ∈ S ] ∣ A ∣ l e n i ) + ( [ i ∉ S ] ∣ A ∣ 2 l e n i ) = ∣ A ∣ n − 2 l e n m 2 m ∏ i = 1 m ( ∣ A ∣ l e n i + ∣ A ∣ 2 l e n i ) \begin{aligned} &\frac{|A|^{n-2len_m}}{2^m}\sum_{S\sube T}([i\in S]|A|^{len_i})+([i\notin S]|A|^{2len_i})\\ =&\frac{|A|^{n-2len_m}}{2^m}\prod_{i=1}^m (|A|^{len_i}+|A|^{2len_i}) \end{aligned} =2mAn2lenmST([iS]Aleni)+([i/S]A2leni)2mAn2lenmi=1m(Aleni+A2leni)
直接计算即可,时间复杂度为 O ( m log ⁡ n ) \mathcal{O}(m\log n) O(mlogn)

Code
#define int long long
const int N=2e5+5,mod=998244353;
int n,m,A,b[N];
int l[N];
il int qpow(int n,int k=mod-2)
{
    int res=1;
    for(;k;n=n*n%mod,k>>=1) if(k&1) res=res*n%mod;
    return res;
}
signed main()
{
    n=read(),m=read(),A=read();
    for(int i=1;i<=m;i++) b[i]=read();
    for(int i=1;i<=m;i++) l[i]=b[i]-b[i-1];
    int sum=1,ans=0;
    for(int i=1;i<=m;i++) sum=sum*(qpow(A,l[i])+qpow(A,2*l[i]))%mod;
    ans=sum*qpow(A,n-2*b[m])%mod;
    ans=ans*qpow(qpow(2,m))%mod;
    printf("%lld\n",ans);
    return 0;
}

ARC062F Painting Graphs with AtCoDeer

一个比较直观的性质是,一条边无论如何都转不出自己所在的边双连通分量。进一步地,发现实际上一条边转不出自己所在的点双。这似乎有点反直觉,但考虑下图,边无法从一个环移到另一个环:

那么根据这个结论,每个点双之间是独立的。分类讨论:

  • 如果一条边的两个端点不在同一点双里,这条边对答案的贡献是 k k k
  • 如果点双是一个环,这是 Polya 定理的板子;
  • 否则有结论:如果一个点双有至少两个环,所有边都可以任意交换。

考虑证明上述结论,我们只需证明存在一种方案,在不改变其他边的情况下交换两条边。

使用上图的做法可以交换两环交界处的两条边。对于不在两环交界处的边,可以先转到交界处再如此操作。
故设这个点双有 c n t cnt cnt 条边,对答案的贡献就是 c n t cnt cnt 条边涂 k k k 个颜色,不区分顺序的方案数。经典插板法,为 ( c n t + k − 1 k − 1 ) \binom{cnt+k-1}{k-1} (k1cnt+k1)

对以上三种情况分别计算贡献即可。

Code
#define int long long
const int N=205,mod=1e9+7;
int n,m,k;
vector<int> e[N];
int dfn[N],low[N],tot,num;
vector<int> t[N],q;
void tarjan(int u,int fa)
{
    dfn[u]=low[u]=++tot; q.push_back(u);
    for(auto v:e[u]) if(v^fa)
    {
        if(!dfn[v])
        {
            tarjan(v,u),low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u])
            {
                num++;
                while(q.back()!=u) 
                {
                    int x=q.back();
                    t[num].push_back(x),q.pop_back();
                    if(x==v) break;
                }
                t[num].push_back(u);
            }
        }
        else low[u]=min(low[u],dfn[v]);
    }
}
int bel[N];
il int qpow(int n,int k=mod-2)
{
    int res=1;
    for(;k;n=n*n%mod,k>>=1) if(k&1) res=res*n%mod;
    return res;
}
il int solve(int m)
{
    int res=0;
    for(int i=1;i<=m;i++) res=(res+qpow(k,__gcd(i,m)))%mod;
    res=res*qpow(m)%mod; return res;
} 
int jc[N],inv[N];
il void init(int mx)
{
    jc[0]=inv[0]=1;
    for(int i=1;i<=mx;i++) jc[i]=jc[i-1]*i%mod;
    inv[mx]=qpow(jc[mx]);
    for(int i=mx-1;i;i--) inv[i]=inv[i+1]*(i+1)%mod;
}
il int C(int n,int m) 
{
    if(m>n) return 0;
    return jc[n]*inv[n-m]%mod*inv[m]%mod;
}
signed main()
{
    n=read(),m=read(),k=read();
    for(int i=1;i<=m;i++)
    {
        int u=read(),v=read();
        e[u].push_back(v),e[v].push_back(u);
    }
    init(m+k);
    int ans=1;
    for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,0);
    for(int i=1;i<=num;i++)
    {
        for(auto x:t[i]) bel[x]=i;
        int cnt=0;
        for(auto u:t[i])
            for(auto v:e[u]) if(bel[v]==i) cnt++;
        cnt>>=1;
        m-=cnt;
        if(cnt>t[i].size()) ans=ans*C(cnt+k-1,k-1)%mod;
        else if(cnt==t[i].size()) ans=ans*solve(cnt)%mod;
        else ans=ans*qpow(k,cnt)%mod;
    }
    printf("%lld\n",ans);
    return 0;
}

[HNOI2009] 图的同构计数

我们可以把每条边选与不选看作对一个完全图上的边黑白染色,这与原题意是等价的。

使用 Polya 定理,先枚举一个置换,并把置换写成循环的形式。考虑对在该置换下不变的染色方案进行计数。

根据一条边的两个端点是否在同一个循环内,分类讨论:

  • 如图,若一条边的两个端点属于同一循环,那么它应当与循环内所有长度相等的边同色。

    那么一个长度为 l e n len len 的循环,其内部共有 ⌊ l e n 2 ⌋ \lfloor \frac{len}{2}\rfloor 2len 类等价的边。
  • 否则,若一条边连接了两个不同循环,设它们的长度分别为 l e n i , l e n j len_i,len_j leni,lenj。那么一条边需要做 lcm ( l e n i , l e n j ) \text{lcm}(len_i,len_j) lcm(leni,lenj) 次置换才能回到它原来的位置,即等价类个数为 gcd ⁡ ( l e n i , l e n j ) \gcd(len_i,len_j) gcd(leni,lenj)

综上,一个 l e n len len 序列对 polya 求和式子的贡献为
S = ∑ i = 1 n ( ⌊ l e n i 2 ⌋ + ∑ j = 1 i − 1 gcd ⁡ ( l e n i , l e n j ) ) S=\sum_{i=1}^n(\lfloor \frac{len_i}{2}\rfloor +\sum_{j=1}^{i-1} \gcd(len_i,len_j)) S=i=1n(⌊2leni+j=1i1gcd(leni,lenj))
发现这只与 l e n len len 数组有关而与具体的置换无关,考虑只枚举 l e n len len 数组,并计算有多少种对应的置换。由 2.3.2 可知,设 c i c_i ci 表示 l e n j = i len_j=i lenj=i j j j 的个数,对应的置换数为
n ! ∏ l e n i ∏ ( c i ! ) \frac{n!}{\prod len_i\prod (c_i!)} leni(ci!)n!
总答案为
1 n ! ∑ l e n n ! ∏ l e n i ∏ ( c i ! ) 2 S \frac{1}{n!}\sum_{len}\frac{n!}{\prod len_i\prod (c_i!)} 2^S n!1lenleni(ci!)n!2S
其中 S S S 见上文。时间复杂度为 n n n 的无序拆分数。

Code
#define int long long
const int N=205,mod=997;
int n,ans,tot,b[N],c[N];
il int qpow(int n,int k=mod-2)
{
    int res=1;
    for(;k;n=n*n%mod,k>>=1) if(k&1) res=res*n%mod;
    return res;
}
il int solve()
{
    int res=0;
    for(int i=1;i<=tot;i++)
    {
        res=(res+(b[i]>>1));
        for(int j=1;j<i;j++) res=(res+__gcd(b[i],b[j]));
    }
    return res;
}
void dfs(int sum)
{
    if(!sum)
    {
        int k=solve();
        int v=1;
        for(int i=1;i<=n;i++) c[i]=0;
        for(int i=1;i<=tot;i++) v=v*b[i]%mod,c[b[i]]++;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=c[i];j++) v=v*j%mod;
        ans=(ans+qpow(2,k)*qpow(v)%mod)%mod;
        return;
    }
    for(int k=b[tot];k<=sum;k++)
    {
        b[++tot]=k,dfs(sum-k);
        tot--;
    }
}
signed main()
{
    n=read();
    b[0]=1; dfs(n);
    printf("%lld\n",ans);
    return 0;
}

P4128 [SHOI2006] 有色图

与上题同理,将 2 2 2 换为 k k k 即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1332210.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习之实验过程01

import pandas as pd import numpy as np import matplotlib.pyplot as plt data_path = /home/py/Work/labs/data/SD.csv # 请确保您的数据文件路径是正确的 df = pd.read_csv(data_path) df.head() # 创建散点图 # 创建散点图 plt.figure(figsize=(10, 6)) plt.scat…

DDD领域驱动设计系列-原理篇-战术设计

概述 上篇战略设计产出了领域及问题域领域模型&#xff1b;详见&#xff1a;DDD领域驱动设计系列-原理篇-战略设计-CSDN博客 战术设计篇聚焦如何落地&#xff0c;包含实际解决方案模型落地&#xff0c;架构分层&#xff08;Clean&#xff0c;CQRS&#xff09;&#xff0c;Rep…

基于Qt之QChart 图表(优美的曲线图案例)

## 项目演示 平台:ubuntu18.04 Qt版本:QT5.14.2 源码位置GitCode:https://gitcode.com/m0_45463480/QCharts/tree/main ## QChart 图表 自从 Qt 发布以来,给跨平台的用户带来很多便利。在 Qt5.7 之前,Qt 在开源社区版本里没有 Qt Charts(自带的绘图组件库)。这使得像…

蓝桥杯2020年10月青少组Python程序设计省赛真题

1、设计一个猜字母的程序,程序随机给出26个小写字母中的一个,答题者输入猜测的字母,若输入的不是26个小写字母之一,让用户重新输入,若字母在答案之前或之后,程序给出相应正确提示,如答错5次,则答题失败并退出游戏,若回答正确,程序输出回答次数并退出游戏。 2、试编一个“口…

收到口头offer千万别飘,离发书面offer还有很远!4个口头offer都没通过,血的教训!...

求职时一路过关斩将&#xff0c;终于收到了口头offer&#xff0c;算是稳了吗&#xff1f; 一位打工人给广大求职者一个建议&#xff1a; 当你收到口头offer时千万别飘&#xff01;因为离最后收到书面offer有很长距离&#xff0c;还有下面这些事要做&#xff1a; 1.提交各种材料…

算法模板之队列图文详解

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;算法模板、数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. ⛳️模拟队列1.1 &#x1f514;用数组模拟实现队列1.1.1 &#x1f47b;队列的定…

第26关 K8s日志收集揭秘:利用Log-pilot收集POD内业务日志文件

------> 课程视频同步分享在今日头条和B站 大家好&#xff0c;我是博哥爱运维。 OK&#xff0c;到目前为止&#xff0c;我们的服务顺利容器化并上了K8s&#xff0c;同时也能通过外部网络进行请求访问&#xff0c;相关的服务数据也能进行持久化存储了&#xff0c;那么接下来…

集简云与语聚AI新增Google Gemini、Gemini Vision两大模型,让对话能力再升级

近日&#xff0c;人工智能又掀起一股热潮&#xff0c;Google最新推出的AI大模型Gemini备受瞩目。号称多模态任务处理能力首次超越人类的 AI 模型&#xff0c;不仅可以处理文本内容&#xff0c;还可以无缝丝滑地处理代码、音频、图像和视频等多种模态的信息。 随着Gemini pro版…

Python patchworklib任意合并子图,多图形混合排版

【背景】 数据展示时&#xff0c;在同一页面上混合排版多个图形是一种常见的用法。本次分享一个Python轮子patchworklib库&#xff1a;通过|、/轻松实现图形排列&#xff1b;比matplotlib、seaborn等自带子图功能更加灵活; 【patchworklib简介】 Patchworklib 是与 matplotl…

IDEA中使用数据库可视化操作工具

文章目录 1.入门介绍2. 没有数据库驱动3. 准备&测试连接3.1测试报错 4.连接5.编写SQL语句 1.入门介绍 在IDEA的专业版的右侧工具栏应该会有DataBase按钮如果没有的同学可以这样操作(必须是IDEA专业版) 新建数据库 2. 没有数据库驱动 如果提示: missing driver files ,…

qt项目-《图像标注软件》源码阅读笔记-类图

目录 1. 开源项目链接 2. 项目界面 3. 项目类图 3.1 形状的绘制及形状的存储 3.2 主窗口中心组件的界面管理 3.3 Command负责实现撤销和重做功能 3.4 其他类 3.5 枚举 3.5.1 Status 主窗口的状态变量 3.5.2 Mode 主窗口模式状态变量 3.5.3 shapeStatus 中心组件状态…

前菜---二叉树+堆的小练习

目录 前言&#x1f3dc;️ 1. 二叉树性质总结⛱️ 1.2 性质3⏰ 2. 二叉树性质小练习&#x1f3d5;️ 3. 答案解析&#x1f4a1; 4. 堆概念结构小练习&#x1fa94; 5. 答案解析&#x1f9ff; 6. 前/中/后/层序遍历小练习&#x1f52b; 7. 答案解析&#x1f9fa; 后语…

MySQL主从架构及读写分离实战

​​​​​​ 目录 一、实验目的与环境 二、基础环境介绍 三、搭建主从集群 1、理论基础 2、同步的原理 3、搭建主从集群 3.1 配置master主服务器 3.2 配置slave从服务 3.3 主从集群测试 3.4 集群搭建扩展&#xff1a; 3.5、GTID同步集群 4、集群扩容 5、半同步复…

Nessus详细安装-windows (保姆级教程)

Nessus描述 Nessus 是一款广泛使用的网络漏洞扫描工具。它由 Tenable Network Security 公司开发&#xff0c;旨在帮助组织评估其计算机系统和网络的安全性。 Nessus 可以执行自动化的漏洞扫描&#xff0c;通过扫描目标系统、识别和评估可能存在的安全漏洞和弱点。它可以检测…

【数据结构入门精讲 | 第十七篇】一文讲清图及各类图算法

在上一篇中我们进行了的并查集相关练习&#xff0c;在这一篇中我们将学习图的知识点。 目录 概念深度优先DFS伪代码 广度优先BFS伪代码 最短路径算法&#xff08;Dijkstra&#xff09;伪代码 Floyd算法拓扑排序逆拓扑排序 概念 下面介绍几种在对图操作时常用的算法。 深度优先D…

【数据结构入门精讲 | 第十四篇】散列表知识点及考研408、企业面试练习(1)

在上一篇中我们进行了树的专项练习&#xff0c;在这一篇中我们将进行散列表知识点的学习。 目录 概念伪代码线性探测法平方探测法查找成功的平均查找长度查找失败的平均查找长度判断题选择题 概念 散列表&#xff08;Hash Table&#xff09;&#xff0c;也被称为哈希表或散列映…

CogAgent:带 Agent 能力的视觉模型来了

之前我们分享过智谱AI新一代多模态大模型 CogVLM&#xff0c;该模型在不牺牲任何 NLP 任务性能的情况下&#xff0c;实现视觉语言特征的深度融合&#xff0c;其中 CogVLM-17B 在 14 个多模态数据集上取得最好或者第二名的成绩。 12月15日&#xff0c;基于 CogVLM&#xff0c;提…

【小沐学写作】Docsify制作在线电子书、技术文档(Docsify + Markdown + node)

文章目录 1、简介2、安装2.1 node2.2 docsify-cli 3、配置3.1 初始化3.2 预览效果3.3 加载对话框3.4 更多页面3.5 侧 栏3.6 自定义导航栏 结语 1、简介 https://docsify.js.org/#/?iddocsify 一个神奇的文档网站生成器。 简单轻巧没有静态构建的 html 文件多个主题 Docsify…

第11章 GUI Page426~427 步骤七 设置直线前景色

运行效果&#xff1a; 关键代码&#xff1a; 接口类 IItem中新增29,30行两个设置前景色纯虚方法 //item_i.hpp 抽象“图形元素”接口定义 #ifndef ITEM_I_HPP_INCLUDED #define ITEM_I_HPP_INCLUDED#include <wx/gdicmn.h> #include <wx/dc.h>class IItem { publ…

Matlab论文插图绘制模板第132期—函数等高线填充图

在之前的文章中&#xff0c;分享了Matlab函数折线图的绘制模板&#xff1a; 函数三维折线图&#xff1a; 函数网格曲面图&#xff1a; 函数曲面图&#xff1a; 函数等高线图&#xff1a; 进一步&#xff0c;再来分享一下函数等高线填充图。 先来看一下成品效果&#xff1a; 特…