计数
加法原理和乘法原理
P7140 [THUPC2021 初赛] 区间矩阵乘法
给定序列 \(\{a_n\}\),\(m\) 次询问,每次给定 \(d,p_1,p_2\),求:
\[\sum_{i=0}^{d-1} \sum_{j=0}^{d-1} \sum_{k=0}^{d-1} a_{p_1+di+j} a_{p_2+dj+k}. \]
令 \(\{s_n\}\) 为 \(a\) 的前缀和,\(f_d(p)=\sum_{i=0}^{d-1} a_{p+di}\)。
因为保证式子中的下标不会超过范围,所以 \(d\le \sqrt{n}\)。显然对于固定的 \(d\),\(f_d(*)\) 可以 \(\mathcal{O}(n)\) 预处理。每次询问都枚举和式中的 \(j\),然后计算即可。时间复杂度 \(\mathcal{O}((n+m)\sqrt{n})\)。
[AGC 023 E] Inversions
北大集训 2019 的题
给定正整数 \(d_1,d_2,\dots,d_n\),求有多少个序列 \(\{a_n\}\) 满足:
- \(1\le a_i\);
- \(a_i\mid d_i\);
- \(\prod a_i\le \prod \frac{d_i}{a_i}\)。
可以发现 \(\prod a_i\le \prod \frac{d_i}{a_i}\) 和 \(\prod a_i\ge \prod \frac{d_i}{a_i}\) 的方案一一对应。假如总方案数是 \(S\),\(\prod a_i=\prod \frac{d_i}{a_i}\) 的方案数是 \(C\),那么答案就是 \(\frac{S+C}{2}\)。计算 \(C\) 时,因为每个素因子是独立的,所以分别背包即可。
二项式系数
P4351 [CERC2015]Frightful Formula
考虑每个 \(F(i,1)\) 对答案的贡献:这显然是 \(\binom{2n-2-i}{n-2}a^{n-1}b^{n-i}F(i,1)\)。\(F(1,i)\) 同理。
再考虑在 \((i,j)\) 处加上的 \(c\) 的贡献:\(c\times a^{n-i}b^{n-j}\binom{2n-i-j}{n-i}\)。这些 \(c\) 的总贡献是 \(\sum_{i=2}^n \sum_{j=2}^n c\times a^{n-i}b^{n-j}\binom{2n-i-j}{n-i}\),令 \((i,j)\gets (n-i,n-j)\) 得
令 \(f(k)=\sum_{j=0}^{n-2} b^j\binom{k+j}{j}\),则化为
考虑 \(f(k)\) 如何递推(这种递推一般会用到加法恒等式):
移项得
注意特判 \(b=1\) 的情况。于是就做完了。
P3726 [AHOI2017/HNOI2017] 抛硬币
直接硬推:
分类讨论,假如 \(a+b\) 是偶数,令 \(m=\frac{a+b}{2}\),根据二项式系数的对称性得:
假如 \(a+b\) 是奇数,令 \(m=\lfloor\frac{a+b}{2}\rfloor\):
因为 \(0<a-b\le 10^4\),所以剩下的这些组合数可以硬算。
exLucas,狗都不写!
一个技巧:假如要表达 \(i>j\),那么可以把 \(i\) 拆成 \(j+k\),其中 \(k\) 是正整数。
Kummer 定理
对于正整数 \(n,m\) 和质数 \(p\),\(\frac{(n+m)!}{n!m!}\) 中 \(p\) 的幂次等于在 \(p\) 进制下计算 \(n+m\) 时进位的次数。
证明似乎直接展开,然后利用 \(n\bmod p=n-p\lfloor\frac{n}{p}\rfloor\) 就行。
容斥原理
记号
记 \([n]=\{1,2,\dots,n\}\)。
题 \(1\)
设字符集为小写英文字母,给定 \(n\) 个带有通配符的字符串 \(s_1,s_2,\dots,s_n\),通配符位置可以填任意字母。求所有填写方案中,这些串构成的字典树的节点个数之和。
设 \(S_i\) 为 \(s_i\) 的所有可能的前缀的集合,答案就是 \(\lvert \bigcup_{i=1}^n S_i \rvert\)。容斥后变成了对于任意 \(T\subset [n]\),求 \((-1)^{|T|-1}\times |\bigcap_{x\in T} S_x|\),而后面那个东西就是 \(T\) 中所有串的可能的 LCP 的长度之和,枚举 LCP 长度然后直接计算即可。
时间复杂度 \(\mathcal{O}(2^n\times \sum_{i=1}^n |s_i|)\)。
P4515 [COCI2009-2010#6] XOR
设 \(t_i\) 为第 \(i\) 个三角形覆盖的区域。首先,答案肯定是形如
的,其中 \(f\) 是一个神秘的函数。对于一个区域,设这 \(n\) 个三角形里有 \(k\) 个完全包含它,那么 \(f\) 需要满足
不妨设 \(f(0)=0\),那么上式的求和可以改成 \(\sum_{i=0}^k\)。
应用二项式反演得:
可以验证 \(f(0)\) 在此时也等于 \(0\)。分类讨论 \(i\) 的奇偶性,假如 \(i\) 是奇数,那么 \((-1)^{i-j}\) 在 \(j\) 是奇数的时候是 \(1\)。也就是 \(f(i)=\sum_{j=0}^i \binom{i}{j}[2\nmid j]=2^{i-1}\)。假如 \(i\) 是偶数,同理得 \(f(i)=-2^{i-1}\)。
合起来就能得到 \(\forall i,f(i)=(-2)^{i-1}\)。若干个三角形的面积交是好算的,所以就做完了,\(\mathcal{O}(n2^n)\)。
还有 \(\mathcal{O}(n^3)\) 的做法,但我现在不会。
AT2062 [AGC005D] ~K Perm Counting
将排列转化成二分图也太妙了。
容斥,设 \(F_i\) 为钦定 \(i\) 个位置使得它们满足 \(|p_x-x|=k\),且其他位置不限制的方案数。那么答案就是 \(\sum_{i=0}^n (-1)^i F_i(n-i)!\)。
考虑一个排列到匹配的映射:假如建立一个左部、右部都有 \(n\) 个点的二分图,在其中连一些边,那么这个二分图的完美匹配与合法的排列一一对应。
所以,设 \(1\dots n\) 是左部点,\((n+1)\dots (2n)\) 是右部点,我们对于任意 \(i\) 都在 \((i,i+k+n)\) 和 \((i,i-k+n)\) 之间连边(如果 \(i+k+n,i-k+n\) 合法)。于是 \(F_i\) 就是这张二分图上大小为 \(i\) 的匹配个数。
因为每个点的度数最多只有 \(2\),所以此二分图实际上是由若干条链组成的。在一条边数为 \(a\) 的链上选择不相交的 \(b\) 条边的方案数是 \(\binom{a-b+1}{b}\),用背包将所有链的答案合并起来即可。
AT4352 [ARC101C] Ribbons on Tree
我居然想出来了。
容斥。设 \(S_i\) 为第 \(i\) 条边没有被覆盖的配对方法的集合,那么答案就是
对于一个大小为 \(k\) 的连通块,将它的点两两配对的方案数是 \((k-1)!!\),于是得到了一个 \(\mathcal{O}(n2^n)\) 的做法。
考虑将容斥系数放在 dp 里:设 \(f_{u,i}\) 表示以 \(u\) 为根的子树内,最顶上那个还未完全确定的连通块中,点数为 \(i\) 的容斥系数之和。这里的容斥系数不包括那个还未完全确定的连通块。
那么,\(\forall i\ge 1\),求 \(f_{u,i}\) 只需要做一次树形背包。对于 \(i=0\) 的情况,它表示 \((u,\mathrm{fa}_u)\) 之间的边不会被覆盖,所以新增了一个已经确定的连通块,此时的转移是:
前面那个负号是容斥系数。树形背包需要上下界优化,\(\mathcal{O}(n^2)\)。
二项式反演
二项式反演有若干种形式:
常见用法是将“恰好”转化为“钦定”。
P6596 How Many of Them
设 \(a_i\) 是 \(n\) 个点的恰好有 \(i\) 条割边的无向连通图数量,\(b_i\) 是 \(n\) 个点的无向连通图,在其中钦定 \(i\) 条割边的方案数,如果算出所有的 \(b_i\),就能通过二项式反演算出所有 \(a_i\),进而算出答案。
考虑现在钦定了 \(k\) 条割边。这 \(k\) 条割边将整张图划分成了 \(k+1\) 个连通块,若将每个连通块都缩成一个点,会形成一棵树。因此,如果已经确定了这 \(k+1\) 个连通块内部的结构,设它们的大小是 \(s_1,s_2,\dots,s_{k+1}\),此时钦定 \(k\) 条割边的方案数是
考虑内部结构如何计数。设 \(f_i\) 表示 \(i\) 个点的无向连通图的个数,设
钦定 \(k\) 条割边的方案数就是
暴力预处理 \(F^1,F^2,\dots,F^n\) 即可,时间复杂度 \(O(n^3)\)。
P6478 [NOI Online #2 提高组] 游戏
考虑对于每个 \(k\),算出钦定 \(k\) 对选择的点具有祖先后代关系的方案数。设 \(f_{u,i}\) 表示仅考虑 \(u\) 的子树,在其中选择 \(i\) 对具有祖先后代关系的点的方案数。转移有两种:一种是不选择 \(u\),直接树形背包合并,另一种是考虑 \(u\) 这个点和另外一个子树内的点配对,此时我们能根据状态算出有多少个点能够与 \(u\) 配对。
DP 完成后,再考虑那些未选择的点的配对方式,显然有 \((\frac{n}{2}-k)!\) 种。再进行一次二项式反演,即可算出答案。时间复杂度 \(O(n^2)\)。
CF1228E Another Filling the Grid
不难想到钦定有 \(i\) 行和 \(j\) 列的最小值不是 \(1\)。设这样的方案数是 \(f(i,j)\),设 \(c=(i+j)n-ij\),有:
如果想要算出答案,实际上要做一个二维的二项式反演。而这与一维的其实没有什么区别:设 \(g(i,j)\) 表示有恰好 \(i\) 行和钦定的 \(j\) 列的最小值不是 \(1\),\(h(i,j)\) 表示有恰好 \(i\) 行和 \(j\) 列的最小值不是 \(1\),那么 \(f\to g\) 的转化需要对第一维做二项式反演,\(g\to h\) 的转化需要对第二维做二项式反演。合起来,可以得到:
答案即为 \(h(0,0)\),时间复杂度 \(O(n^2)\)。