Atcoder abc284

https://atcoder.jp/contests/abc284/tasks

Ex - Count Unlabeled Graphs

按照下面步骤生成图

选 简单,无向,n个无标签点 的图

给每个点 写 <= k的数, (1~k每个都至少出现一次

找方案数 mod p(质数 1e8~1e9)

范围

k <= n <= 30

我的思路

无标签的图 和 有标签的图之间 如何进行 重复统计的转化 ???

考虑按照连通块来划分

连通块大小 和 同联通块大小的选择个数

f[s] = 每个连通块大小为s 的 染色方案数 的生成方程 = a[s] x^s + a[2s] x^2s + a[3s] x^3s …

为了统计 g[s] = 加上外部贡献的选择倍数 = a[s]/s! x^s + a[2s]/(2s)! x^2s + a[3s]/(3s)! x^3s …

这样 ans = [x^n] n! g[1] * g[2] * g[3] * ... * g[n]


那么问题来了, 如何计算f[i]

h[i] = 1个大小为i的联通块的染色方案数

a[i] = h[i], 直接染色

a[2i] = binom(2i,i-1) h[i] * h[i], 确定1在地一个块

a[3i] = binom(3i,i-1) * binom(2i,i-1) h[i]^3, 确定1在地一个块, 不在第一个块中最小的在第二个块


那么如何计算h[i]

count[形状] = 一个形状的染色方案数

h[i] = sum count[形状i]

形状不同, 染色后一定不同, 但是相同形状 染色后可能相同,


如何判断两个形状不同, 如何枚举形状, 每个形状如何计算染色方案??????????????????????????

并不会


能想到一些必要条件, 但没啥充分条件, 比如 点i连的点和相同,且度相同

题解

上面考虑的过程还是差了一个 正好k个颜色


考虑 <= k个颜色的方案, 再算正好k = sum binom(k,i) (-1)^{k-i} (<=i的方案) 容斥一下


然后 无标签图难以处理, 先考虑带标签图

$S_n=$ n的排列的集合

子问题: 多少个n点带标签图, 点值在[1..k], 如果 一个图 通过某个$p\in S_n$ 映射了值和边以后 得到另一个图,认为它们相等

$G$ 所有有标签的图, (点上无值)


对于有标签的图$g\in G$, $p(g)$ 表示 $g$的 点经过排列$p$映射后的图

$A(g) = $ G 中能通过 排列映射得到g 的 图的数量

$B(g) = $ 就是g通过 排列映射后 还是g的 排列数

那么有 $A(g)B(g) = N!$

右侧就是 $g$ 和所有排列作用

而注意到 任何图 经过$p$ 变换后 它的”形状”没有变, 所以 B(g) == B(p(g))

所以 A(g) 对应的每个图 都是 B(g) 个变化, 且都能通过某个p(g)得到

根据一一映射得证


例子: 图 g=(1-2,3), 那么A(g) = 3, B(g) = 2

A(g): 的3个图 (1-2,3),(1-3,2),(1,2-3),

B(g): 的2个排列 (1,2,3),(2,1,3)

3 * 2 = 6 = 3!


Pólya enumeration theorem (applied to this problem)

令 G’ 为(从G中去掉标签后的无向图)的集合.

那么有 $|G’| = \frac{\sum_{p \in S_n} \vert \lbrace g \vert g \in G, p(g) = g \rbrace \vert}{N!}$

证明这个等式相等:

G中每个生成 无标签的图 只会在G’ 中出现一次, 对于无标签图 g’, 有 A(g) 个图 在g中和它对应(通过去掉标签)

例如 o-o,o1-2,3,1-3,2,1,2-3

$|G’| = \sum_{g \in G} \frac{1}{A(g)} $

$= \frac{1}{N!} \sum_{g \in G} \frac{N!}{A(g)} $

$= \frac{1}{N!} \sum_{g \in G} B(g)$

$= \frac{1}{N!} \sum_{g \in G} \vert \lbrace p \vert p \in S_n, p(g) = g \rbrace \vert$

$= \frac{1}{N!} \sum_{g \in G} \sum_{p \in S_n} \lbrack p(g) = g \rbrack$

$= \frac{1}{N!} \sum_{p \in S_n} \sum_{g \in G} \lbrack p(g) = g \rbrack$

$= \frac{1}{N!} \sum_{p \in S_n} \vert \lbrace g \vert g \in G, p(g) = g \rbrace \vert$

这样, 我们可以 消除 “isomorphic up to labels,” 的情况, 简单的做objects统计, 像这个问题, 一个组合问题 需要 identify graphs up to permutations 可以通过 不动点 的 平均值 解决. 这样的技巧 在cycle或cube中的组合问题中也使用了,如 ABC198F. (Pólya’s theorem 同样成立, 当用在 排列的集合 上时.)

证明: $g’$ 表示 $g$ 去掉标签后的图, $t(g’)$ 表示给这个无向图每个点放值的方案数

$ans = \sum_{g’\in G’} t(g’) = \sum_{g \in G} \frac{1}{A(g)} t(g’) $

$= \frac{1}{N!} \sum_{g \in G} \frac{N!}{A(g)} t(g’) $

$= \frac{1}{N!} \sum_{g \in G} B(g) t(g’)$

$= \frac{1}{N!} \sum_{g \in G} \vert \lbrace p \vert p \in S_n, p(g) = g \rbrace \vert t(g’)$

$= \frac{1}{N!} \sum_{g \in G} \sum_{p \in S_n} \lbrack p(g) = g \rbrack t(g’)$

$= \frac{1}{N!} \sum_{p \in S_n} \sum_{g \in G} \lbrack p(g) = g \rbrack t(g’)$

这里 就变成按一个具体的有标签的$g$, 来统计, 也就是说 如果 $t(g_1’)$和$t(g_2’)$ 的到相同结果, 都会被统计, 只是 同一个$g$ 去标签 再给点赋值 得到的重复的 只统计一次,

显然 如果有一个g’中的点赋值方案, 至少有一个g中的点赋值方案对应, 问题是 是否存在g中两个点赋值方案 对应到 同一个g’的点赋值方案,

而这里保证这点的反而是这个p, 因为在p的关系下, “有标签”的作用 其实变成了 对无标签的图形的唯一标识!!!??? 啊就很神奇,

这样, 对于每个给定的p, 计算 有标签图 $p(g) = g$ 的个数, 并求平均值(就是乘上1/n!). 排列可以表示成 环的大小,$(c_1, c_2, \dots, c_m)$, 这样的图的数量为

$K^m \times 2^{\sum_{i=1}^m \left(\lfloor c_i/2\rfloor + \sum_{j=1}^{i-1} \gcd(c_i, c_j)\right) }$

在排列的同一个环上的数都一样, 所以是K^m, 接下来是有自由度的边, 如果 环i中pi 和 环j中pj相连, 那么 环i中的 (pi+w)%len(环i) 和 (pj+w)%len(环j)相连, 所以一个环和前面的环相连的自由边 是 $\gcd(c_i,c_j)$, 可以连或不然后就是环内自己, 考虑环内(pi) 和(pi+w)连, 那么w的的范围是$\lfloor \frac{c_i}{2} \rfloor$

$= \frac{1}{N!} \sum_c \sum_{\mathrm{cycle}(p)= c} \sum_{g \in G} \lbrack p(g) = g \rbrack t(g’)$

和abc226f 一样, 枚举n的所有分割(每次让当前最小的在新的环中), 然后加起来(按环表示对应的排列数) $\times$ (上面的值). 可以 O(p(N) poly(N)) 算出来, p(n) 是 n-th 分割数,

按环表示对应的排列数, 考虑 大小s有x个, 在选值时 有 binom{n}{s,s,…,s} 种, 然后它们之间每个方案中每组s用最小的表示, 所以轮换还有 m!, 所以 需要 1/(m!s^m)

代码

https://atcoder.jp/contests/abc284/submissions/38141401

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <bits/stdc++.h>
#include <atcoder/modint>
using mint = atcoder::modint;
using namespace std;

#define rep(i,a,n) for (int i=a;i<(int)n;i++)
#define per(i,a,n) for (int i=n;i-->(int)a;)
int read(){int r;scanf("%d",&r);return r;}
const int T=100;
vector<mint> fac;
vector<mint> ifac;
mint binom(int n,int m){return (n<m or m<0)?0:(fac[n] * ifac[n-m] * ifac[m]);}

// 对n 拆分, 上一个拆分的大小为last, 这次比last大
mint dfs(int n,int K, int last, vector<pair<int, int>> &v) {
if (n == 0) {
mint ans = 1;
rep(i,0,size(v)){
auto [cyc1, num1] = v[i]; // 环大小, 个数
ans /= fac[num1] * (mint{cyc1}.pow(num1)); // 清除轮换等价
ans *= mint{K}.pow(num1); // K^m = K^{sum num}
ans *= mint{2}.pow(cyc1 / 2 * num1 + cyc1 * num1 * (num1 - 1) / 2); // c[i]/2 + sum gcd(num1,num1)
rep(j,0,i) {
auto [cyc2, num2] = v[j];
ans *= mint{2}.pow(gcd(cyc1, cyc2) * num1 * num2);
}
}
return ans;
}else{
mint ans = 0;
rep(nxt,last+1,n+1) for (int i = 1; nxt * i <= n; i++) { // 拆分 i个 nxt大小的环
v.push_back({nxt, i});
ans += dfs(n-nxt*i, K, nxt, v);
v.pop_back();
}
return ans;
}
}

mint f(int n,int k){ // n点 值[1..k] 方案数
vector<pair<int, int>> v; // {环大小, 个数}
return dfs(n,k,0,v);
}

int main() {
int n=read();
int K=read();
mint::set_mod(read());
fac.assign(T+1,1);
rep(i,1,T+1) fac[i] = fac[i - 1] * i;
ifac.resize(T+1);
ifac[T] = fac[T].inv();
per(i,0,T) ifac[i] = ifac[i + 1] * (i + 1);

mint ans = 0;
rep(k,1,K+1) ans+=f(n,k)*binom(K, k)*(((K-k)&1)?-1:1);//容斥ans[==K]=sum binom(K,i)(-1)^{K-i}f(<=i)
printf("%d\n",ans.val());
return 0;
}

总结

Ex

有想过 标签的图 和 无标签的图的 转化, 但没想出具体怎么搞

学了一手 A(g)B(g) = N!

这个 无标记图个数 = avg (每个排列 的 不动图 个数) 怎么就能直接知道 无标记点有值个数 = avg(每个排列 的 点有值不动图 个数) ????????????????????????????????????????

然后就是与无标签图和有标签图有关的 polya 定理

$\sum_{g’\in G’} t(g’) = \frac{1}{N!} \sum_{p \in S_n} \sum_{g \in G} \lbrack p(g) = g \rbrack t((g)’)$

然后这里的 p(g)=g 的作用下 其实是让g在g’中唯一标识, 所以同个g的 不同点上赋值 对应的g’的点上赋值一定不同

参考

官方题解

abc 226f

luogu p4727