• 「学习笔记」Burnside 引理 & Polya 定理


    前置知识

    群,置换,循环,轨道,不动点。

    (G) 为有限群,(X) 为一个集合,(x in X),定义 (x) 的轨道为

    [G_x = { gx | g in G } ]

    定义 (X) 的轨道数 (L = |{ G_x | x in X }|)(X^g = {x | x in X, gx = x }) 表示集合 (X) 中的所有不动点。

    所以,通俗地来说,轨道数就是本质不同的 xxx 的数量。

    定理

    Burnside 引理:

    [L = frac 1 {|G|} sum_{g in G} |X^g| ]

    然而并不会证明。

    例子

    洛谷P4980 【模板】Pólya 定理

    这里 (G) 中的元素都表示一个旋转了多少的置换。

    而如果旋转了 (i) 格,那么有 (gcd(n, i)) 个循环,要是不动点则必须满足循环上每个点颜色相同,所以不动点数目就是 (n^{gcd(n, i)})

    所以,答案就是:

    [frac 1nsum_{i=1}^n n^{gcd(n, i)} ]

    洛谷P4708 画画

    将无标号转成有标号,那么 (G) 就是点置换,这样 (L) 就表示本质不同的每个点度数都是偶数的图的个数。

    可以发现,如果我们要求不动点数目,那么只和每个置换的循环长度可重集有关,那么可以列出式子:

    [egin{aligned} mathrm{ans} &= frac 1 {n!} sum_{l_1 leq l_2 leq cdots leq l_k, c} left[left(sum l_i = n ight) and left(c_i = sum [l_j = i] ight) ight] inom{n}{l_1, l_2, cdots, l_k} frac {prod (l_i - 1)!}{prod c_i!} F(l_1, l_2, cdots, l_k)\ &= sum_{l_1 leq l_2 leq cdots leq l_k, c} left[left(sum l_i = n ight) and left(c_i = sum [l_j = i] ight) ight] frac 1{prod l_i prod c_i!} F(l_1, l_2, cdots, l_k) end{aligned} ]

    现在考虑求 (F)

    1. 循环内部连边

    对于一个循环 ((a_0a_1cdots a_{k - 1})),若 (a_i)(a_j) 有一条边,那么 (a_{i + 1 mod k})(a_{j + 1 mod k}) 之间也一定要连边。

    (k) 为奇数时,(lfloor frac k2 floor) 种合法的连边方案都不会改变任意点度数的奇偶性。

    (k) 为偶数时,仅有 (a_0)(a_{k / 2}) 连边会导致所有点度数奇偶性发生改变,还有 (k / 2 - 1) 种方案没有影响,可以直接加入答案中。

    2. 循环间连边

    对于任意两个循环 ((a_0a_1cdots a_{i-1}))((b_0b_1cdots b_{j - 1})),若 (a_x)(b_y) 有一条边,那么 (a_{x + 1 mod k})(b_{y + 1 mod k}) 也一定要有连边。

    所以说,两个循环中有 (gcd(i, j)) 种连边方式,同时每种方式给每个点带来的度数变化是一样的。

    由于一种方式会产生 (operatorname{lcm}(i,j )) 条边,所以每个点 (a_x) 就会连出 (frac {j} {gcd(i, j)}) 条边,(b_y) 同理。

    如果这条边只改变了 (a, b) 中一个循环的度数奇偶性,那么就可以当成一个点对自己的作用;如果同时改变了,记录下来;否则可以直接乘到答案中去。


    可以发现循环中每个点度数的奇偶性在任意时刻都相同,那么将一个循环看成一个点。

    此时问题转化为:给定 (k) 个点和 (e) 条边,每个点有 (p_i) 次机会使自己的点权异或 (1),对于每条边都有机会使边上两个端点的权值异或 (1),问操作完之后每个点权值不变的方案数。

    假设图连通(如果不连通就直接分开做),考虑每条边都不会改变 (k) 个点权值和的奇偶性,所以每个点的操作次数之和必须为偶数,所以操作点的方案数就是 (2 ^ {max(sum p_i - 1, 0)})

    接下来考虑原图的一棵生成树,可以发现只要非树边的方案确定,树边的方案可以唯一确定,所以这一部分的方案数就是 (2 ^ {e - k + 1})

    总方案数就是 (2 ^ {max(sum p_i - 1, 0) + e - k + 1})

    #include <cstdio>
    
    const int N(55), Mod(998244353);
    inline int upd(const int &x) { return x + (x >> 31 & Mod); }
    int fastpow(int x, int y)
    {
    	int ans = 1;
    	for (; y; y >>= 1, x = 1ll * x * x % Mod)
    		if (y & 1) ans = 1ll * ans * x % Mod;
    	return ans;
    }
    
    int n, m, a[N], c[N], fac[N], inv[N], g[N][N], fa[N], p[N], ans;
    int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
    
    void calc()
    {
    	int res = 1, tot = -m;
    	for (int i = 1; i <= a[m]; i++) if (c[i]) res = 1ll * res * inv[c[i]] % Mod;
    	for (int i = 1; i <= m; i++) res = 1ll * res * inv[a[i]] % Mod * fac[a[i] - 1] % Mod;
    	for (int i = 1; i <= m; i++) fa[i] = i, p[i] = 0;
    	for (int i = 1; i <= m; tot += (a[i] - 1) >> 1, i++) if (!(a[i] & 1)) ++p[i];
    	for (int i = 1; i <= m; i++)
    		for (int j = i + 1; j <= m; j++)
    		{
    			int d = g[a[i]][a[j]], x = (a[j] / d) & 1, y = (a[i] / d) & 1;
    			if (!x && !y) tot += d; else if (!y) p[i] += d; else if (!x) p[j] += d;
    			else tot += d, fa[find(i)] = find(j);
    		}
    	for (int i = 1; i <= m; i++) if (i != find(i)) p[find(i)] += p[i];
    	for (int i = 1; i <= m; i++) if (find(i) == i) tot += p[i] ? p[i] : 1;
    	ans = (ans + 1ll * res * fastpow(2, tot)) % Mod;
    }
    
    void dfs(int n, int d)
    {
    	if (n == 0) return calc();
    	for (int i = d; i <= n; i++) ++c[a[++m] = i], dfs(n - i, i), --m, --c[i];
    }
    
    int main()
    {
    	std::scanf("%d", &n), fac[0] = 1;
    	for (int i = 1; i <= n; i++) fac[i] = 1ll * fac[i - 1] * i % Mod;
    	inv[n] = fastpow(fac[n], Mod - 2);
    	for (int i = n; i; i--) inv[i - 1] = 1ll * inv[i] * i % Mod;
    	for (int i = 1; i <= n; i++) g[i][0] = g[0][i] = i;
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= i; j++) g[i][j] = g[j][i] = g[j][i % j];
    	dfs(n, 1), printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    如何分配资源和管理资源
    让Project把周六和周日也计算工期
    Project设置子任务
    pytest-配置文件
    pytest-fixture
    pytest-标记
    pytest-断言
    pytest-参数化
    pytest入门
    maven-插件
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/14453198.html
Copyright © 2020-2023  润新知