容斥原理

一、容斥原理

  在计数时,要保证无一重复,无一遗漏。为了使重叠部分不被重复计算,在不考虑重叠的情况下,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理。

  1.容斥原理1——两个集合的容斥原理

  如果被计数的事物有A、B两类,那么,先把A、B两个集合的元素个数相加,发现既是A类又是B类的部分重复计算了一次,所以要减去。如图所示:

  公式:A∪B=A+B-A∩B

总数=两个圆内的-重合部分的

2.容斥原理2——三个集合的容斥原理

  如果被计数的事物有A、B、C三类,那么,将A、B、C三个集合的元素个数相加后发现两两重叠的部分重复计算了1次,三个集合公共部分被重复计算了2次。

  如图所示,灰色部分A∩B-A∩B∩C、B∩C-A∩B∩C、C∩A-A∩B∩C都被重复计算了1次,黑色部分A∩B∩C被重复计算了2次,因此总数A∪B∪C=A+B+C-(A∩B-A∩B∩C)-(B∩C-A∩B∩C)-(C∩A-A∩B∩C)-2A∩B∩C=A+B+C-A∩B-B∩C-C∩A+A∩B∩C。即得到:

  公式:A∪B∪C=A+B+C-A∩B-B∩C-C∩A+A∩B∩C

总数=三个圆内的-重合两次的+重合三次的

上面只是简单介绍一下容斥原理,那么代码如何写呢
就可以看看一篇讲的比较好的博客,里面有具体的实现方法还包括欧拉函数和抽屉原理的讲解。
点击打开博客http://blog.csdn.net/qq_36368339/article/details/70217849

附上两个实际的例子:
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1284

我只是单纯的应用到了这个原理,代码写得有点直接。

正确代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL maxn=1e18;
int main()
{
    LL n;
    while(~scanf("%lld",&n))
    {
        LL a,b,c,d,ab,ac,ad,bc,bd,cd,abc,acd,abd,bcd,abcd;//15
        a=n/2;
        b=n/3;
        c=n/5;
        d=n/7;
        ab=n/6;
        ac=n/10;
        ad=n/14;
        bc=n/15;
        bd=n/21;
        cd=n/35;
        abc=n/30;
        acd=n/70;
        abd=n/42;
        bcd=n/105;
        abcd=n/210;
        abc=abc-abcd;//仅包括同时能被2,3,5整除的数,下面得到的结果依次类推
        abd=abd-abcd;
        acd=acd-abcd;
        bcd=bcd-abcd;
        ab=ab-(abc+abd+abcd);
        ac=ac-(abc+acd+abcd);
        ad=ad-(abd+acd+abcd);
        bc=bc-(abc+bcd+abcd);
        bd=bd-(abd+bcd+abcd);
        cd=cd-(acd+bcd+abcd);
        a=a-(ab+ac+ad+abc+abd+acd+abcd);
        b=b-(ab+bc+bd+abc+abd+bcd+abcd);
        c=c-(ac+bc+cd+abc+acd+bcd+abcd);
        d=d-(ad+bd+cd+abd+acd+bcd+abcd);
        LL ans;
        ans=n-(a+b+c+d+ab+ac+ad+bc+bd+cd+abc+abd+acd+bcd+abcd);//此时的各部分之间没有重叠
        printf("%lld\n",ans);
    }
    return 0;
}

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6106
容斥原理

正确代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,maxn=-1;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            int a,b,c,d,e,f,g,ab,bc,ac,abc;
            scanf("%d%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f,&g);
            //接下来的操作将各部分之间重复的排除
            d-=g;//ab
            e-=g;//bc
            f-=g;//ac
            a=a-(d+f+g);
            b=b-(d+e+g);
            c=c-(e+f+g);
            if(a<0||b<0||c<0||d<0||e<0||f<0||g<0)//判断数据是否有误
                continue;
            int s=a+b+c+d+e+f+g;
            if(s>maxn)
               maxn=s;
        }
        printf("%d\n",maxn);
    }
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
容斥原理是一种计数方法,用于解决集合中某些对象的数目的问题。它的基本思想是先计算包含于某个内容中的所有对象的数目,然后排除重复计算的对象,以确保计数结果既不遗漏又没有重复。在容斥原理的应用中,通常需要先求出所有包含的区间,然后使用欧拉函数求和,并进行一些补充操作,例如乘以某个系数或减去一个常数。在使用容斥原理时,需要注意一些细节,例如在枚举因子时要注意使用最小公倍数(LCM),而不是直接相乘。如果容斥问题中的集合可能包含0,还需要特殊处理。至于如何使用容斥原理在MATLAB中求解具体的问题,我需要更多的上下文信息才能给出具体的指导。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [容斥原理](https://blog.csdn.net/ling_wang/article/details/80488797)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [容斥原理练习记录](https://blog.csdn.net/z631681297/article/details/81318279)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值