20250610 闲话
某题转化后得到:
初始有 \(n\) 个孤立点。\(n - 1\) 次操作,每次合并两个连通块。每次操作之后询问:
在每个连通块中至多取 \(1\) 个点,总共恰好取 \(m\) 个点,求取法的方案数。
\(2 \le n \le 10^5, 2\le m \le 10\)。答案对 \(998244353\) 取模。
设当前有 \(k\) 个连通块,第 \(i\) 个大小为 \(s_i\),相当于动态求 \([x^m]\prod_{i=1}^k(1+s_ix)\)。
直接在线段树上插入或删除,pushup 暴力卷积合并信息,\(O(nm^2\log n)\)。
容易 \(O(m)\) 加入一个 \((1+ax)\),使用线段树分治可以 \(O(nm\log n)\)。
\[f'(x) = f(x) + s_if(x-1)
\]
观察发现删去一个 \((1+ax)\) 可以把加入的过程逆过来做(相当于交换插入顺序然后撤销),也是 \(O(m)\) 的,于是 \(O(nm)\)。前面两种做法都蠢了。
upd 20250611:
事实上:
\[\frac{1}{1+ax} = \sum_{i=0}^{\infty} (-1)^i a^i x^i
\]
一个系数为 \(a\) 的 0-1 背包物品的逆,是一个系数为 \(-a\),重量相同的完全背包物品。
void ins(LL x) { for (int i = m; i; --i) Fplus(f[i], f[i - 1] * x % mod); }
void ers(LL x) { for (int i = 1; i <= m; ++i) Fminus(f[i], f[i - 1] * x % mod); }

浙公网安备 33010602011771号