容斥原理 数论

文章目录

原理

S1、S2 、S3 分别代表下图三个圆1、2、3的面积
如果我们想求下面图形构成的面积,该怎么求呢,很简单
S = S1 ∪ S2 ∪ S3=
S1 + S2 + S3
-S1 ∩ S2 - S1 ∩ S3 - S2 ∩ S3
+S1 ∩ S2 ∩ S3
在这里插入图片描述
拓展一下,如果是4个圆的面积应该是
S =S1 ∪ S2 ∪ S3 ∪ S 4 =

S1 + S2 + S3 + S4

-S1 ∩ S2 - S1 ∩ S3 - S1 ∩ S4 - S2 ∩ S3 - S2 ∩ S4 - S3 ∩ S4

+S1 ∩ S2 ∩ S3 + S1 ∩ S2 ∩ S4 + S1 ∩ S3 ∩ S4 + S2 ∩ S3 ∩ S4

-S1 ∩ S2 ∩ S3 ∩ S4

可以发现规律 ,S1 ∪ S2 ∪ … ∪ S n = ( ∑ i = 1 n \sum_{i=1}^n i=1nSi) - ( ∑ i , j = 1 n \sum_{i,j=1}^n ij=1n Si ∩ Sj) + ( ∑ i , j , k = 1 n \sum_{i,j,k=1}^n ijk=1n Si ∩ Sj ∩ Sk) -…+ ((-1)n-1 ∑ i , j , k . . . . = 1 n \sum_{i,j,k....=1}^n ijk....=1n Si ∩ Sj ∩ Sk ∩…∩ Sn)

上面的是用面积来考虑,如果我们用集合来考虑的话, 若 |S| 代表3个集合并集元素的个数,则:

|S| = |S1 ∪ S2 ∪ S3|=
|S1| + |S2| + |S3|
-|S1 ∩ S2| - |S1 ∩ S3| - |S2 ∩ S3|
+|S1 ∩ S2 ∩ S3|

设 n 个集合并集的元素个数为 |S1 ∪ S2 ∪ … ∪ S n|

那么,|S1 ∪ S2 ∪ … ∪ S n| = ( ∑ i = 1 n \sum_{i=1}^n i=1n|Si|) - ( ∑ i , j = 1 n \sum_{i,j=1}^n ij=1n| Si ∩ Sj|) + ( ∑ i , j , k = 1 n \sum_{i,j,k=1}^n ijk=1n |Si ∩ Sj ∩ Sk|) -…+ ((-1)n-1 ∑ i , j , k . . . . = 1 n \sum_{i,j,k....=1}^n ijk....=1n |Si ∩ Sj ∩ Sk ∩…∩ Sn|) ,这就是容斥原理的公式

很容易发现,如果某一项包含奇数个集合时,那么它的符号就是"",反之,某一项包含偶数个集合时,它的符号就是"-"。


证明

为什么容斥原理是对的呢?
不妨设一个元素 x(x ∈ S1 ∪ S2 ∪ … ∪ S n) 出现在了 k (1≤ k ≤n)个集合中,那么 x 一共会被算C ( 1 k ) \tbinom{1}{k} (k1) - C ( 2 k ) \tbinom{2}{k} (k2) + C ( 3 k ) \tbinom{3}{k} (k3) - C ( 4 k ) \tbinom{4}{k} (k4) + … + (-1)k-1C ( k k ) \tbinom{k}{k} (kk),这个式子是恒等于 1 的(可以证明)。所以,任意 1 个元素 x 只被加了一次,所以说容斥原理是正确的

上面已经知道计算 3 个集合的并集的元素个数的式子有 7 项,计算4 个集合并集的元素个数的式子有 15 项。

大胆猜测一下,计算 n 个集合的并集的元素个数的式子一共有 2n - 1 项。

证明:
C ( 0 n ) \tbinom{0}{n} (n0) + C ( 1 n ) \tbinom{1}{n} (n1) + C ( 2 n ) \tbinom{2}{n} (n2) + C ( 3 n ) \tbinom{3}{n} (n3) + … + C ( n n ) \tbinom{n}{n} (nn) = 2n

①等式右边代表从 n 个数中选任意多个数的方案数,因为第一个数选或不选有两种方案,第二个数选或不选两种方案,第三个数…第n个数…总共 2n
②等式左边代表从 n 个数中选 0 个数的方案数 + 从 n 个数中选 1 个数的方案数 + … +从 n 个数中选 n 个数的方案数。

很明显,①②两者的意义是相同的,所以等号成立。

C ( 1 n ) \tbinom{1}{n} (n1) + C ( 2 n ) \tbinom{2}{n} (n2) + C ( 3 n ) \tbinom{3}{n} (n3) + … + C ( n n ) \tbinom{n}{n} (nn) = 2n - 1,得证


例题

在这里插入图片描述
样例:

1、2、3、4、5、6、7、8、9、10,质数p={2、3}
2 的倍数的有S2 = {2、4、6、8、10} 5个
3 的倍数的有S3 = {3、6、9} 3个
既是 2 的倍数,也是 3 的倍数的有 S2 ∩ S3 = {6} 1个

所以,5 + 3 - 1 = 7 个

那么,1~n 中 p 的倍数的个数怎么求呢?
答: n/p
既是 pi 的倍数,也是 pj 和 pk 的倍数的个数是 n/pipjpk

思路:二进制,已知共有 2m - 1 项,每一项所包含的质数都不同,我们可以用 1~2m-1 这 2m - 1 个数,来表示不同的项,每个数都转换成 m 位二进制数后,这 m 位就分别代表着 m 个质数是否包含,1代表包含,0代表不包含

AcWing 890. 能被整除的数

#include<iostream>
using namespace std;
typedef long long LL;
const int N = 20;
int n,m;
int p[N];

int main()
{
	cin >> n >> m;
	for(int i = 0; i < m; i++) cin >> p[i];
	
	int res = 0;
	for(int i = 1; i< 1 << m; i++) // 1~2^m-1这些数代表2^m-1个不同的项
	{
	    int t = 1, cnt = 0; //cnt代表当前枚举的项中包含集合的个数 
		for(int j=0; j<m; j++)//看这个项的第 j 位是否包含,1代表包含,0代表不包含 
		   if(i >> j & 1) //选 
		   {
			  if((LL)t * p[j] > n) //此时 n/t = 0,直接break即可 
			  {
			  	 t = -1;
			  	 break;
			  }	
			  cnt++;
			  t *= p[j];
		   }	
		if(t != -1)
		{
			if(cnt % 2) res += n/t; //加奇数项的个数 
			else res -= n/t; //减偶数项的个数 
		}		
	} 
	cout << res;
}

时间复杂度:O(2^m * m)


  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值