• 容斥


    二项式定理

    [(a + b) ^ n = sum_{i=0}^n inom{n}{i} cdot a ^ {i} cdot b ^ {n - i} ]

    证明:

    (n)((a + b)), 考虑对于最终 (a ^ k cdot b ^ {n - k}) 的贡献:
    每一项选 (a)(b) 然后相乘累加, 那么总共从 (n) 项里选 (k)(a), 其余都选 (b)

    常见带入:

    [(x + 1) ^ n = sum_{i=0}^n inom{n}{i} x ^ i ]

    [(1 + x) ^ n = sum_{i=0}^n inom{n}{i} x ^ {n - i} ]

    [(x + 1) ^ n = sum_{i=0}^n inom{n}{n - i} x ^ {n - i} ]

    二项式反演

    [f_n = sum_{i=0}^n (-1)^i {n choose i} g_i Leftrightarrow g_n = sum_{i=0}^n (-1)^i {n choose i} f_i ]

    下面这个式子的 (g(i)) 当做上面的 (g(i) cdot (-1) ^ i), 然后带入易得

    [f_n = sum_{i=0}^n {n choose i} g_i Leftrightarrow g_n = sum_{i=0}^n (-1)^{n-i} {n choose i} f_i ]

    证明第一个:

    充要条件, 那么左边可推出右边, 右边可推出左边

    由于这两个式子对称, 这里就偷懒只证明一个方向好了
    例: 充分性: 左 (Rightarrow)

    [egin{aligned} g_n & = sum_{i=0}^n (-1)^i inom{n}{i} sum_{j=0}^i (-1)^j inom{i}{j} g_j \ & = sum_{i=0}^n sum_{j=0}^i (-1)^{i + j} inom{n}{i} inom{i}{j} g_j end{aligned} ]

    写在一个矩阵里比较直观(对于推导不是必要的), 观察右下角即为 (g_n) 与等式左边相同, 若要成立说明前面一片是 (0):

    [egin{bmatrix} & inom{n}{0}inom{0}{0} g_0 \ & -inom{n}{1}inom{1}{0} g_0 & inom{n}{1}inom{1}{1} g_1 \ & inom{n}{2}inom{2}{0} g_0 & -inom{n}{2}inom{2}{1} g_1 & inom{n}{2}inom{2}{2} g_2\ & vdots & vdots & ddots & \ & (-1)^ninom{n}{n}inom{n}{0} g_0 & (-1)^{n+1}inom{n}{n}inom{n}{1} g_1 & dots & (-1)^{2n}inom{n}{n}inom{n}{n} g_n\ end{bmatrix} ]

    改成竖向求和

    [egin{aligned} g_n & = sum_{i=0}^n g_i sum_{j=i}^n inom{n}{i} inom{i}{j} (-1)^{i+j}\ & = sum_{i=0}^n g_i inom{n}{j} sum_{j=i}^n inom{n-i}{j-i} (-1) ^ {i + j} end{aligned} ]

    解释一下组合数: (i in j in n), 画一个集合图可得
    然后最后面一段像是二项式定理, 把 (j) 换元成原来的 (j-i) 比较直观 (换元可以参考上面的矩阵的规律)

    [egin{aligned} g_n & = sum_{i=0}^n g_i inom{n}{j} sum_{j=0}^{n - i} inom{n-i}{j} (-1) ^ {j} \ & = sum_{i=0}^n g_i inom{n}{j} (-1 + 1) ^ {n-i} \ & = sum_{i=0}^n g_i inom{n}{j} [i = n] \ & = g_n end{aligned} ]

    min-max 容斥

    (max(S), min(S)) 分别表示 (S) 中的最大,最小元素

    那么有这样两个式子:

    [egin{cases} max(S) & = sum_{T subseteq S} (-1) ^ {|T| - 1} min(T) \ min(T) & = sum_{T subseteq S} (-1) ^ {|T| - 1} max(T) \ end{cases} ]

    证明:

    第一个:

    将元素从大到小排序 ({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)])

    [sum_{i=0}^x inom{x}{i} cdot F(i + 1) = [x = (k - 1)] Leftrightarrow F(x + 1) = sum_{i=0}^x (-1) ^ {x - i} cdot inom{x}{i} [i = (k - 1)] ]

    [F(x + 1) = (-1) ^ {x - (k - 1)} cdot inom{x}{k - 1} ]

    所以

    [max_{k}(S) = sum_{T subseteq S} (-1) ^ {|T| - k} inom{|T| - 1}{k - 1} min(T) ]

    同理

    [min_{k}(S) = sum_{T subseteq S} (-1) ^ {|T| - k} inom{|T| - 1}{k - 1} max(T) ]

    例题

    [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})

    [E(max(S)) = sum_{T subseteq S} (-1) ^ {|T| - 1} min(T) ]

    预处理 + 枚举子集

    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]),
    也就是说和上一题一样

    在考虑如何快速求这个

    [E(min(S)) = sum_{t cap S e emptyset} p[t] ]

    尝试转化成 FWT 能用的形式, 设 sum[S] = (sum_{t cap S e emptyset} p[t])

    [egin{aligned} sum[S] & = totsum - sum_{t cap S = emptyset} p[t] \ & = totsum - sum_{complement t cap S = S} p[t] end{aligned} ]

    后面那段就是 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;
    }
    
  • 相关阅读:
    [LeetCode] 273. Integer to English Words 整数转为英文单词
    What happens when you type an URL in the browser and press enter?
    HTTP Status Code
    What's binary search?
    [Http] Difference between POST and GET?
    [LeetCode] 53. Maximum Subarray 最大子数组
    [LeetCode] 621. Task Scheduler 任务调度
    C# web项目添加*.ashx文件后报错处理
    Web项目和Windows应用程序的配置文件
    C#中web项目使用log4net日志
  • 原文地址:https://www.cnblogs.com/Kuonji/p/12052656.html
Copyright © 2020-2023  润新知