hdu 1796 How many integers can you find 容斥原理

来源:互联网 发布:衬衫品牌 知乎 编辑:程序博客网 时间:2024/04/30 02:26

传送门:hdu 1796 How many integers can you find

题目大意

在M个集合中,找到能被N整除(不包含N)的个数

解题思路

首先要解决这个题目要知道什么容斥定理!
我们先假设N=100,然后M=3其中M集合中的元素为{1,2,3}
如果我们直接计算N/a1 = 100,N/a2=50,N/a3 = 33,在计算前两个的时候,N/a2这么多个元素就是多余的,在计算后面两个的时候我们会发现lcm(a2,a3)中也是公共部分需要减去的!
例子的展示图如下:
这里写图片描述
假设Ai(1<=i<=M)是X的一些子集,我们要求|⋃ Ai|,例如在上面的问题中,就可以看为Ai = {N|N可以整除ai},然后就能的到容斥原理的一般公式
这里写图片描述

容斥原理简单来说就是奇加偶减
偶减是减去任意偶数个集合的交集
奇加是加上任意奇数个集合的交集
上面的两句话就解释了容斥原理那个公式!
我们把M个元素变为1~((1<

long long solve(){    long long res = 0;    for(int i=1; i<(1<<M); i++)    {        int num = 0;        for(int j=i; j!=0; j>>=1) num += j&1;//判断有几个集合        long long lcm = 1;        /*求num个集合的最小公倍数*/        for(int j=0; j<M; j++)            if(i>>j&1)            {                lcm = lcm/gcd(lcm,a[j])*a[j];                if(lcm>N) break;            }        //奇加偶减        if(num%2 == 0)res -= (N/lcm);        else res+=(N/lcm);    }    return res;}

AC代码

#include<cstdio>#include<cstring>int N,M,a[28];long long  gcd(long long a,long long b) //求最大公约数函数{    if (a%b==0) return b;    else return gcd(b,a%b); //辗转相除法}long long solve(){    long long res = 0;    for(int i=1; i<(1<<M); i++)    {        int num = 0;        for(int j=i; j!=0; j>>=1) num += j&1;//判断有几个集合        long long lcm = 1;        /*求num个集合的最小公倍数*/        for(int j=0; j<M; j++)            if(i>>j&1)            {                lcm = lcm/gcd(lcm,a[j])*a[j];                if(lcm>N) break;            }        //奇加偶减        if(num%2 == 0)res -= (N/lcm);        else res+=(N/lcm);    }    return res;}int main(){    while(scanf("%d%d",&N,&M))    {        for(int i=0; i<M; i++)        {            scanf("%d",&a[i]);            if(!a[i])            {                i--;                M--;            }        }        if(N<=2)        {            puts("0");            continue;        }        N--;        printf("%lld\n",solve());    }    return 0;}
0 0
原创粉丝点击