二项式定理
证明:
有 (n) 项 ((a + b)), 考虑对于最终 (a ^ k cdot b ^ {n - k}) 的贡献:
每一项选 (a) 或 (b) 然后相乘累加, 那么总共从 (n) 项里选 (k) 个 (a), 其余都选 (b)
常见带入:
二项式反演
下面这个式子的 (g(i)) 当做上面的 (g(i) cdot (-1) ^ i), 然后带入易得
证明第一个:
充要条件, 那么左边可推出右边, 右边可推出左边
由于这两个式子对称, 这里就偷懒只证明一个方向好了
例: 充分性: 左 (Rightarrow) 右
写在一个矩阵里比较直观(对于推导不是必要的), 观察右下角即为 (g_n) 与等式左边相同, 若要成立说明前面一片是 (0):
改成竖向求和
解释一下组合数: (i in j in n), 画一个集合图可得
然后最后面一段像是二项式定理, 把 (j) 换元成原来的 (j-i) 比较直观 (换元可以参考上面的矩阵的规律)
min-max 容斥
(max(S), min(S)) 分别表示 (S) 中的最大,最小元素
那么有这样两个式子:
证明:
第一个:
将元素从大到小排序 ({a_1, a_2, dots, a_n}), 当 (a_{x + 1}) 作为 (min(T)) 时,
他的系数是 (sum_{i=0}^x inom{x}{i} (-1) ^ {i + 1 - 1}) , 这是 ((-1 + 1) ^ x) 的二项式展开,
那么当 (x = 0) 时系数为 (1) 否则为 (0), 即 (max(S) = min({ a_1 }))
第二个:
从小到大排序, 其余一样
kth min-max 容斥
设 (max_{k}(S), min_{k}(S)) 分别为 (S) 中第 (k) 大/小 的元素
设 (max_k(S) = sum_{T subseteq S} F(|T|) min(T)), 求得这个系数 (F(|T|))
模仿上面的套路, 尝试用 (min(T)) 来表示 (max_{k}(S)) ((min_{k}(S)) 同理)
将元素从大到小排序 ({a_1, a_2, dots, a_n}), 当 (a_{x + 1}) 作为 (min(T)) 时,
使得当 (x = k - 1) 时系数为 (1) 否则为 (0)
根据上面的关系可得 (sum_{i=0}^x inom{x}{i} cdot F(i + 1) = [x = (k - 1)])
套用二项式反演 (f(i) = F(i + 1), g(i) = [i = (k - 1)])
则
所以
同理
例题
[HDU4336]Card Collector <min-max 容斥>
题意:
给出每种卡牌出现的概率(和为 1 , (n le 20)), 每买一次按上述概率抽卡, 求买到所有卡的期望次数
Sol:
设 (E(max(S))) 为买到 (S) 中剩下的最后一张卡的期望次数, 即答案(理解)
设 (E(min(S))) 为买到 (S) 中第一张卡的期望次数, 显然是 (frac{1}{sum_{i in T} p_i})
预处理 + 枚举子集
typedef double LDB;
int n;
const int MAXN = (1 << 20) + 10;
int cnt[MAXN], d[MAXN];
LDB p[30], mnp[MAXN];
int lowbit(int x) { return x & (-x); }
int main()
{
while (scanf("%d", &n) != EOF)
{
d[1] = 0;
for (int i = 1; i <= n; ++ i)
{
scanf("%lf", &p[i]);
d[1 << i] = i;
}
int S = (1 << n) - 1;
mnp[0] = cnt[0] = 0;
for (int i = 1; i <= S; ++ i)
{
mnp[i] = mnp[i & (i - 1)] + p[d[lowbit(i)] + 1];
cnt[i] = cnt[i & (i - 1)] + 1;
}
LDB ans = 0;
for (int T = S; T != 0; T = (T - 1) & S)
ans += (cnt[T] % 2 == 1 ? 1 : -1) * 1 / mnp[T];
printf("%lf
", ans);
}
return 0;
}
BZOJ4036: [HAOI2015]按位或
刚开始你有一个数字0,每一秒钟你会随机选择一个[0,2^n-1]的数字,与你手上的数字进行或(c++,c的|,pascal
的or)操作。选择数字i的概率是p[i]。保证0<=p[i]<=1,Σp[i]=1问期望多少秒后,你手上的数字变成2^n-1。
Sol:
先套用 min-max, (E(max(S))) 表示到达最后一个元素的期望, (E(min(S))) 到达第一个元素的期望
考虑 (E(min(S))) 怎么求, 当没有到达第一个元素的时候, 当前到达的集合和 (S) 是没有交集的, 这时需要或上一个与 (S) 有交集的数即可
于是发现既然没有到达之前都是无交集, 而且此时选择的数的概率仍然是这样, 那么无论何时概率都是 (sum_{t cap S
e emptyset} p[t]),
也就是说和上一题一样
在考虑如何快速求这个
尝试转化成 FWT 能用的形式, 设 sum[S] = (sum_{t cap S
e emptyset} p[t])
则
后面那段就是 FWT and 的通式, 一遍 FWT 求得
void FWT(double * a, int len)
{
// FWT(A) = merge(FWT(A0) + FWT(A1), FWT(A1)) ;
for (int mid = 1; mid < len; mid <<= 1)
for (int i = 0; i < len; i += (mid << 1))
for (int j = 0; j < mid; ++ j)
a[i + j] += a[i + j + mid];
}
int main()
{
n = in();
int S = (1 << n) - 1;
for (int i = 0; i <= S; ++ i) scanf("%lf", &p[i]), totsum += p[i];
for (int i = 1; i <= S; ++ i)
{
int sub = i & (i - 1);
cnt[i] = cnt[sub] + 1;
}
for (int i = 0; i <= S; ++ i)
if (i < S - i) swap(p[i], p[S - i]);
FWT(p, S + 1);
double ans = 0;
for (int T = S; T != 0; T = (T - 1) & S)
{
if (fabs(totsum - p[T]) <= 0) return printf("INF
"), 0;
ans += (cnt[T] % 2 == 1 ? 1 : -1) * 1.0 / (totsum - p[T]);
}
printf("%.6lf
", ans);
return 0;
}