容斥原理(三元容斥,四元容斥)

本文深入解析容斥原理,探讨其在算法设计中的应用,特别是解决集合问题时的高效计算策略,通过实例讲解如何利用容斥原理求解三、四集合的并集,以及在特定竞赛题目中的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

 

题意:    已知集合A,B,C,  输出三集合的并集。

 

容斥原理(用图解释)

对于求三集合并集的公式:

  A∪B∪C=A+B+C - A∩B - A∩C - B∩C + A∩B∩C

  对于证明,我就简单的叙述一下。

    因为求并集不能将两集合的重复元素进行相加。而 A+B+C  没有考虑重复元素,直接相加,显然这是元素多加的情况,那要还原必须要减去多加的部分,对于上图蓝色部分只加了一次,红色部分加了两次,绿色的部分加了三次,那么我们只需要使他们全部只加一次就能得到正确答案。

所以我们要执行下操作     A+B+C -A∩B + A∩C + B∩C) ,但还不算完美,因为在这里绿色部分被减了三次,要使把绿色部分只减一次,那么要再加上一个绿色部分即可。

 

 

 

对于求四集合并集的公式:

A∪B∪C∪D=A+B+C+D - A∩B - B∩C  -  C∩A -  A∩D  -  B∩D  -  C∩D + A∩B∩C + A∩B∩D  + A∩C∩D  + B∩C∩D  -  A∩B∩C∩D    规律   集合数    奇加偶减

 

对于证明类似于上列三元并集证明。   

 

贴一题目(四元):

  

 
 
给出一个数N,求1至N中,有多少个数不是2 3 5 7的倍数。 例如N = 10,只有1不是2 3 5 7的倍数。
 
输入
输入1个数N(1 <= N <= 10^18)。
输出
输出不是2 3 5 7的倍数的数共有多少。
输入样例
10
输出样例
1

 

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<stack>
#include<algorithm>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define Mem0(x) memset(x,0,sizeof(x))
#define Mem1(x) memset(x,-1,sizeof(x))
#define MemX(x) memset(x,0x3f,sizeof(x))
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f;
const double pi=acos(-1.0);

ll n;
int main()
{
    ll ans=0;
    cin>>n;
    ans=n/2+n/3+n/5+n/7;
    ans=ans-n/6-n/10-n/14-n/15-n/21-n/35+n/30+n/42+n/105+n/70-n/210;
    cout<<n-ans<<endl;
    return 0;
}

 

再贴一题:  (提供链接,就不贴题目了)

https://ac.nowcoder.com/acm/contest/634/C    

 
 
 
解题:
 
  

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<stack>
#include<algorithm>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define Mem0(x) memset(x,0,sizeof(x))
#define Mem1(x) memset(x,-1,sizeof(x))
#define MemX(x) memset(x,0x3f,sizeof(x))
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f;
const double pi=acos(-1.0);


ll l,r,k;
ll prime[500050];
bool check[1000010];
int cnt;
void prim()
{
    memset(check,false,sizeof(check));
    check[0]=check[1]=true;
    cnt=0;
    for (int i=2;i<500000;i++){
        if (!check[i])
            prime[cnt++]=i;
        for (int j=0;j<cnt&&i*prime[j]<1000000;j++){
            check[i*prime[j]]=true;
            if (i%prime[j]==0)
                break;
        }
    }
}
ll a[1000010];
int main()
{
    prim();
    cin>>l>>r>>k;
    ll p=0;//质因数的个数 
    ll tmp=k<<1;
/*    for (int i=0;;i++){
        if (tmp%prime[i]==0){
            a[p++]=prime[i];
            while (tmp%prime[i]==0){
                tmp/=prime[i];
            }
        }
        if (tmp<=1)
            break;
    }*/
    for(int i=2;i*i<=tmp;i++){
        if(!(tmp%i)){
            a[p++]=i;
            while(!(tmp%i))
                tmp/=i;
        }
    }
    if(tmp>1)
        a[p++]=tmp;
    
    ll sum=0;
    tmp=1<<p;//  存在p个质数,则有pow(2,p)种的组合数,
    for (int i=0;i<tmp;i++){
        ll t=1,s=0;   //t是质因数的公倍数,s则为选举的质因数的个数 
        for (int j=0;j<p;j++){
            if (i&(1<<j)){
                s++;
                t*=a[j];
            }
        }
         if(r/t>(l+2*k-1)/t){  //容斥  奇加偶减 
            if(s%2)sum-=r/t-(l+2*k-1)/t;
            else sum+=r/t-(l+2*k-1)/t;
        }        
    }
    cout<<sum<<endl; 
    return 0;
}

 

 

转载于:https://www.cnblogs.com/q1204675546/p/10738964.html

### 三元容斥原理概述 三元容斥原理是一种组合数学工具,用于计算三个集合交集的大小。它基于二元容斥原理扩展而来,适用于更复杂的场景。假设存在三个有限集合 \(A\)、\(B\) 和 \(C\),则它们的并集大小可以通过以下公式表示: \[ |A \cup B \cup C| = |A| + |B| + |C| - |A \cap B| - |A \cap C| - |B \cap C| + |A \cap B \cap C| \] 该公式的推导依赖于加法原则和减法修正的思想[^4]。 --- ### 应用场景分析 #### 场景一:计数问题 在实际应用中,当需要统计满足某些条件的对象数量时,三元容斥原理非常有用。例如,在一组学生中分别有喜欢篮球的学生集合 \(A\)、喜欢足球的学生集合 \(B\) 和喜欢乒乓球的学生集合 \(C\)。如果要找出至少喜欢一种运动的学生人数,则可以直接套用上述公式。 #### 场景二:概率计算 三元容斥原理也可以应用于概率论领域。比如在一个随机实验中,事件 \(A\) 表示某件事情发生的情况,事件 \(B\) 和 \(C\) 同理。通过三元容斥原理可以精确求解至少一个事件发生的概率。 #### 场景三:算法设计 在计算机科学中,特别是在处理复杂查询或优化问题时,三元容斥原理常被用来减少重复计算的影响。例如,在数据库查询过程中涉及多表联结操作时,利用此方法可以帮助估算符合条件的数据量[^2]。 以下是使用 Python 实现的一个简单例子来演示如何运用三元容斥原理解决具体问题: ```python def inclusion_exclusion(A, B, C, AB, AC, BC, ABC): """ 计算三个集合的并集大小。 参数: A, B, C -- 单独集合的大小 AB, AC, BC -- 双重交集的大小 ABC -- 三重交集的大小 返回: 并集大小 """ union_size = A + B + C - AB - AC - BC + ABC return union_size # 示例输入 size_A = 10 size_B = 8 size_C = 7 size_AB = 3 size_AC = 2 size_BC = 4 size_ABC = 1 result = inclusion_exclusion(size_A, size_B, size_C, size_AB, size_AC, size_BC, size_ABC) print(f"The size of the union is: {result}") ``` --- ### 总结 三元容斥原理不仅是一个理论上的重要成果,而且在实践中有广泛的应用价值。无论是解决日常生活中的分类统计还是深入到科学研究和技术开发等领域,都展现了强大的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值