容斥原理


容斥原理

定理

集合S">SS中不具有性质Pi:1im">Pi:1imPi:1≤i≤m的元素个数:
Ai">AiAi为具有性质Pi">PiPi的集合

|S||Ai|+AiAjAiAjAk+...+(1)mA1A2...Am">|S|?|Ai|+Ai?Aj?Ai?Aj?Ak+...+(?1)mA1?A2?...?Am|S|?∑|Ai|+∑Ai?Aj?∑Ai?Aj?Ak+...+(?1)m∑A1?A2?...?Am



项数:(m0)+(m1)+...+(mm)=2m">(m0)+(m1)+...+(mm)=2m(m0)+(m1)+...+(mm)=2m


Proof.">Proof.Proof.
1.">1.1. 没有任何一条性质的元素贡献为1">11
2.">2.2. 有n">nn条性质的元素,在n">nn个集合Ai">AiAi中出现,贡献为(n0)(n1)+(n2)+...+(1)n(nn)=0">(n0)?(n1)+(n2)+...+(?1)n(nn)=0(n0)?(n1)+(n2)+...+(?1)n(nn)=0


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

实质

i=0n(1)i(ni)=[n=0]">i=0n(?1)i(ni)=[n=0]∑i=0n(?1)i(ni)=[n=0]

也就是上面的证明过程



错排

满足ijj">ijjij≠j的排列数

Dn=n!i=0n(1)ii!">Dn=n!i=0n(?1)ii!Dn=n!∑i=0n(?1)ii!

(ni)(ni)! = n!i!">(ni)(n?i)! = n!i!(ni)(n?i)! = n!i! 就是i">i≥i个位置不是错排的方案数,应用容斥原理即可

还有一个递推关系
Dn=nDn1+(1)n">Dn=nDn?1+(?1)nDn=nDn?1+(?1)n


总结

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

= k  k+1 + k+2 ...">= k ? k+1 + k+2 ...= ≥k个 ? ≥k+1个 + ≥k+2个 ...

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

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

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


**update 2017.5.15**

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

我们考虑一个恰好x:xk">x:xkx:x≥k个的方案被统计的次数:

(1)=i=kx(1)ik(ik)(xi)(2)=(xk)i=kx(1)ik(xkxi)(3)=(xk)j=0xk(xkj)(4)=[x==k]">(1)=∑i=kx(?1)i?k(ik)(xi)(2)=(xk)∑i=kx(?1)i?k(x?kx?i)(3)=(xk)∑j=0x?k(x?kj)(4)=[x==k]

哈哈O(∩_∩)O


莫比乌斯反演 Mobius Inversion

说明

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



积性函数

定义

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

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

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


积性函数:φ(n), μ(n)">φ(n), μ(n)φ(n), μ(n)

完全积性函数:

  • 单位函数ϵ(n)=[n=1]">?(n)=[n=1]?(n)=[n=1],

  • 恒等函数id(n)=n">id(n)=nid(n)=n

  • 常函数1(n)=1">1(n)=11(n)=1


狄利克雷卷积

(fg)(n)=d|nf(d)g(nd)">(f?g)(n)=d|nf(d)g(nd)(f?g)(n)=∑d|nf(d)g(nd)

满足交换律结合律对加法的分配律,单位元 ϵ">??


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

计算

  1. 可以O(nlogn)">O(nlogn)O(nlogn)预处理,无脑枚举所有数的倍数
  2. 线性筛
  • i=1, i是质数和i%p[j]!=0的情况很好求
  • 对于i%p[j] == 0,可以通过分析增加一个最小质因子后的变化,或者直接考虑f(pk)">f(pk)f(pk)怎么求,反正积性函数不同质因子都是互质乘起来就行了不影响
  • 也可以筛出最小质因子的次数,分解成f(n)=f(pk)f(npk)">f(n)=f(pk)f(npk)f(n)=f(pk)f(npk),对于f(pk)">f(pk)f(pk)考虑如何计算,带有约数和的可以考虑展开
  • 一些非积性函数也可以通过分析函数的性质也可以用线性筛来求
    例:欧拉函数可以直接根据公式得到如何处理 φ(n)=npi1pi=(pi1)piei1">φ(n)=npi?1pi=(pi?1)?pei?1iφ(n)=n∏pi?1pi=∏(pi?1)?piei?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];
}
1">d(n)=(11)(n)">σ(n)=(1id)(n)">

