yny组合计数
完工。

首先组合数的公式可以通过下降幂来表达:
加法公式:
由组合意义显然。
对称公式:
由组合意义显然。
吸收公式:
乘 \(k\) 使得 \(n,k\) 减 \(1\),乘 \(n-k\) 使得 \(n\) 减 \(1\),还有 \(n\) 的系数。
上指标反转:
上指标求和:
劳资不会证。
范德蒙德卷积(多用于数据结构题目):
组合意义是简单的。
[HAOI2008] 硬币购物
提示:基础容斥。
Sol
考虑暴力是多重背包。因为只有四个物品,所以直接容斥。
考虑全集为所有物品都可以选无限次,则减去不合法。
枚举每个物品是否超过限制,若一个物品超过限制,则它在选了 \(d_{i}+1\) 后,方案数变成完全背包。
于是我们预处理四个物品的完全背包方案数,然后容斥做即可。
Code
#include <bits/stdc++.h>
#define int long long
#define upp(a,x,y) for(int a=x;a<=y;a++)
#define dww(a,x,y) for(int a=y;a>=x;a--)
using namespace std;
const int N = 5e5+10;
int f[N], c[11], d[11], m, n;
int dfs(int u, int sum, int res) {
if (u == 5) {
if (res % 2) return -f[sum];
return f[sum];
}
int wow = 0;
if (sum >= d[u] * c[u]) wow += dfs(u + 1, (sum - d[u] * c[u]), res + 1);
wow += dfs(u + 1, sum, res);
return wow;
}
signed main() {
upp(i, 1, 4) cin >> c[i];
cin >> n;
f[0] = 1;
upp(i, 1, 4)
upp(j, c[i], 1e5)
f[j] += f[j - c[i]];
while (n--) {
upp(i, 1, 4) cin >> d[i],d[i]++;
cin >> m;
cout << dfs(1,m,0) << endl;
}
return 0;
}
[HNOI2011] 卡农
思路
首先不考虑无序这一块(顺序不同算同样方案),因为最后除以 \(m!\) 即可,原因是有序更好考虑。
首先考虑如果我们确定了 \(i-1\) 个片段,那么 \(i\) 片段也随之确定(通过偶数性质确定,但不保证合法,考虑容斥)。
此时的方案数为 \({2^{n}-1 \choose i-1} \times (i-1)!\)。
考虑不合法的情况有两种:
-
目前推出取空集,这时候前 \(i-1\) 个合法,应该将答案减去 \(ans_{i-1}\)。
-
与前面的集合重复,则去除那个集合,有 \(i-2\) 个合法,目前这个有 \(2^n-1-(i-2)\) 种取法,相同集合的位置有 \(i-1\) 种,答案减去 \(ans_{i-2} \times (2^n-i+1) \times (i-1)\)。
考虑到计算 \(ans_{i}\) 需要用到 \(ans_{i-1},ans_{i-2}\),递推即可。
别忘了最后除以 \(m!\)。
[ABC213G] Connectivity 2
思路
设 $S$ 为 $F=\{1,2,\dots,n\}$ 的一个子集。$f(S)$ 表示点集为 $S$ 的原图所有连通子图数量,$g(S)$ 表示点集为 $S$ 的原图所有子图的数量。此时有 \(ans_{k}=\sum_{\{1,k\} \subseteq S \subseteq F} f(S) \times g(C_{F}S)\),这个是 \(O(2^nn)\) 的。
问题转化为如何计算 \(f,g\)。
-
对于 \(g\),直接枚举点集,统计原图的边两个点都在点集里的个数为 \(cnt\),则方案数为 \(2^{cnt}\),这个是 \(O(2^nm)\)。
-
对于 \(f\),考虑容斥,\(f(S)=g(S)-\) 点集为 \(S\) 不连通的子图个数,考虑直接随便钦定一个点 \(v\in S\),再枚举 \(S\) 的联通子集 \(T\) 包含 \(v\)。
那么就有 \(f(S)=g(S)-\sum_{v \in T \subset S} f(T) \times g(C_ST)\),这个考虑枚举子集的子集是 \(O(3^n)\) 的。
二项式反演,设 \(f(n)\) 表示从 \(n\) 个元素构成特定结构的方案数,\(g(n)\) 表示从 \(n\) 个元素选 \(i(i\ge 0)\) 个元素构成特定结构的方案数。
显然有:
然后可以推出:
证明:
类似的,若 \(f(i)\) 表示 \(m\) 个元素中有严格 \(i\) 个元素满足条件的方案数,\(g(i)\) 表示 \(m\) 个元素中有至少 \(i\) 个元素满足条件的方案数。
我们显然有:
同理推得:
一般第二个更常用。
从例题开始
球的染色
有 \(n\) 个球,\(m\) 中颜色,现在要给所有球染色,使得每个颜色都被染到了,求方案数?
首先去除每个颜色都被染到了的限制,方案数显然为 \(m \times (m-1)^{n-1}\)。
然后用到了 \((i\le x)x\) 种颜色的方案数为 \(g(x)\),其实我们可以计算 \(g(x)=x \times (x-1)^{n-1}\)。
那么最后有 \(g(x)=\sum_{i=0}^{x} {x \choose i} f(i)\)。
反演后即可得到 \(f(x)\) 的表达式,求出 \(f(m)\) 即可。
这里使用了第一个公式,但是如果将每个颜色都被染到了转化为有 \(0\) 个颜色没用到,则会使用第二个公式。这表明了两个公式就是本质相同的。
注意这里我们不在乎颜色具体是什么,只在乎相对关系,所以不用组合数。
[SDOI2016] 排列计数
直接考虑没有限制,有 \(n!\) 种。
我们钦定 \(k\) 个位置 \(a_{i}=i\),则推出 \(g(k)={n \choose k} (n-k)!\)。
然后反演一下得到 \(f(m)\) 即可。这里用的是第二个公式。
BZOJ2839 集合计数
依然考虑没限制,我们有 \(2^{2^{n}}-1\) 种选法。
考虑钦定 \(x\) 个元素在并集里,那么可以得到 \(g(x)={n\choose x} (2^{2^{n-x}}-1)\)。
用第二个公式反演一下得到 \(f(k)\) 即可。
已经没有什么好害怕的了
记一个匹配为 \((x,y)\) 其中 \(x\) 表示糖果,\(y\) 表示药片。
若 \((x,y)(x>y)\) 的数量减去 \((x,y)(x<y)\) 的数量为 \(k\),那么有 \((x,y)(x>y)\) 的数量为 \(\frac{(n+k)}{2}\),只要能知道这个的方案数,我们就能解决原问题。
考虑钦定 \(k\) 个匹配满足 \((x,y)(x>y)\),怎么计算方案数呢?
考虑动态规划,\(f_{i,j}\) 表示前 \(i\) 个糖果,处理了 \(j\) 个钦定的方案数。
设 \(cnt_{i}=\sum_{j=1}^{n} [y_{j} < i]\)。
考虑这样实际上算重了,因为 \(cnt_{x_{i}}\) 可能有已经被算过的数。
怎么处理呢?我们希望不要算已经算过的数,这表示,我们目前的可选集合,一定会有一些是 \(f_{i-1,j-1}\) 这个状态没有的。
于是,考虑每次都是上一个集合的超集。这表明 \(x_{i}>x_{i-1}\)。于是我们按照 \(x\) 从小到大转移就行了。记得减去 \(i-1\) 这些之前已经匹配过的。
于是我们就愉快的把 \(g(k)\) 算出来了,使用 \(O(n^2)\) 的动态规划。利用第二个公式即可反演出 \(f(k)\),也就是真正严格的方案数。
然后我们就能解决 \((x,y)(x>y)\) 的数量严格为 \(i\) 的方案数了,答案就是 \(f(\frac{n+k}{2})\)。
希望我没讲错,因为我没写过代码,不过对了一下大概是这样的。
[JSOI2011] 分特产
首先不考虑每个同学都要得到东西的限制,我们每种物品考虑,那么,考虑 \(m\) 个同种物品,分给 \(n\) 个人,每个人可以得到 \(0\) 个物品的方案数,我们可以把这 \(m\) 个物品排成序列,然后考虑到每个人最低获得 \(0\) 个物品,我们就再加 \(n\) 个物品,这样变成 \(m+n\) 个物品,每个人必须获得物品的方案数。插板法可以知道为 \(m+n-1 \choose n-1\)。那么没限制方案数就是 \(\displaystyle \prod_{m} {m+n-1 \choose n-1}\)。然后所有同学都得到物品就是 \(0\) 个人没得到物品,考虑钦定 \(x\) 人没得物品,那么 \(\displaystyle g(x)={n\choose x} \prod_{m} {m+n-1-x \choose n-1-x}\)。公式二反演一下得到 \(f\),\(f(0)\) 就是答案。

浙公网安备 33010602011771号