zoukankan      html  css  js  c++  java
  • [容斥原理与莫比乌斯反演][学习笔记]

    容斥原理 与 莫比乌斯反演

    今天(2.23.2017)翻了一下《组合数学》前6章,发现我之前一定是学了假的莫比乌斯反演,于是来新写一篇



    # 容斥原理

    定理

    集合(S)中不具有性质(P_i:1le i le m)的元素个数:
    (A_i)为具有性质(P_i)的集合

    ( |S| - sum{|A_i|} + sum{A_i igcap A_j} -sum{A_i igcap A_j igcap A_k}+...+ (-1)^msum{A_1 igcap A_2 igcap ... igcap A_m} )



    项数:$ inom{m}{0} + inom{m}{1} + ... + inom{m}{m} = 2^m$


    (Proof.)
    (1.) 没有任何一条性质的元素贡献为(1)
    (2.)(n)条性质的元素,在(n)个集合(A_i)中出现,贡献为(inom{n}{0} - inom{n}{1} + inom{n}{2} + ... + (-1)^ninom{n}{n} = 0)


    关于第二条的证明:
    根据二项式定理,((1-1)^n =0 : n eq 0)
    或者考虑前(n-1)个元素都可以选或不选,最后一个元素为了保证选的元素个数的奇偶性只有一种选择,所以奇数个元素的子集数量和偶数个元素的子集数量相等

    实质

    [sumlimits_{i=0}^{n}(-1)^iinom{n}{i} = [n=0] ]

    也就是上面的证明过程



    错排

    满足(i_j eq j)的排列数

    [D_n = n!sumlimits_{i=0}^{n}frac{(-1)^i}{i!} ]

    (inom{n}{i}(n-i)! = frac{n!}{i!}) 就是(ge i)个位置不是错排的方案数,应用容斥原理即可

    还有一个递推关系
    (D_n = nD_{n-1} + (-1)^n)


    总结

    在统计一类问题时,应用容斥原理可以有效的弱化限制条件
    有一种统计恰好k个的问题,限制很强,通常弱化为先拿出k个,剩下的任意
    这时候容斥的形式通常是

    [= ge k个 - ge k+1个 + ge k+2个 ... ]

    这时候我们在统计(ge j:k le j le n)时,如果依靠了枚举哪j个或者类似的DP,可能会过多的统计,比如一个(k+i)个的方案在这时候会被考虑(inom{k+i}{k})次,所以需要乘上一个组合数系数(inom{k+i}{k})

    有的问题是恰好没有之类的,这时候(inom{i}{0}=1)所以不用考虑这个东西;同理,恰好n个也不用考虑。

    update 2017.5.3:貌似这个东西也不是这么回事儿...感觉还与二项式反演有关...还是具体问题具体分析吧


    **update 2017.5.15**

    今天闲来无事证明了一下,这玩意应该是普遍成立的!

    我们考虑一个恰好(x:x ge k)个的方案被统计的次数:

    [egin{align} &= sum_{i=k}^x (-1)^{i-k}inom{i}{k} inom{x}{i} \ &= inom{x}{k} sum_{i=k}^x (-1)^{i-k} inom{x-k}{x-i}\ &= inom{x}{k} sum_{j=0}^{x-k} inom{x-k}{j} \ &= [x==k] end{align} ]

    哈哈O(∩_∩)O


    莫比乌斯反演 Mobius Inversion

    说明

    容斥原理是莫比乌斯反演在有限偏序集上的一个实例
    莫比乌斯反演应用在一类二变量函数,偏序关系到实数的映射
    《组合数学》上讨论了好多任意有限偏序集的莫比乌斯反演,还有偏序集的直积,我已经看蒙了
    所以直接说莫比乌斯反演在数论上的经典形式吧,反正不是整除关系也不会考



    积性函数

    定义

    定义域为正整数集的函称为数论函数

    满足(f(ab) = f(a)f(b) : gcd(a,b) =1)的数论函数称为积性函数

    完全积性函数对ab没有互质限制


    积性函数:(varphi(n), mu(n))

    完全积性函数:

    • 单位函数(epsilon(n)=[n=1]),

    • 恒等函数(id(n)=n)

    • 常函数(1(n)=1)


    狄利克雷卷积

    [(f*g)(n) = sumlimits_{d|n}f(d)g(frac{n}{d}) ]

    满足交换律结合律对加法的分配律,单位元 (epsilon)


    ###性质 1. 积性函数的**点积**和**狄利克雷卷积**也是积性函数 2. 一个函数的约数和可以卷上$1$,如约数个数$d(n)=(1*1)(n)$,约数和 $sigma(n) = (1*id)(n)$

    计算

    1. 可以(O(nlogn))预处理,无脑枚举所有数的倍数
    2. 线性筛
    • i=1, i是质数和i%p[j]!=0的情况很好求
    • 对于i%p[j] == 0,可以通过分析增加一个最小质因子后的变化,或者直接考虑(f(p^k))怎么求,反正积性函数不同质因子都是互质乘起来就行了不影响
    • 也可以筛出最小质因子的次数,分解成(f(n) = f(p^k) f(frac{n}{p^k})),对于(f(p^k))考虑如何计算,带有约数和的可以考虑展开
    • 一些非积性函数也可以通过分析函数的性质也可以用线性筛来求
      例:欧拉函数可以直接根据公式得到如何处理 (varphi(n) = nprodfrac{p_i-1}{p_i} = prod{(p_i-1)*p_i^{e_i-1}})
    void sieve() {
    	varphi[1] = 1;
    	for(int i=2; i<=n; i++) {
    		if(!notp[i]) p[++p[0]] = i, varphi[i] = i-1;
    		for(int j=1; j<=p[0] && i*p[j]<=n; j++) {
    			notp[i*p[j]] = 1;
    			if(i%p[j] == 0) {
    				varphi[i*p[j]] = varphi[i] * p[j];
    				break;
    			}
    			varphi[i*p[j]] = varphi[i] * (p[j]-1);
    		}
    	}
    	for(int i=1; i<=n; i++) varphi[i] += varphi[i-1];
    }
    



    ##莫比乌斯函数 $$ mu(1) = 1\ mu(n) = (-1)^i quad n 是i个质数之积 \ mu(n) = 0 quad p^2 | n, p > 1 $$

    [ mu * 1 = epsilon, 即 sumlimits_{d|n}mu(d) = [n=1]$$。 </br> $Proof. $设$n$有$k$种质因子, ]

    sumlimits_{d|n}mu(d) = sum_{i=0}^{k}(-1)^iinom{k}{i}

    [和上面的容斥原理证明类似,应用二项式定理 </br> ## 欧拉函数 ]

    varphi(n) = sum_{i=1}^n [(n,i)=1]
    varphi(n) = prod p^{c-1}(p-1)

    [ </br> 1. $$ varphi * 1 = id 即 n = sumlimits_{d|n}varphi(d) , 反演后 mu * id = varphi ]

    (Proof.) 考虑列出所有分子(frac{i}{n})一共(n)

    1. [sum_{i=1}^n [(n,i)=1]*i = frac{[n=1] + n*varphi(n)}{2} ]

      (Proof.) ((n,i)=(n, n-i)),除了1和2 互质成对出现,和为n


    莫比乌斯反演

    [g(n) = sum_{d|n}f(d) \ f(n) = sum_{d|n}mu(d)g(frac{n}{d}) ]

    (g = f*1 ightarrow f = g * mu)


    (Proof.)
    两边都卷上(mu * 1)
    其他证明方法还有很多,我写这个是因为这个短


    另一种形式

    [g(n) = sum_{n|d}f(n) \ f(n) = sum_{n|d}mu(d)g(frac{d}{n}) ]


    ***

    应用

    感觉还是直接使用这个式子代换比较简单,构造函数再进行反演好像并不好想

    [sumlimits_{d|n}mu(d) = [n=1] ]

    有一些常见技巧:

    • 枚举gcd取值
    • 交换枚举倍数与约数
    • 用莫比乌斯函数求和替换
    • 改写求和指标
    • 最后通常需要得到一个可以整除分块的形式,处理一个函数的前缀和后可以在根号复杂度内解决一次询问

    一般的题目推导起来挺套路的,通常都是枚举两个变量求一个带着gcd的东西(有的题目需要你自己把式子变形把gcd放进去),套路推♂倒之后都变成了整除分块,然后重点就在如何通过线性筛求函数了

    栗子

    [egin{align*} sumlimits_{i=1}^n sum_{j=1}^m gcd(i,j) &= sum_{d=1}^n d sum_{i=1}^n sum_{j=1}^m [gcd(i,j)=d] \ 先枚举d再枚举倍数,出现[=1]的形式 \ &=sum_{d=1}^n d sum_{i=1}^{frac{n}{d}} sum_{j=1}^{frac{m}{d}} [gcd(i,j)=1] \ 用sumlimits_{e|n}mu(e) = [n=1]替换 ,先枚举e再枚举倍数\ &=sum_{d=1}^n dsum_{e=1}^n mu(e) frac{n}{de} frac{m}{de} \ 改写求和指标,令D = de \ &= sum_{D=1}^n sum_{d|D} dmu(frac{D}{d}) frac{n}{D} frac{m}{D}\ 发现最后就是 id * mu = varphi \ &= sum_{D=1}^n varphi(D) frac{n}{D} frac{m}{D}\ end{align*} ]

    代码

    int notp[N], p[N];ll varphi[N];
    void sieve(int n) {
        varphi[1]  1;
        for(in i=2; i<=n; i++) {
            if(!notp[i]) p[++p[0]] = i, varphi[i] = i-1;
            for(int j=1; j<=p[0] && i*p[j]<=n; j++) {
                notp[i*p[j]] = 1;
                if(i%p[j] == 0) {varphi[i*p[j]] = varphi[i]*p[j]; break;}
                varphi[i*p[j]] = varphi[i]*(p[j]-1);
            }
        }
        for(int i=1; i<=n; i++) varphi[i] += varphi[i-1];
    }
    ll cal(int n, int m) {
        ll ans=0; int r;
        for(int i=1; i<=n; i=r+1) {
            r = min(n/(n/i), m/(m/i));
            ans += (varphi[r] - varphi[i-1]) * (n/i) * (m/i);
        }
        return ans;
    }
    
  • 相关阅读:
    HDU 5744
    HDU 5815
    POJ 1269
    HDU 5742
    HDU 4609
    fzu 1150 Farmer Bill's Problem
    fzu 1002 HangOver
    fzu 1001 Duplicate Pair
    fzu 1150 Farmer Bill's Problem
    fzu 1182 Argus 优先队列
  • 原文地址:https://www.cnblogs.com/candy99/p/mobius.html
Copyright © 2011-2022 走看看