1">d(n)=(11)(n)">σ(n)=(1id)(n)">
##莫比乌斯函数
μ(1)=1μ(n)=(1)iniμ(n)=0p2|n, p>1">μ(1)=1μ(n)=(?1)iniμ(n)=0p2|n, p>1μ(1)=1μ(n)=(?1)in是i个质数之积μ(n)=0p2|n, p>1 1">d(n)=(11)(n)">σ(n)=(1id)(n)">
μ1=ϵ  d|nμ(d)=[n=1]$$</br>$Proof. $$n$$k$">μ?1=?  d|nμ(d)=[n=1]$$</br>$Proof. $$n$$k$μ?1=?, 即 ∑d|nμ(d)=[n=1]$$。
$Proof. $设$n$有$k$种质因子,

\sum\limits_{d|n}\mu(d) = \sum_{i=0}{k}(-1)i\binom{k}{i}

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





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

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

</br>1.$$φ1=id  n=d|nφ(d),  μid=φ"></br>1.$$φ?1=id  n=d|nφ(d),  μ?id=φ
1.$$φ?1=id 即 n=∑d|nφ(d), 反演后 μ?id=φ

Proof.">Proof.Proof. 考虑列出所有分子in">inin一共n">nn个

  1. i=1n[(n,i)=1]i=[n=1]+nφ(n)2">i=1n[(n,i)=1]?i=[n=1]+n?φ(n)2∑i=1n[(n,i)=1]?i=[n=1]+n?φ(n)2 Proof.">Proof.Proof. (n,i)=(n,ni)">(n,i)=(n,n?i)(n,i)=(n,n?i),除了1和2 互质成对出现,和为n
1">d(n)=(11)(n)">σ(n)=(1id)(n)">

莫比乌斯反演

g(n)=d|nf(d)f(n)=d|nμ(d)g(nd)">g(n)=d|nf(d)f(n)=d|nμ(d)g(nd)g(n)=∑d|nf(d)f(n)=∑d|nμ(d)g(nd)

g=f1f=gμ">g=f?1f=g?μg=f?1→f=g?μ


Proof.">Proof.Proof.
两边都卷上μ1">μ?1μ?1
其他证明方法还有很多,我写这个是因为这个短


另一种形式

g(n)=n|df(n)f(n)=n|dμ(d)g(dn)">g(n)=n|df(n)f(n)=n|dμ(d)g(dn)g(n)=∑n|df(n)f(n)=∑n|dμ(d)g(dn) 1">d(n)=(11)(n)">σ(n)=(1id)(n)">
***

应用

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

d|nμ(d)=[n=1]">d|nμ(d)=[n=1]∑d|nμ(d)=[n=1]

有一些常见技巧:

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

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

栗子

i=1nj=1mgcd(i,j)=d=1ndi=1nj=1m[gcd(i,j)=d]d,[=1]=d=1ndi=1ndj=1md[gcd(i,j)=1]e|nμ(e)=[n=1],e=d=1nde=1nμ(e)ndemdeD=de=D=1nd|Ddμ(Dd)nDmDidμ=φ=D=1nφ(D)nDmD">i=1nj=1mgcd(i,j)d,[=1]e|nμ(e)=[n=1],eD=deid?μ=φ=d=1ndi=1nj=1m[gcd(i,j)=d]=d=1ndi=1ndj=1md[gcd(i,j)=1]=d=1nde=1nμ(e)ndemde=D=1nd|Ddμ(Dd)nDmD=D=1nφ(D)nDmD∑i=1n∑j=1mgcd(i,j)=∑d=1nd∑i=1n∑j=1m[gcd(i,j)=d]先枚举d再枚举倍数,出现[=1]的形式=∑d=1nd∑i=1nd∑j=1md[gcd(i,j)=1]用∑e|nμ(e)=[n=1]替换,先枚举e再枚举倍数=∑d=1nd∑e=1nμ(e)ndemde改写求和指标,令D=de=∑D=1n∑d|Ddμ(Dd)nDmD发现最后就是id?μ=φ=∑D=1nφ(D)nDmD

代码

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;
}





( 转载)