UPC(混合5)问题 E: 数学难题

标签:容斥原理

一、知识梳理

(一)定义:
如果被计数的事物有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 - B∩C - C∩A + A∩B∩C)
(二)公式:
两个集合的容斥关系公式:A∪B =|A∪B| = |A|+|B| - |A∩B |(∩:重合的部分)
三个集合的容斥关系公式:|A∪B∪C| = |A|+|B|+|C| - |A∩B| - |B∩C| - |C∩A| + |A∩B∩C|
(三)韦恩图:
在这里插入图片描述
(具体证明过程可以参见百度百科或者博客:https://blog.csdn.net/lxt_lucia/article/details/81066272)

二、实战训练

时间限制: 1 Sec 内存限制: 128 MB
题目描述
学佛Fife最喜欢Bemy上的数学课了。因为他可以在数学课上尽情的蒸发学水~
Bemy为了不让学佛Fife过度骄傲,以保证每一个学水都能不被他影响,自信地不断地进步,给Fife一个有挑战性的数学题。
因为Fife不想让妹子Maze等得太久,决定把这道题交给你。

题目是这样的:有一个表达式(B+E+S+S+I+E)(G+O+E+S)(M+O+O)
其中B,E,S,I,G,O,M为七个变量(注意“O”是变量不是0)。
对于每个变量,Bemy会告诉Fife这个变量所代表的各个可能值。
Bemy想问问Fife这样一个问题:原表达式有多少种可能的情况,使表达式的值为偶数。(只要有一个变量的值不同,即为一种情况)

输入
第一行输入包含一个整数N。
下一个N 行每行包含一个变量名称和一个这个变量可以使用的值。
注:每个变量在整张表中不会出现多于20 次。
同一个变量不存在两个相同的值。所有给出的值都在-300……300 之间。

输出
打印出一个整数,表示有多少种方法使表达式的值为一个偶数。
样例输入

10
B 2
E 5
S 7
I 10
O 16
M 19
B 3
G 1
I 9
M 2

样例输出 Copy

6

提示
样例解释
(B,E,S,I,G,O,M)=(2,5,7,10,1,16,19)->53,244
=(2,5,7,10,1,16,2)->35,496
=(2,5,7,9,1,16,2)->34,510
=(3,5,7,10,1,16,2)->36,482
=(3,5,7,9,1,16,19)->53,244
=(3,5,7,9,1,16,2)->35,496
【数据规模】
对于30%的数据,N<=60。
对于100%的数据,N<=140。

我们初中就已经学过了奇数和偶数的相关知识,不妨跟着笔者来回顾一下
设a为奇数,b为偶数;
a = xy,b=st(乘号省略)
很容易得出:x和y均为奇数;s和t中至少有一个是偶数。
那么回到题目
(B+E+S+S+I+E)(G+O+E+S)(M+O+O) ,不妨记这三部分为a,b,c,要使abc是偶数,那么三者中至少一个偶数。
然后再看每一部分,(B+E+S+S+I+E),2E和2S一定是偶数,相加也是偶数,所以2E和2S对这个式子的奇偶性不起决定性作用,所以只要看(B+I)即可,同理,c也可以化简为M。
综上:abc=(B+I)(G+O+E+S)M
接下来应用容斥原理,先求出a、b、c所有的组合数,再求出a、b、c为偶数的情况,下面用语言描述一下公式
(稍微有点复杂,可能直接看代码容易理解)
abc为偶数=a为偶数xb种数xc种数+a种数xb为偶数xc种数+a种数xb种数xc为偶数-a为偶数xb为偶数xc种数-a为偶数xb种数xc为偶数-a种数xb为偶数xc为偶数+a为偶数xb为偶数xc为偶数。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <ctime>
#include <ctype.h>
#define ll long long
#define local
#define inf 0x3f3f3f3f
using namespace std;
const int N = 1005;
const int mod = 1e9 + 7;
int n,t;
char c;
int bi=0,ei=0,si=0,ii=0,gi=0,oi=0,mi=0;
int b[20],e[20],s[20],i[20],g[20],o[20],m[20];
int main()
{
#ifdef local
    freopen("input.txt","r",stdin);
#endif
    scanf("%d",&n);
    while(n--)
    {
        scanf(" %c",&c);
        scanf("%d",&t);
        if(c=='B')
            b[bi++]=t;
        else if(c=='E')
            e[ei++]=t;
        else if(c=='S')
            s[si++]=t;
        else if(c=='I')
            i[ii++]=t;
        else if(c=='G')
            g[gi++]=t;
        else if(c=='O')
            o[oi++]=t;
        else if(c=='M')
            m[mi++]=t;

    }
    int t1=gi*oi*ei*si;
    int t2=bi*ii;
    int t3=mi;
    int num1=0,num2=0,num3=0;
    //printf("%d %d %d\n",bi,ii,mi);
    for(int i1=0; i1<gi; i1++)
    {
        for(int j=0; j<oi; j++)
        {
            for(int k=0; k<ei; k++)
            {
                for(int l=0; l<si; l++)
                {
                    if((g[i1]+o[j]+e[k]+s[l])%2==0)
                        num1++;
                }
            }
        }
    }
    for(int k=0; k<bi; k++)
    {
        for(int j=0; j<ii; j++)
        {
            if((b[k]+i[j])%2==0)
                num2++;
        }
    }
    for(int k=0; k<mi; k++)
        if(m[k]%2==0)
            num3++;
    //(A∪B∪C = A+B+C - A∩B - B∩C - C∩A + A∩B∩C)
    int ans=num1*t2*t3+t1*num2*t3+t1*t2*num3-t1*num2*num3-num1*t2*num3-num1*num2*t3+num1*num2*num3;
    printf("%d",ans);
    return 0;
}

参考:
【1】百度百科;
【2】https://blog.csdn.net/lxt_lucia/article/details/81066272

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值